久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

JavaScript DOM 事件模型

 小世界的野孩子 2021-11-06

JavaScript 是基于面向?qū)ο蠛褪录?qū)動(dòng)的一門語言,,事件模型是 DOM 中至關(guān)重要的內(nèi)容,,理解事件驅(qū)動(dòng)機(jī)制、事件反饋,、事件冒泡,、事件捕獲以及事件委托能幫助我們更好的處理事件,寫出更優(yōu)的代碼

事件驅(qū)動(dòng)機(jī)制

  1. 當(dāng)事件發(fā)生時(shí),,我們收到事件的反饋,,在 JavaScript 中,事件反饋是我們自行定義的事件處理函數(shù)

  2. 事件,,如點(diǎn)擊事件,、鼠標(biāo)移入事件等,是每一個(gè)元素與生俱來的能力

  3. 通常說的綁定事件,,實(shí)際上是綁定事件的反饋,,即事件處理函數(shù)

  4. 例如點(diǎn)擊一個(gè)按鈕,按鈕元素對(duì)象是事件發(fā)送器或事件源,,事件是鼠標(biāo)點(diǎn)擊事件,,事件處理函數(shù)是偵聽器

  5. 元素對(duì)象發(fā)出事件,事件處理函數(shù)做出反應(yīng),,這就是 JS 的事件驅(qū)動(dòng)機(jī)制

在觀察者模式中,,事件發(fā)送器就是主題,事件處理函數(shù)即偵聽器就是觀察者

綁定事件反饋

  1. 內(nèi)聯(lián)屬性

    <button onclick="test()">按鈕</button>

    介于結(jié)構(gòu)和邏輯要相分離,,不建議使用內(nèi)聯(lián)方式綁定

  2. 事件句柄

    var oBtn = document.getElementsByTagName('button')[0];
    oBtn.onclick = function() {
        // this -> oBtn
    }

    兼容性好,,但是重復(fù)綁定會(huì)覆蓋

  3. 事件監(jiān)聽器

    var oBtn = document.getElementsByTagName('button')[0];
    oBtn.addEventListener("click", funtion(){
        // this -> oBtn
     }, false);
    oBtn.addEventListener("click", test, false);
    funtion test(){ 
        // 事件處理函數(shù)
    }

    重復(fù)添加,不會(huì)覆蓋之前添加的監(jiān)聽器,,但是如果事件類型,、事件處理函數(shù)和最后一個(gè)布爾參數(shù)都相同,則不會(huì)重復(fù)執(zhí)行

    IE8 及以下不支持 addEventListener,,可用 attachEvent 代替

    var oBtn = document.getElementsByTagName('button')[0];
    oBtn.attachEvent("onclick", funtion(){
    // this -> window
        }); 
    // 區(qū)別于 addEventListener,,第一個(gè)參數(shù)使用 'onclick',而不是 'click'
    // 并且內(nèi)部 this 指向 window
    // 對(duì)于 attachEvent,,如果事件類型,、事件處理函數(shù)都相同,還是會(huì)重復(fù)執(zhí)行

    兼容性封裝

    function addEvent(elem, type, fn) {
        if (elem.addEventListener) {
            elem.addEventListener(type, fn, false);
        } else if (elem.attachEvent) {
            elem.attachEvent('on' + type, function(ev) {
                    fn.call(elem, ev); // call 兼容性比 bind 好
                });
        } else {
            elem['on' + type] = fn;
        }
    }
  4. 解除綁定

    oBtn.onclik = null;
    oBtn.removeEventListener("click", test, false); // 解除 addEventListener
    oBtn.detachEvent('onclick', test); // 解除 attachEvent

    示例:點(diǎn)擊一次后清除事件反饋

    oBtn.onclik = function() {
    // ...
        this.onclick = null;
    }
    // 非嚴(yán)格模式
    oBtn.addEventListener("click", funtion() {
    // ...
        this.removEventListener('cilck', arguments.callee, false);
    }, false);
    // 嚴(yán)格模式
    oBtn.addEventListener("click", funtion temp() {
    // ...
        this.removeEventListener('click', temp, false);
    }, false);

事件冒泡和捕獲

  1. 事件冒泡:當(dāng)一個(gè)元素發(fā)生事件時(shí),,該事件會(huì)向父級(jí)元素傳遞,,按由子到父的順序觸發(fā)一連串的事件反饋,稱之為事件冒泡

    DOM 上的嵌套關(guān)系會(huì)產(chǎn)生事件冒泡,,例如兩個(gè) div 嵌套,,點(diǎn)擊內(nèi)部的 div,,觸發(fā)內(nèi)部 div 的點(diǎn)擊事件,內(nèi)部 div 的點(diǎn)擊事件處理函數(shù)進(jìn)行響應(yīng),,這個(gè)事件向其父級(jí)即外部 div 傳遞,,外部 div 也有點(diǎn)擊事件,外部 div 所綁定的點(diǎn)擊事件反饋也會(huì)響應(yīng)

    <div class="outer">
        <div class="inner"></div>
    </div>
    var outer = document.getElementsByClassName('outer')[0],
        inner = outer.getElementsByClassName('inner')[0];
    outer.addEventListener('click', function () {
        console.log('bubble outer');
    }, false);
    inner.addEventListener('click', function () {
        console.log('bubble inner');
    }, false);
    // addEventListener 最后一個(gè)參數(shù)默認(rèn)值為 false,,表示事件冒泡
    // 點(diǎn)擊 inner,,打印出
    // bubble inner 
    // bubble outer
  2. 事件捕獲:當(dāng)一個(gè)元素發(fā)生事件時(shí),該事件會(huì)向父級(jí)元素傳遞,,按由父到子的順序觸發(fā)一連串的事件反饋,,稱之為事件捕獲

    事件捕獲與事件冒泡的觸發(fā)順序相反,同樣需要 DOM 上的嵌套關(guān)系

    outer.addEventListener('click', function () {
        console.log('outer');
    }, true);
    inner.addEventListener('click', function () {
        console.log('inner');
    }, true);
    // addEventListener 最后一個(gè)參數(shù)使用 true,,表示事件捕獲
    // 點(diǎn)擊 inner,,打印出
    // outer
    // in
  3. 捕獲和冒泡的執(zhí)行順序

    outer.addEventListener('click', function () {
        console.log('bubble outer');
    }, false); // 冒泡
    inner.addEventListener('click', function () {
        console.log('bubble inner');
    }, false); // 冒泡
    outer.addEventListener('click', function () {
        console.log('outer');
    }, true); // 捕獲
    inner.addEventListener('click', function () {
        console.log('inner');
    }, true); // 捕獲
    // 點(diǎn)擊 inner,打印出
    // outer
    // bubble inner
    // inner
    // bubble outer

    點(diǎn)擊一個(gè)元素,,元素即事件源,,若事件源綁定了事件處理函數(shù),且設(shè)定了事件捕獲,,則先執(zhí)行捕獲,,捕獲執(zhí)行完畢后,按照綁定順序執(zhí)行該事件源綁定的事件,,如果設(shè)定了事件冒泡,,再執(zhí)行冒泡

  4. focus blur change submit reset select 事件沒有冒泡和捕獲,IE 瀏覽器沒有事件捕獲

阻止事件冒泡

  1. 阻止冒泡的方法

    Event 的原型上有 stopPropagation 方法,,可以阻止冒泡,,是 w3c 的規(guī)范

    Event 的原型上有 cancleBubble 屬性,賦值為 true,,可以阻止冒泡

  2. addEventListener 綁定事件處理函數(shù),,拿到事件對(duì)象

    var outer = document.getElementsByClassName('outer')[0],
        inner = outer.getElementsByClassName('inner')[0];
    inner.addEventListener('click', function (ev) {
        console.log(ev); // 事件對(duì)象 ev
        ev.stopPropagation(); // 阻止事件冒泡
        }, false);
  3. IE 瀏覽器沒有 stopPropagation 方法,可以使用 cancelBubble 屬性

    注意:IE 瀏覽器中事件對(duì)象存放在 window.event 中,。IE8 不支持 addEventListener 方法

    // 封裝阻止冒泡的方法
    function cancelBubble(ev) {
        if (ev.stopPropagation) {
            ev.stopPropagation();
        } else ev.cancelBubble = true; // 兼容 IE8 及以下
    }
    // 使用上文中封裝好的 addEvent 方法
    function addEvent(elem, type, fn) {
        if (elem.addEventListener) {
            elem.addEventListener(type, fn);
        } else if (elem.attachEvent) {
            elem.attachEvent('on' + type, function (ev) {
                fn.call(elem, ev);
            });
        } else {
            elem['on' + type] = fn;
        }
    }
    // 綁定事件處理函數(shù)
    var outer = document.getElementsByClassName('outer')[0],
        inner = outer.getElementsByClassName('inner')[0];
    addEvent(inner, 'click', function (ev) {
            var ev = ev || window.event; // IE 兼容性寫法
        cancelBubble(ev); // 阻止冒泡
        });

阻止默認(rèn)事件

  1. 三種方法

    • 事件對(duì)象 preventDefault() 方法,,兼容 IE9 及以上

    • 事件對(duì)象 returnValue = false,兼容 IE8 及以下

    • 事件處理函數(shù) return false

  2. 兼容性寫法

    function preventDefaultEvent(ev) {
        if (ev.preventDefault) {
            ev.preventDefault();
        } else ev.returnValue = false; // 兼容 IE8 及以下
    }
  3. 右鍵菜單事件

    document.oncontextmenu = function (ev) {
        var ev = ev || window.event;
        // 1. ev.preventDefault();  // IE9 及以上
        // 2. ev.returnValue = false; // IE8 及以下
        // 3. return false;
    }
  4. a 標(biāo)簽跳轉(zhuǎn)事件

    href 使用偽協(xié)議

    <a href="javascript:void(0);">a 標(biāo)簽</a> 
    <a href="javascript:;">a 標(biāo)簽</a> 
    <a href="#">a 標(biāo)簽</a> <!--跳轉(zhuǎn)到當(dāng)前頁面頂部-->

    onclick 事件 return false

    <a href="http://www.baidu.com" onclick="return false">a 標(biāo)簽</a>
    <a href="http://www.baidu.com" onclick="return test(),false">a 標(biāo)簽</a>
    <!--第二個(gè)是利用了 “,” 分隔符會(huì)返回最后一個(gè)的特點(diǎn),,與 test 方法無關(guān)-->

    綁定事件處理函數(shù)

    <!--內(nèi)聯(lián)綁定-->
    <a id='taga' href="http://www.baidu.com" onclick="return test()">a 標(biāo)簽</a>
    <!--句柄綁定-->
    <script>
        document.getElementById('taga').onclick = test;
        function test(ev) {
           var ev = ev || window.event;
        // 1. ev.preventDefault();  // IE9 及以上
        // 2. ev.returnValue = false; // IE8 及以下
        // 3. return false;
        }
        // 前兩種方式在使用內(nèi)聯(lián)屬性綁定時(shí),,不需要在屬性上加 return,第三種則需要
    </script>

    表單的 action 屬性支持 javascript: 偽協(xié)議,,onsubmit 或者提交按鈕點(diǎn)擊事件都可以綁定處理函數(shù),,阻止提交的方法和阻止 a 標(biāo)簽跳轉(zhuǎn)的方法類似

冒泡捕獲流

  1. 事件流:描述從頁面中接收事件的順序

  2. 事件冒泡流:微軟 IE 提出,Event Bubbling

  3. 事件捕獲流:網(wǎng)景 Netscape 提出,,Event Capturing

  4. 事件流三個(gè)階段:事件捕獲階段,、處于目標(biāo)階段,、事件冒泡階段

    元素觸發(fā)事件時(shí),首先事件捕獲階段,,由父到子的執(zhí)行事件處理函數(shù),,然后處于目標(biāo)階段,,該元素的事件處理函數(shù)按綁定順序執(zhí)行,,最后事件冒泡階段,由子到父的執(zhí)行事件處理函數(shù)

事件和事件源

  1. 事件即事件對(duì)象,,可以由事件處理函數(shù)的參數(shù)拿到

    IE8 及以下中事件對(duì)象存放在 window.event 中

    // btn 按鈕元素
    btn.onclick = function(ev) {
        var ev = ev || window.event; // IE8 兼容性寫法
    }
  2. 事件源即事件源對(duì)象,,是發(fā)生事件的元素,即事件發(fā)送器,,可以從事件對(duì)象中獲取

    IE8 及以下只有 srcElement,,firefox 低版本只有 target,chrome 兩者都有

    // btn 按鈕元素
    btn.onclick = function(ev) {
        var ev = ev || window.event; // IE8 兼容性寫法
        var tar = ev.target || ev.srcElement; // 獲取事件源的兼容性寫法
    }

事件委托

  1. 事件委托也叫事件代理,,指對(duì)父級(jí)元素綁定事件處理函數(shù),,通過獲取事件源來處理子元素

  2. 示例:點(diǎn)擊按鈕使列表 ul 增加 li 元素,點(diǎn)擊每個(gè) li 元素打印出其中的內(nèi)容(innerHTML)

    如果不使用事件委托,,需要循環(huán)對(duì)每個(gè) li 進(jìn)行綁定,,點(diǎn)擊按鈕添加新的 li 元素后也要進(jìn)行綁定,效率低下

    使用事件委托,,直接對(duì) ul 綁定點(diǎn)擊事件處理函數(shù),,獲取事件對(duì)象、事件源對(duì)象,,再對(duì)源對(duì)象進(jìn)行處理

    <body>
    <button>btn</button>
    <ul>
        <li>1</li>
        <li>2</li>
        <li>3</li>
        <li>4</li>
    </ul>
    <script>
        var oBtn = document.getElementsByTagName('button')[0],
            oList = document.getElementsByTagName('ul')[0],
            oLi = oList.getElementsByTagName('li');
        oBtn.onclick = function () {
            var li = document.createElement('li');
            li.innerText = oLi.length + 1;
            oList.appendChild(li);
        }
        oList.onclick = function (ev) {
            var ev = ev || window.event,
                tar = ev.target || ev.srcElement;
            // tar 即為被點(diǎn)擊的 li 元素
            console.log(tar.innerHTML); 
            // 返回在所有兄弟元素中的索引,,借用數(shù)組 indexOf 方法
            console.log(Array.prototype.indexOf.call(oLi, tar));
        }
    </script>
    </body>

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,,不代表本站觀點(diǎn),。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,,謹(jǐn)防詐騙,。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào),。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多