DOM學習之路--Mr.Ember

DOM學習之路--Mr.Emberhtml

摘要:打好基礎從DOM基礎開始node

 

一. 事件冒泡和捕獲正則表達式

當一個元素事件被觸發時,不只只在對象自己觸發一次,還經歷了三個階段:數組

(1)捕獲階段:文檔先由根對象(document)向內捕獲事件對象jsp

(2)目標階段:到達目標事件位置,觸發事件函數

(3)冒泡階段:再從目標事件位置往文檔的根節點方向回溯,從內向外冒泡事件對象。性能

 

下面來看一個栗子🌰學習

 

<div class="box1">a
     <div class="box2">b
          <div class="box3">c

          </div>
     </div>
</div>

 

給這三個元素綁定上事件this

a.addEventListener('click', function() {
    console.log(1)
}, true)
b.addEventListener('click', function() {
    console.log(2)
}, false)

c.addEventListener('click', function() {
    console.log(3)
}, false)

addEventListener第三個參數表達的含義是:是否在捕獲階段執行。默認falsespa

因此點擊c時,上述打印結果爲: 1,3,2

可是若是是都在a上添加事件,事件就會按照js的順序執行。

a.addEventListener('click', function() {
    console.log(1)
}, false)
a.addEventListener('click', function() {
    console.log(2)
}, true)

上述執行的結果是:1,2

因此能夠總結出:事件是按照其餘元素的捕獲事件->自己元素的事件順序->其餘元素的冒泡事件。

 

 

二. jQuery選擇器模擬實現

選擇器有不少種,下面我簡單的實現class選擇器,id選擇器,標籤選擇器。

<div id="div1">div1</div>

<div class="div2">222</div>
<div class="div2">333</div>
    
<p>p1</p>
<p>p2</p>

有上述html代碼片斷,打印下面的值

window.onload = function() {
    var ele1 = $('#div1');
    var ele2 = $('.div2');
    var ele3 = $('p');

    console.log(ele1)
    console.log(ele2)
    console.log(ele3)
}

首先建立一個空數組,用來放置選擇器選中的值

var TQObject = function() {
    this.data = [];
}

在上述對象的原型上掛載$

TQObject.prototype = {}
var $ = function(selecter) {
    this.tqObject = new TQObject();
    if(selecter.substring(0,1) == '#') {   //id選擇器
        var elem = document.getElementById(selecter.substring(1));
        this.tqObject.data.push(elem);
    }else if(selecter.substring(0,1) == '.') {  //class選擇器
        var elems = document.getElementsByTagName('*');
        var reg = new RegExp("(^|\\s)" + selecter.substring(1) + "($|\\s)");
        for(var i =0; i<elems.length;i++) {
            if(reg.test(elems[i].className)) {
                this.tqObject.data.push(elems[i])
            }
        }
    } else {   //標籤選擇器
        var elems = document.getElementsByTagName(selecter);
        // console.log(elems)
        for(var i = 0; i<elems.length; i++) {
            this.tqObject.data.push(elems[i])
        }
    }
    return tqObject
}

ID選擇器經過document.getElementById()進行選擇。可是class能夠經過document.getElementsByClassName()選擇,也能夠經過正則表達式選擇,上述代碼是經過正則表達式匹配實現的。

選擇結果:

 

三. 實現一個事件綁定函數

首先實現一個簡單的自定義事件綁定函數

function bindEvent(obj, events, fn) {
    obj.listeners = obj.listeners || {};
    bindCore(obj, events, fn)
}

bindCore函數

function bindCore(obj, events, fn) {
    obj.listeners[events] = obj.listeners[events] || [];
    obj.listeners[events].push(fn);
    
    if(obj.nodeType) {
        if(obj.addEventListener) {
            obj.addEventListener(events, fn, false);
        }else {
            obj.attachEvent('on'+ events, fn);
        }
    }
}

上述的綁定函數,下面還有解綁函數

function unbindEvent(obj, events, fn) {
    obj.listeners = obj.listeners || {};
    obj.listeners[events] = obj.listeners[events] || [];
    

    if(obj.nodeType) {
        if(obj.removeEventListener) {
            obj.removeEventListener(events, fn, false)
            console.log(obj.listeners)
        }else {
            obj.detachEvent('on' + events, fn)
        }
    }
}

給綁定函數解綁,最重要的一點是:綁定事件的函數和解綁事件的函數必須是一個函數。而且不能夠是匿名函數。

下面實現一個能夠爲多個元素添加多個事件、多個元素添加一個事件、一個元素添加一個事件、一個元素添加多個事件

function bindEvent(objArr, eventsArr, fn) {
    if(objArr.length > 1) {  
        objArr.forEach(element => { //多個元素添加事件
            element.listeners = element.listeners || {};
            if(eventsArr.length > 1) {
                eventsArr.forEach( eventItem => {  //多個元素添加多個事件
                    bindCore(element, eventItem, fn)
                })
            }else {  //多個元素添加一個事件
                bindCore(element, eventsArr, fn)
            }
        });
    }else {  //一個元素添加一個事件
        objArr.listeners = objArr.listeners || {};
        if(eventsArr.length > 1) {
            eventsArr.forEach( eventItem => {  //一個元素添加多個事件
                bindCore(objArr, eventItem, fn)
            })
        }else {  //多個元素添加一個事件
            bindCore(objArr, eventsArr, fn)
        }
    }
}

 

四. queryselect和getELementByxxxx之間的區別

1. queryselect能夠獲取頁面的靜態集合,可是不能經過這個值改變這個值,可是getELementByxxxx能夠經過這個獲取的值來改變當前的頁面上的值。

2. queryselector僅僅返回匹配指定選擇器的第一個元素,queryselectall是獲取全部的元素。

3. 性能方面來講,getELementByxxxx要比queryselect快不少,具體體驗地址

相關文章
相關標籤/搜索