5.DOM:事件高級( 注冊事件更哄、事件監(jiān)聽芋齿、解綁事件、 DOM事件流(捕獲階段成翩、當(dāng)前目標(biāo)階段觅捆、冒泡階段)、事件對象麻敌、e.target 和 this 的區(qū)別栅炒、阻止默認(rèn)行為、阻止事件冒泡术羔、事件委托赢赊、)

1.1. 事件高級

1.1.1. 注冊事件(2種方式)

1.1.2 事件監(jiān)聽

addEventListener()事件監(jiān)聽(IE9以后支持)

eventTarget.addEventListener()方法將指定的監(jiān)聽器注冊到 eventTarget(目標(biāo)對象)上,當(dāng)該對象觸發(fā)指定的事件時级历,就會執(zhí)行事件處理函數(shù)释移。

attacheEvent()事件監(jiān)聽(IE678支持)

? eventTarget.attachEvent()方法將指定的監(jiān)聽器注冊到 eventTarget(目標(biāo)對象) 上,當(dāng)該對象觸發(fā)指定的事件時寥殖,指定的回調(diào)函數(shù)就會被執(zhí)行玩讳。

<button>傳統(tǒng)注冊事件</button>
<button>方法監(jiān)聽注冊事件</button>
<button>ie9 attachEvent</button>
<script>
    var btns = document.querySelectorAll('button');
    // 1. 傳統(tǒng)方式注冊事件
    btns[0].onclick = function() {
        alert('hi');
    }
    btns[0].onclick = function() {
            alert('hao a u');
        }
   // 2. 事件偵聽注冊事件 addEventListener 
   // (1) 里面的事件類型是字符串 必定加引號 而且不帶on
   // (2) 同一個元素 同一個事件可以添加多個偵聽器(事件處理程序)
    btns[1].addEventListener('click', function() {
        alert(22);
    })
    btns[1].addEventListener('click', function() {
            alert(33);
    })
    // 3. attachEvent ie9以前的版本支持
    btns[2].attachEvent('onclick', function() {
        alert(11);
    })
</script>

事件監(jiān)聽兼容性解決方案

封裝一個函數(shù),函數(shù)中判斷瀏覽器的類型:

1.1.3. 刪除事件(解綁事件)

    <div>1</div>
    <div>2</div>
    <div>3</div>
    <script>
        var divs = document.querySelectorAll('div');
        divs[0].onclick = function() {
            alert(11);
            // 1. 傳統(tǒng)方式刪除事件
            divs[0].onclick = null;
        }
        // 2. removeEventListener 刪除事件
        divs[1].addEventListener('click', fn) // 里面的fn 不需要調(diào)用加小括號
        function fn() {
            alert(22);
            divs[1].removeEventListener('click', fn);
        }
        // 3. detachEvent
        divs[2].attachEvent('onclick', fn1);

        function fn1() {
            alert(33);
            divs[2].detachEvent('onclick', fn1);
        }
    </script>

**刪除事件兼容性解決方案 **

1.1.4. DOM事件流

html中的標(biāo)簽都是相互嵌套的嚼贡,我們可以將元素想象成一個盒子裝一個盒子熏纯,document是最外面的大盒子。
當(dāng)你單擊一個div時,同時你也單擊了div的父元素,甚至整個頁面窄坦。

那么是先執(zhí)行父元素的單擊事件榛搔,還是先執(zhí)行div的單擊事件 ?坛猪??

比如:我們給頁面中的一個div注冊了單擊事件,當(dāng)你單擊了div時萍膛,也就單擊了body,單擊了html嚷堡,單擊了document蝗罗。

當(dāng)時的2大瀏覽器霸主誰也不服誰!
IE 提出從目標(biāo)元素開始蝌戒,然后一層一層向外接收事件并響應(yīng)串塑,也就是冒泡型事件流。
Netscape(網(wǎng)景公司)提出從最外層開始北苟,然后一層一層向內(nèi)接收事件并響應(yīng)桩匪,也就是捕獲型事件流。

江湖紛爭友鼻,武林盟主也腦殼疼I店肌9肷А!

最終妆档,w3c 采用折中的方式僻爽,平息了戰(zhàn)火,制定了統(tǒng)一的標(biāo)準(zhǔn) —--— 先捕獲再冒泡贾惦。
現(xiàn)代瀏覽器都遵循了此標(biāo)準(zhǔn)胸梆,所以當(dāng)事件發(fā)生時,會經(jīng)歷3個階段须板。

DOM 事件流會經(jīng)歷3個階段:

  1. 捕獲階段

  2. 當(dāng)前目標(biāo)階段

  3. 冒泡階段

? 我們向水里面扔一塊石頭碰镜,首先它會有一個下降的過程,這個過程就可以理解為從最頂層向事件發(fā)生的最具體元素(目標(biāo)點)的捕獲過程习瑰;之后會產(chǎn)生泡泡绪颖,會在最低點( 最具體元素)之后漂浮到水面上,這個過程相當(dāng)于事件冒泡杰刽。

事件冒泡

    <div class="father">
        <div class="son">son盒子</div>
    </div>
    <script>
        // onclick 和 attachEvent(ie) 在冒泡階段觸發(fā)
        // 冒泡階段 如果addEventListener 第三個參數(shù)是 false 或者 省略 
        // son -> father ->body -> html -> document
        var son = document.querySelector('.son');
        // 給son注冊單擊事件
        son.addEventListener('click', function() {
            alert('son');
        }, false);
        // 給father注冊單擊事件
        var father = document.querySelector('.father');
        father.addEventListener('click', function() {
            alert('father');
        }, false);
        // 給document注冊單擊事件菠发,省略第3個參數(shù)
        document.addEventListener('click', function() {
            alert('document');
        })
    </script>

事件捕獲

    <div class="father">
        <div class="son">son盒子</div>
    </div>
    <script>
        // 如果addEventListener() 第三個參數(shù)是 true 那么在捕獲階段觸發(fā)
        // document -> html -> body -> father -> son
         var son = document.querySelector('.son');
        // 給son注冊單擊事件,第3個參數(shù)為true
         son.addEventListener('click', function() {
             alert('son');
         }, true);
         var father = document.querySelector('.father');
        // 給father注冊單擊事件贺嫂,第3個參數(shù)為true
         father.addEventListener('click', function() {
             alert('father');
         }, true);
        // 給document注冊單擊事件滓鸠,第3個參數(shù)為true
        document.addEventListener('click', function() {
            alert('document');
        }, true)
    </script>

1.1.5. 事件對象

什么是事件對象

事件發(fā)生后,跟事件相關(guān)的一系列信息數(shù)據(jù)的集合都放到這個對象里面第喳,這個對象就是事件對象糜俗。

比如:

  1. 誰綁定了這個事件。

  2. 鼠標(biāo)觸發(fā)事件的話曲饱,會得到鼠標(biāo)的相關(guān)信息悠抹,如鼠標(biāo)位置。

  3. 鍵盤觸發(fā)事件的話扩淀,會得到鍵盤的相關(guān)信息楔敌,如按了哪個鍵。

事件對象的使用

事件觸發(fā)發(fā)生時就會產(chǎn)生事件對象驻谆,并且系統(tǒng)會以實參的形式傳給事件處理函數(shù)卵凑。

所以,在事件處理函數(shù)中聲明1個形參用來接收事件對象胜臊。

事件對象的兼容性處理

事件對象本身的獲取存在兼容問題:

  1. 標(biāo)準(zhǔn)瀏覽器中是瀏覽器給方法傳遞的參數(shù)勺卢,只需要定義形參 e 就可以獲取到。

  2. 在 IE6~8 中象对,瀏覽器不會給方法傳遞參數(shù)黑忱,如果需要的話,需要到 window.event 中獲取查找。

只要“||”前面為false, 不管“||”后面是true 還是 false甫煞,都返回 “||” 后面的值菇曲。
只要“||”前面為true, 不管“||”后面是true 還是 false,都返回 “||” 前面的值抚吠。

    <div>123</div>
    <script>
        var div = document.querySelector('div');
        div.onclick = function(e) {
                // 事件對象
                e = e || window.event;
                console.log(e);
        }
    </script>

// 1. event 就是一個事件對象 寫到我們偵聽函數(shù)的 小括號里面 當(dāng)形參來看
// 2. 事件對象只有有了事件才會存在羊娃,它是系統(tǒng)給我們自動創(chuàng)建的,不需要我們傳遞參數(shù)
// 3. 事件對象 是 我們事件的一系列相關(guān)數(shù)據(jù)的集合 跟事件相關(guān)的 比如鼠標(biāo)點擊里面就包含了鼠標(biāo)的相關(guān)信息埃跷,鼠標(biāo)坐標(biāo)啊,如果是鍵盤事件里面就包含的鍵盤事件的信息 比如 判斷用戶按下了那個鍵
// 4. 這個事件對象我們可以自己命名 比如 event 邮利、 evt弥雹、 e
// 5. 事件對象也有兼容性問題 ie678 通過 window.event 兼容性的寫法 e = e || window.event;

事件對象的屬性和方法

e.target 和 this 的區(qū)別

  • this 是事件綁定的元素(綁定這個事件處理函數(shù)的元素) 。

  • e.target 是事件觸發(fā)的元素延届。

通常情況下terget 和 this是一致的剪勿,
但有一種情況不同,那就是在事件冒泡時(父子元素有相同事件方庭,單擊子元素厕吉,父元素的事件處理函數(shù)也會被觸發(fā)執(zhí)行),
這時候this指向的是父元素械念,因為它是綁定事件的元素對象头朱,
而target指向的是子元素,因為他是觸發(fā)事件的那個具體元素對象龄减。

    <div>123</div>
    <script>
        var div = document.querySelector('div');
        div.addEventListener('click', function(e) {
            // e.target 和 this指向的都是div
            console.log(e.target);
            console.log(this);

        });
    </script>

事件冒泡下的e.target和this

    <ul>
        <li>abc</li>
        <li>abc</li>
        <li>abc</li>
    </ul>
    <script>
        var ul = document.querySelector('ul');
        ul.addEventListener('click', function(e) {
              // 我們給ul 綁定了事件  那么this 就指向ul  
              console.log(this); // ul

              // e.target 觸發(fā)了事件的對象 我們點擊的是li e.target 指向的就是li
              console.log(e.target); // li
        });
    </script>

1.1.6 阻止默認(rèn)行為

html中一些標(biāo)簽有默認(rèn)行為项钮,例如a標(biāo)簽被單擊后,默認(rèn)會進(jìn)行頁面跳轉(zhuǎn)希停。

     <div>123</div>
    <a >百度</a>
    <form action="http://www.baidu.com">
        <input type="submit" value="提交" name="sub">
    </form>
    <script>
        // 常見事件對象的屬性和方法
        // 1. 返回事件類型
        var div = document.querySelector('div');
        div.addEventListener('click', fn);
        div.addEventListener('mouseover', fn);
        div.addEventListener('mouseout', fn);

        function fn(e) {
            console.log(e.type);

        }
        // 2. 阻止默認(rèn)行為(事件) 讓鏈接不跳轉(zhuǎn) 或者讓提交按鈕不提交
        var a = document.querySelector('a');
        a.addEventListener('click', function(e) {
                e.preventDefault(); //  dom 標(biāo)準(zhǔn)寫法
            })
            // 3. 傳統(tǒng)的注冊方式
        a.onclick = function(e) {
            // 普通瀏覽器 e.preventDefault();  方法
            // e.preventDefault();
            // 低版本瀏覽器 ie678  returnValue  屬性
            // e.returnValue;
            // 我們可以利用return false 也能阻止默認(rèn)行為 沒有兼容性問題 特點: return 后面的代碼不執(zhí)行了烁巫, 而且只限于傳統(tǒng)的注冊方式
            return false;
            alert(11);
        }
    </script>

1.1.7 阻止事件冒泡

事件冒泡本身的特性,會帶來的壞處宠能,也會帶來的好處亚隙。

    <div class="father">
        <div class="son">son兒子</div>
    </div>
    <script>
        var son = document.querySelector('.son');
        // 給son注冊單擊事件
        son.addEventListener('click', function(e) {
            alert('son');
            e.stopPropagation(); // stop 停止  Propagation 傳播
            window.event.cancelBubble = true; // 非標(biāo)準(zhǔn) cancel 取消 bubble 泡泡
        }, false);

        var father = document.querySelector('.father');
        // 給father注冊單擊事件
        father.addEventListener('click', function() {
            alert('father');
        }, false);
        // 給document注冊單擊事件
        document.addEventListener('click', function() {
            alert('document');
        })
    </script>

阻止事件冒泡的兼容性處理

1.1.8 事件委托

事件冒泡本身的特性,會帶來的壞處违崇,也會帶來的好處阿弃。

什么是事件委托

把事情委托給別人,代為處理亦歉。

事件委托也稱為事件代理恤浪,在 jQuery 里面稱為事件委派。

說白了就是肴楷,不給子元素注冊事件水由,給父元素注冊事件,把處理代碼在父元素的事件中執(zhí)行赛蔫。

生活中的代理:

js事件中的代理:

事件委托的原理

? 給父元素注冊事件砂客,利用事件冒泡泥张,當(dāng)子元素的事件觸發(fā),會冒泡到父元素鞠值,然后去控制相應(yīng)的子元素媚创。

事件委托的作用

  • 我們只操作了一次 DOM ,提高了程序的性能彤恶。

  • 動態(tài)新創(chuàng)建的子元素钞钙,也擁有事件。

    <ul>
        <li>知否知否声离,點我應(yīng)有彈框在手芒炼!</li>
        <li>知否知否,點我應(yīng)有彈框在手术徊!</li>
        <li>知否知否本刽,點我應(yīng)有彈框在手!</li>
        <li>知否知否赠涮,點我應(yīng)有彈框在手子寓!</li>
        <li>知否知否,點我應(yīng)有彈框在手笋除!</li>
    </ul>
    <script>
        // 事件委托的核心原理:給父節(jié)點添加偵聽器斜友, 利用事件冒泡影響每一個子節(jié)點
        var ul = document.querySelector('ul');
        ul.addEventListener('click', function(e) {
            // e.target 這個可以得到我們點擊的對象
            e.target.style.backgroundColor = 'pink';
        })
    </script>
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市株憾,隨后出現(xiàn)的幾起案子蝙寨,更是在濱河造成了極大的恐慌,老刑警劉巖嗤瞎,帶你破解...
    沈念sama閱讀 210,835評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件墙歪,死亡現(xiàn)場離奇詭異,居然都是意外死亡贝奇,警方通過查閱死者的電腦和手機虹菲,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,900評論 2 383
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來掉瞳,“玉大人毕源,你說我怎么就攤上這事∩孪埃” “怎么了霎褐?”我有些...
    開封第一講書人閱讀 156,481評論 0 345
  • 文/不壞的土叔 我叫張陵,是天一觀的道長该镣。 經(jīng)常有香客問我冻璃,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,303評論 1 282
  • 正文 為了忘掉前任省艳,我火速辦了婚禮娘纷,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘跋炕。我一直安慰自己赖晶,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 65,375評論 5 384
  • 文/花漫 我一把揭開白布辐烂。 她就那樣靜靜地躺著遏插,像睡著了一般。 火紅的嫁衣襯著肌膚如雪纠修。 梳的紋絲不亂的頭發(fā)上涩堤,一...
    開封第一講書人閱讀 49,729評論 1 289
  • 那天,我揣著相機與錄音分瘾,去河邊找鬼。 笑死吁系,一個胖子當(dāng)著我的面吹牛德召,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播汽纤,決...
    沈念sama閱讀 38,877評論 3 404
  • 文/蒼蘭香墨 我猛地睜開眼上岗,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了蕴坪?” 一聲冷哼從身側(cè)響起肴掷,我...
    開封第一講書人閱讀 37,633評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎背传,沒想到半個月后呆瞻,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,088評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡径玖,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,443評論 2 326
  • 正文 我和宋清朗相戀三年痴脾,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片梳星。...
    茶點故事閱讀 38,563評論 1 339
  • 序言:一個原本活蹦亂跳的男人離奇死亡赞赖,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出冤灾,到底是詐尸還是另有隱情前域,我是刑警寧澤,帶...
    沈念sama閱讀 34,251評論 4 328
  • 正文 年R本政府宣布韵吨,位于F島的核電站匿垄,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜年堆,卻給世界環(huán)境...
    茶點故事閱讀 39,827評論 3 312
  • 文/蒙蒙 一吞杭、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧变丧,春花似錦芽狗、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,712評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至攻晒,卻和暖如春顾复,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背鲁捏。 一陣腳步聲響...
    開封第一講書人閱讀 31,943評論 1 264
  • 我被黑心中介騙來泰國打工芯砸, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人给梅。 一個月前我還...
    沈念sama閱讀 46,240評論 2 360
  • 正文 我出身青樓假丧,卻偏偏與公主長得像,于是被迫代替她去往敵國和親动羽。 傳聞我的和親對象是個殘疾皇子包帚,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,435評論 2 348