1. 程式人生 > >Python-JS事件與面向物件操作

Python-JS事件與面向物件操作

目錄
一、函式高階
迴圈繫結:
使用迴圈繫結會出現的問題及解決方案:

二、面向物件
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