一褂痰、綁定事件
想要給一個元素綁定事件兼搏,我們有兩種方法:使用內(nèi)聯(lián)事件或事件監(jiān)聽器。在之前的課程中连霉,我們一直使用的是內(nèi)聯(lián)事件來為元素綁定事件榴芳,例如一個按鈕的點擊事件嗡靡,代碼如下
btn.onclick =function(){}//綁定鼠標單擊事件
我們還可以用使用事件監(jiān)聽器為元素綁定事件,代碼如下
btn.addEventListener("click",function(){});
下面我們用兩種方法為按鈕綁定事件
1按鈕1 2按鈕2 3 4varbtn1 = document.querySelector("#btn1"); 5varbtn2 = document.querySelector("#btn2"); 6 7btn1.onclick =function(){ 8console.log("我是按鈕1"); 9? ? }1011btn2.addEventListener("click",function(){12console.log("我是按鈕2");13? ? })14
兩種方法都能實現(xiàn)相同的效果翠语,能成功的為按鈕綁定了點擊事件叽躯,但區(qū)別是使用addEventLitener可以無限制的為元素綁定事件财边,而內(nèi)聯(lián)事件后面的會覆蓋前面的
1varbtn1 = document.querySelector("#btn1"); 2varbtn2 = document.querySelector("#btn2"); 3 4btn1.onclick =function(){ 5console.log("我是按鈕1"); 6} 7btn1.onclick =function(){ 8console.log("我是按鈕1,第二次綁定"); 9}1011btn2.addEventListener("click",function(){12console.log("我是按鈕2");13})1415btn2.addEventListener("click",function(){16console.log("我是按鈕2,第二次綁定");17})
第一個按鈕第二次綁定的事件覆蓋了第一次綁定的事件肌括,第二個按鈕兩次綁定的事件都能被觸發(fā)。
二酣难、事件冒泡與事件捕獲
接下來我們用事件監(jiān)聽器為三個div元素綁定點擊事件谍夭,最外層的div寬高是300px,中間的div寬高都是200px憨募,最內(nèi)層的div寬高都是100px紧索,那么思考一下,點擊最內(nèi)層的div菜谣,事件會如何觸發(fā)珠漂,是只觸發(fā)最內(nèi)層的div,還是從內(nèi)到外依次觸發(fā)尾膊,還是從外到內(nèi)依次觸發(fā)
1
通過上面的例子我們可以看到媳危,事件是從最內(nèi)層開始觸發(fā),然后依次向外冈敛,輸出的順序是box3-box2-box1待笑。導致這種順序的原因是因為:事件流有事件捕獲階段和事件冒泡階段,事件捕獲階段是從最外層元素開始一層一層進入到事件目標(也就是我們點擊的那個元素)抓谴,到達事件目標后暮蹂,進入事件冒泡階段,事件從最內(nèi)層流向最外層癌压,事件默認情況下在冒泡階段觸發(fā)仰泻,所以我們看到的是先輸出box3,最后輸出box1。
我們也可以將事件設(shè)置為捕獲階段觸發(fā)滩届,代碼如下
1box1.addEventListener("click",function(){2console.log("我是box1")3},true)4box2.addEventListener("click",function(){5console.log("我是box2")6},true)7box3.addEventListener("click",function(){8console.log("我是box3")9},true)
只要在添加事件方法中添加第三個參數(shù)為true,事件就會在捕獲階段被觸發(fā)集侯,這樣輸出的順序就變成了box1-box2-box3。但是在日常開發(fā)中丐吓,我們幾乎不用做此修改浅悉,讓事件在冒泡階段觸發(fā)就可以了。
三券犁、事件委托
利用事件流的原理术健,我們可以實現(xiàn)事件委托,事件委托可以簡單的理解為將子級的事件委托給父級來處理粘衬,我們先來看一個簡單的例子
1
網(wǎng)頁中有兩個按鈕荞估,他們的父級是一個div標簽咳促,現(xiàn)在我們希望給這兩個按鈕綁定事件,當我們點擊按鈕的時候輸出按鈕的文本內(nèi)容勘伺,按照我們之前學過的知識跪腹,可以有如下寫法
1//第一種寫法2varbtn1 = document.querySelector(".btn1");3varbtn2 = document.querySelector(".btn2");4btn1.addEventListener("click",function(){5console.log(this.innerHTML)6})7btn2.addEventListener("click",function(){8console.log(this.innerHTML)9})
這種方法簡單易懂,但是存在重復飞醉,兩個按鈕觸發(fā)事件執(zhí)行的代碼完全一樣冲茸,我們可以獲取到所有按鈕,再通過遍歷綁定事件
1//第二種寫法2varbtnArray = document.querySelectorAll("button");3for(vari = 0;i
通過遍歷我們優(yōu)化了代碼缅帘,但是仍然存在問題轴术,首先,如果按鈕的數(shù)量特別多钦无,每一個按鈕都綁定依次事件會非常影響程序的性能逗栽,其次,就算不考慮性能失暂,通過這種方法綁定事件彼宠,如果使用js新增了一個按鈕,這個按鈕因為初始化的時候沒有綁定事件弟塞,所以無法點擊凭峡。為了解決上述問題,我們可以使用事件委托的方式來實現(xiàn)上面的功能
1varbtnBox = document.querySelector(".btnBox");2btnBox.addEventListener("click",function(event){3vartarget = event.target;//通過事件對象獲取事件目標4? ? console.log(target.innerHTML);5})
在事件監(jiān)聽函數(shù)中宣肚,我們可以在形參的位置獲取到事件對象event想罕,事件對象中包含了事件相關(guān)的信息,通過event.target可以獲取到我們的事件目標霉涨,在這個例子中事件目標就是我們點擊的按鈕按价,而我們事件綁定的是按鈕的容器,這樣就可以將自己元素的事件委托給父級來處理笙瑟。
四楼镐、課后練習
一、實現(xiàn)如下功能(阻止事件冒泡)
點擊一個按鈕往枷,顯示一個容器的盒子框产;
點擊容器,容器背景顏色改變错洁;
點擊容器按鈕 容器關(guān)閉;
二秉宿、實現(xiàn)水果列表,讓后添加的元素也可以刪除(事件委托);
三屯碴、通過上下左右按鍵控制元素移動描睦;