Python-JS事件與面向物件操作
阿新 • • 發佈:2018-12-24
目錄
一、函式高階
迴圈繫結:
使用迴圈繫結會出現的問題及解決方案:
二、面向物件
3、建構函式(ES5)
三、JS選擇器
1、getElement系列(最嚴謹)
2、querySelector系列(最方便)
3、通過id名直接獲取
4.JS中操作頁面標籤全域性屬性,對映到HYML中
四、JS中的事件(基礎)
五、 JS處理操作頁面:
1.操作頁面內容:
2.操作頁面樣式
這篇部落格我們先將上篇部落格中沒有介紹完的函式部分介紹完,然後再介紹函式高階
一、函式高階
1、函式回撥
函式回撥的本質:在一個函式中(呼叫函式),當滿足一定條件,呼叫引數函式(回撥函式)
回撥函式作為呼叫函式的引數傳入
回撥函式通過引數將呼叫還是內部資料傳出
// 回撥的函式
function callback(data) {}
// 邏輯函式
function func(callback) {
// 函式回撥
if (callback) callback(data);
}
2、閉包函式
什麼是閉包: 區域性的函式 (被一個函式包裹的函式)
為什麼使用閉包:
1.一個函式要使用另一個函式的區域性變數
2.閉包會持久化包裹自身的函式的區域性變數
3.解決迴圈繫結
閉包目的:不允許提升變數作用域時,該函式的區域性變數需要被其他函式使用
閉包本質:函式的巢狀,內層函式稱之為閉包
閉包的解決案例:①影響區域性變數的生命週期,持久化區域性變數;②解決變數汙染
閉包的模板示例:
function outer() {
var data = {}
function inner() {
//1.在inner函式中,使用了outer的區域性變數num
return data;
}
return inner;
}
//2.藉助閉包,將區域性變數data的生命週期提升了
var innerFn=outer()
var data=innerFn()
迴圈繫結:
.html檔案
<ul>
<li>列表項</li>
<li>列表項</li>
<li>列表項</li>
</ul>
迴圈繫結:
.js檔案
var lis = document.querySelector('li');
for (var i = 0; i < lis.length; i++) {
lis[i].onclick = function () {
// 列印列表項的索引
console.log(i);
}
}
使用迴圈繫結會出現的問題及解決方案:
出現的問題: 變數汙染
例如:
在這裡使用var來迴圈繫結的時候,沒有辦法產生區域性作用域,所以每次產生的i值都會被下一次的新i值所替代,就會導致每個塊的點選事件中的i值都是一樣的,也就是每個點選事件的序號或者說index都是一樣的,這就是我們所說的變數汙染
for (var i = 0; i < divs.length; i++) {
// i = 0 | 1 | 2 | 3
// 迴圈繫結
divs[i].onclick = function () {
console.log("***", i)
}
}
// i = 3
console.log(">>>", i);
解決方案:
1.獲取區域性作用域(塊級作用域)解決
使用塊級作用域來解決變數汙染的問題, 原理就是使得每次迴圈都產生新的塊級作用域, 在本次迴圈中的i值只在產生它的作用域中能夠被訪問到, 在作用域外面是訪問不到的, 這就解決了每次i 的值都被覆蓋的情況, 採用這種辦法可以解決變數汙染的問題
for (let i = 0; i < divs.length; i++) {
// {i=0 <= i} {i=1 <= i} {i=2 <= i}
// i = 3
// 迴圈繫結
divs[i].onclick = function () {
console.log("***", i)
}
} // for執行結束, i=3會被銷燬
console.log(">>>", i)
2.利用閉包解決迴圈繫結中的變數汙染問題
// 使用閉包解決變數汙染的格式一(比較明瞭)
for (var i = 0; i < divs.length; i++) {
(function () {
var index = i;
divs[index].onclick = function () {
console.log("###", index)
}
})()
// 使用閉包解決變數汙染的格式二(格調高一點)
/*
(function (index) {
divs[index].onclick = function () {
console.log("###", index)
}
})(i)
*/
// 使用閉包解決變數汙染的格式三(格局更明顯)
/*
(function (i) {
divs[i].onclick = function () {
console.log("###", i)
}
})(i)
*/
}
3.利用標籤屬性解決
在迴圈的時候直接將本次迴圈的 i 值新增給標籤的index屬性, 這樣每次迴圈都能給不同的標籤新增不同的 i 值,從而進行區分 解決變數汙染的問題
for (var i = 0; i < divs.length; i++) {
divs[i].index = i;
divs[i].onclick = function () {
// console.log("###", i)
console.log(this.index)
}
}
二、面向物件
物件: 特徵與行為的結合體, 是一個具象的實體
JS物件語法:
//單一物件
var obj={
// 屬性(以key="value"的形式存在)
name:"Zero",
// 方法
teach:function(){
console.log("教學");
}
}
// 物件使用屬性與方法, 採用.語法
console.log(obj.name);
obj.teach();
1、屬性與方法(都是以key:"value"的形式存在的)
1.1 key的型別為字串型別
在訪問的時候,可以使用下面兩種方式: obj.key | obj["key"]
js支援的識別符號可以省略引號,反之不可以省略, 不支援的識別符號訪問方式: 不可以採用點語法,需要採用[ ]語法, eg: obj["background-color"]
var obj = {
name: "name",
"person-age": 18
}
// 訪問
obj.name | obj["name"]
obj.["person-age"]
1.2 物件可以任意新增或刪除屬性
拓展: 獲取的頁面元素就是標籤物件, 可以對其新增任意屬性
var obj = {}; | var obj = new Object();
// 屬性
obj.prop = "";
// 方法
obj.func = function () {}
// 刪除屬性與方法
delete obj.prop
delete obj.func
// 新增
obj.age = 18 //如果age的key已存在就是修改, 不存在就是新增鍵值對, 新增的key任意
// 注: 獲取的頁面元素(標籤物件)也可以任意新增/刪除 屬性
2、類字典結構使用
結構
var dict = {name: "zero", age: 18}
拓展
var dict = {"my-name": "zero", fn: function () {}, fun () {}}
使用
dict.name | dict["my-name"] | dict.fn()
3、建構函式(ES5)
宣告與普通函式一樣,只是函式採用大駝峰體命名規則
建構函式內部屬性方式不同於普通函式
ES5中還沒有引入類的概念, 所以使用建構函式來模擬類的存在
我們目前一般都是使用ES5中的建構函式來當做類的使用
function People(name, age) { //類似於python中的類來使用
this.name = name; //this代表 Person建構函式例項化出的所有具體物件中的某一個
this.age = age;
this.eat = function () {
return 'eat';
}
}
如何使用建構函式中的屬性與方法
//1.通過建構函式例項化出具體物件
//2.通過物件.語法呼叫屬性與方法
var p1 = new Person('allen',18);
var p2 = new Person('eric',19);
console.log(p1.name)
console.log(p2.name)
p1.eat();
p2.eat();
4、繼承(ES5)
定義一個父級
// 父級
function Sup(name) {
this.name = name;
this.fn = function () {
console.log('fn class');
}
}
// 原型
console.log(Sup.prototype);
console.log(sup.__proto__);
// 子級
function Sub(name) {
// 繼承屬性
Sup.call(this, name);
}
// 繼承方法
Sub.prototype = new Sup;
// 建立子級物件
var sub = new Sub("subClass");
// 使用屬性
console.log(sub.name);
// 使用方法
sub.fn();
// 指向自身建構函式
Sub.prototype.constructor = Sub;
5、類及繼承(ES6)
// 父類
class People {
// 構造器: 完成物件的宣告與初始化
// 屬性在構造器中宣告並完成初始化
constructor (name, age) {
this.name = name;
this.age = age;
}
// 類中規定例項方法
eat () {
console.log('吃吃吃');
}
// 類方法: 給類使用的
static create () {
console.log('誕生');
}
}
// 子類(使用extends繼承父類)
class Student extends People {
constructor (name, age) {
// super關鍵詞
super(name, age)
}
}
ES6中類的使用:
//1.例項化類的物件
let p1=new People('嘿嘿');
//2.使用屬性與方法
console.log(p1.name)
p1.eat()
ES6中的類方法介紹:
類方法一般是由類來直接進行呼叫的,不建議使用由類例項化出的物件來呼叫,因為一般類方法都是一些功能類(工具類)的方法
class Tool { // 功能類(工具類)中的方法都定義為類方法
static max (num1, num2) {
return num1 > num2 ? num1 : num2;
}
}
// 通過Tool類來求兩個數中的大值, 需要Tool類的物件出現嗎? 不需要 => 功能有類直接使用
console.log(Tool.max(666, 888));
JS中的主動拋異常
throw "自定義異常";
onsole.log("上面如果出現了異常, 邏輯將會被強制停止,後邊的程式碼不會被執行");
var num = 10 / 0;
console.log(num)
三、JS選擇器
什麼是js選擇器: 將js與html建立起連線
js中一般稱標籤為頁面元素
我們這小節中涉及到的幾個物件名詞的範圍大小:
window > document > html > body
window不僅包括顯示頁面中的所有內容,還包括視窗上方的內容
所有顯示頁面中的內容(展現給使用者 看的),都是屬於文件(document)物件的內容,包括<!doctype html>
在文件中(document)中出現的所有內容都是document中的節點
HTML包括html標籤內的所有內容
body包括bady標籤內的所有內容
節點(瞭解):在文件(document)中出現的所有內容都是document中的節點
節點(node): 標籤節點(元素element) | 註釋節點 | 文字節點 | <!doctype>節點
標籤節點指的是一個完整的標籤
文字節點指的是標籤之間的空白符合字元(包括兩個標籤之間的空白符)
1、getElement系列(最嚴謹)
該選擇器是動態的: 當元素有變化時,會自動識別
獲取文件中的標籤 => document物件通過點語法去獲取具體的目標標籤元素
getElement選擇標籤的方法:
1.通過id名獲取頁面中出現的第一個唯一滿足條件的頁面元素
該方法只能由document呼叫
原因: 我們要保證一個文件中一個id只能出現一次,doctument檢索的就是文件
而某父級標籤只能檢索自身內部區域,doctument可以保證文件中只能是一個id,而父級標籤只能檢索自身標籤內部區域,documtnt可以保證文件中自身內部id不重複,能不能保證與外界不重複?
答案是不能的, 所以從安全形度出發,獲取唯一物件的getRlementByID方法只能由能確定唯一id的物件來呼叫,能被document呼叫,不能被sup來呼叫
var body = document.getElementById('id名');
console.log(body)
2、通過class名獲取所有滿足條件的頁面元素
該方法可以由document及任意頁面元素物件呼叫
返回值為HTMLCollection (一個類陣列結果的物件,使用方式同陣列)
沒有匹配到任何結果返回空HTMLCollection物件 ([])
取到列表之後可以使用索引來取到我們需要的相應元素
var divs = document.getElementsByClassName('class名');
console.log(divs)
3.通過tag(標籤)名獲取所有滿足條件的頁面元素
該方法可以由document及任意頁面元素物件呼叫
返回值為HTMLCollection (一個類陣列結果的物件,使用方式同陣列)
沒有匹配到任何結果返回空HTMLCollection物件 ([])
取到列表之後可以使用索引來取到我們需要的相應元素
document.getElementsByTagName('tag名');
2、querySelector系列(最方便)
引數裡邊是採用css選擇器的語法
對id檢索是不嚴謹的
querySelector選擇標籤的方法:
1.獲取第一個匹配到的頁面元素
該方法可以由document及任意頁面物件呼叫/
var div = document.querySelector('css語法選擇器');
console.log(div)
2.獲取所有匹配到的頁面元素(檢索所有滿足結果)
該方法可以由document及任意頁面物件呼叫
返回值為NodeList (一個類陣列結果的物件,使用方式同陣列)
取到列表之後可以使用索引來取到我們需要的相應元素
沒有匹配到任何結果返回空NodeList物件 ([])
引數中也是採用css選擇器的語法
var divs = document.querySelectorAll('css語法選擇器');
console.log(divs)
3、通過id名直接獲取
可以通過id名直接獲取對應的頁面元素物件,但是不建議使用
如使用console.log(id名)可以直接進行列印
4.JS中操作頁面標籤全域性屬性,對映到HYML中
// 獲取頁面標籤ele的alert全域性屬性的值,如果沒有該全域性屬性結果為null
ele.getAttribute("alert")
ele.setAttribute("att_key","attr_value");
//頁面標籤ele已有該全域性屬性,就是修改值, 沒有就是新增該全域性屬性並賦相應值
注: 一般應用場景,結合css的屬性選擇器完成樣式修改
四、JS中的事件(基礎)
什麼是事件: 頁面標籤在滿足某種條件下可以完成指定功能的這種過程,稱之為事件
某種條件: 如滑鼠點選標籤: 單擊事件 | 滑鼠雙擊標籤: 雙擊事件 | 滑鼠懸浮標籤: 懸浮事件 | 鍵盤按下: 鍵盤按下事件
指定功能: 開發者根據實際需求完成相應的功能實現
鉤子函式: 就是滿足某種條件被系統回撥的函式(完成指定功能)
點選事件: 明確啟用鉤子的條件= 啟用鉤子後該處理什麼邏輯指定完成功能
事件使用簡單案例:
var div = document.querySelector(".div"); // 找到的是第一個.div
div.onclick = function () {
// alert(123)
this.style.backgroundColor = "pink";
}
// 明確第一個及第二個
var divs = document.querySelectorAll('.div');
divs[1].ondblclick = function () {
divs[0].style.backgroundColor = "yellow";
}
事件使用案例:(事件控制標題欄)
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>js事件控制標題欄</title>
<style>
.part1 div {
width: 100px;
height: 30px;
text-align: center;
line-height: 30px;
float: left;
cursor: pointer;
}
.part1 {
overflow: hidden;
}
h2 {
height: 30px;
}
</style>
</head>
<body>
<div class="part1">
<div class="b1">標題欄</div>
<div class="b2">標題欄</div>
<div class="b3">標題欄</div>
<div class="b4">標題欄</div>
</div>
<h2></h2>
</body>
</html>
第一種方式:使用事件一步一步實現
<script>
var b1 = document.querySelector('.b1');
// 滑鼠懸浮事件
b1.onmouseenter = function () {
console.log("滑鼠懸浮上了");
// 懸浮上後,該標籤的字型顏色變化橘色
this.style.color = "#FF6700";
}
// 需求並非為滑鼠移走,去除顏色
b1.onmouseleave = function () {
this.style.color = "#000";
}
</script>
第二種方式:
使用迴圈繫結的方式進行多個標題的控制
在這裡使用var和let進行迴圈繫結時的區別:
var是沒有塊級作用域的概念的,也就是說在這裡使用var進行迴圈繫結,i 的值在迴圈外邊也是可以訪問的,在迴圈的時候就會不斷被修改,在本題中,i 的值最終會被修改為4
使用let的時候let具有塊級作用域的概念,在每次迴圈都是會產區域性作用域的,在區域性作用域中產生的變數,在外部不能被訪問的,所以使用了let之後,每次迴圈 i 的值都是新的,這就簡單解決了變數汙染的問題
在這裡還要注意在JS中函式的定義和呼叫不是嚴格遵守先定義後呼叫的原則的, 它交給瀏覽器解析的時候會有一個編譯過程,會將文件中產生的所有名稱存放起來,所以在函式定義的上邊進行函式的呼叫也是沒有問題的,在編譯過程結束之後才會執行函式裡邊的程式碼體
<script>
// 製作資料
var data = ["標題1", "標題2", "標題3", "標題4"];
var divs = document.querySelectorAll('.part1 div');
console.log(divs);
// 迴圈繫結 => 會出現變數(i)汙染
for (let i = 0; i < divs.length; i++) {
divs[i].onmouseenter = function () {
// 列印自身索引值
console.log(i);
// 將自身顏色變為橘色,其他兄弟顏色變為黑色
// 就是i為橘色, 非i為黑色
changeColor(i);
// 懸浮內容
changeContent(i)
}
}
// console.log(i);
// 自定義的修改顏色的方法
function changeColor(index) {
for (let i = 0; i < divs.length; i++) {
// 先不管三七二十一,全改成黑色
divs[i].style.color = "black";
// 如果是目標選中標籤,它的顏色再重新設定為橘色
if (i == index) {
divs[i].style.color = "#FF6700";
}
}
}
var h2 = document.querySelector('h2');
// 修改內容
function changeContent(index) {
h2.innerText = data[index];
}
</script>
五、 JS處理操作頁面:
在進行頁面操作之前,必須要先獲取頁面元素:
比如我們通過類名獲取元素:
var d1 = document.querySelector('.d1');
var d2 = document.querySelector('.d2');
var d3 = document.querySelector('.d3');
1.操作頁面內容:
innerText是獲取文字內容的
box.innerText
可以設值, 也可以獲取值
var text = d1.innerText;
// 獲取內容
console.log(text);
// 修改(刪除)內容
d1.innerText = "";
d1.innerText = "修改後的文字內容";
讀寫 style屬性 樣式
d1.style.backgroundColor = 'red';
// 1.操作的為行間式
// 2.可讀可寫
// 3.具體屬性名採用小駝峰命名法
② 操作標籤內容
box.innerHTML
可以設值, 也可以獲取值, 能解析html語法程式碼
box.outerHTML
獲取包含自身標籤資訊的所有子內容資訊
// 獲取
var html = d2.innerHTML;
console.log(html)
// 修改
d2.innerHTML = "<b>加粗的文字</b>"; // 可以解析html語法的程式碼
// d2.innerText = "<b>加粗的文字</b>";
// 瞭解
console.log(d2.innerHTML); // 只是標籤內部的子標籤與子內容
console.log(d2.outerHTML); // 不僅包含標籤內部的子標籤與子內容,還包含自身標籤資訊
2.操作頁面樣式
1.獲取 頁面樣式
var bgColor = d3.style.backgroundColor; // 只能獲取行間式
console.log(bgColor);
2. 修改
d3.style.backgroundColor = "yellow"; // 只能修改行間式
行間式的我們可以進行修改了,那問題就來了
問題: 那用內聯外聯設定的樣式如何獲取?
內聯與外聯設定的樣式叫: 計算後樣式
getComputedStyle(目標標籤, 偽類(null填充)).具體的樣式
bgColor = window.getComputedStyle(d3, null).backgroundColor; // 相容性較差
console.log(bgColor);
// 可以獲取計算後樣式, 也可以獲取行間式, 但它為只讀
bgColor = getComputedStyle(d3, null).getPropertyValue('background-color'); // 相容性較好
console.log(bgColor);
// 一些不常用的屬性會出現瀏覽器之間的相容問題, 通過新增字首來處理
console.log(d3.style);
// chrome: -webkit-
// ie: -ms-
// opera: -o-
// eg: 背景顏色
// 推薦
getComputedStyle(頁面元素物件, 偽類).getPropertyValue('background-color');
// 不推薦
getComputedStyle(頁面元素物件, 偽類).backgroundColor;
// IE9以下
頁面元素物件.currentStyle.getAttribute('background-color');
頁面元素物件.currentStyle.backgroundColor;
// 1.頁面元素物件由JS選擇器獲取
// 2.偽類沒有的情況下用null填充
// 3.計算後樣式為只讀
// 4.該方式依舊可以獲取行間式樣式 (獲取邏輯最後的樣式)
操作樣式小結:
box.style.樣式名 ==> 可以設值,也可以獲取,但操作的只能是行間式
getComputedStyle(box, null).樣式名 ==> 只能獲取值,不能設值, 能獲取所有方式設定的值(行間式 與 計算後樣式)
注: 獲取計算後樣式,需要關注值的格式
結合 css 操作樣式
頁面元素物件.className = ""; // 清除類名
頁面元素物件.className = "類名"; // 設定類名
頁面元素物件.className += " 類名"; // 新增類名
---------------------
原文:https://blog.csdn.net/Onion_cy/article/details/85101977