首頁  >  文章  >  web前端  >  js事件流以及擴充應用程式實例

js事件流以及擴充應用程式實例

小云云
小云云原創
2018-03-26 17:34:451349瀏覽

什麼是事件流呢?本文主要和大家分享js事件流以及擴充應用程式實例以及擴充應用實例,希望能幫助大家。

js事件流以及擴充應用程式實例
DOM標準規定事件流包含三個階段:事件擷取階段、處於目標階段、事件冒泡階段。
 ● 事件捕獲階段:實際目標(<p></p>)在捕獲階段不會接收事件。也就是在捕獲階段,事件從document到再到就停止了。上圖為1~3.
 ● 處於目標階段:事件在<p></p>上發生並處理。但是事件處理會被看成是冒泡階段的一部分。
 ● 冒泡階段:事件又傳回文件。
note:
1)、儘管「DOM2級事件」標準規範明確規定事件捕獲階段不會涉及事件目標,但是在IE9、Safari、Chrome、Firefox和Opera9.5及更高版本都會在捕獲階段觸發事件物件上的事件。結果,就是有兩次機會在目標物件上面操作事件。
2)、並非所有的事件都會經過冒泡階段 。所有的事件都要經過捕獲階段和處於目標階段,但是有些事件會跳過冒泡階段:如,獲得輸入焦點的focus事件和失去輸入焦點的blur事件。

捕捉型事件流:事件的傳播是從最不特定的事件目標到最特定的事件目標。即從DOM樹的根到葉子。
冒泡型事件流:事件的傳播是從最特定的事件目標到最不特定的事件目標。即從DOM樹的葉子到根。

那麼這裡要實現的就是冒泡型事件流,從裡面(葉子)到外面(根)

//只需要在window.onload里面给每一个圆添加点击事件处理程序就ok了哦,其余代码请看上[一篇文章](https://blog.csdn.net/weixin_38323736/article/details/79685589)当然是在圆画好之后执行这一段代码,所以位置放在后面,别放错var circles=document.getElementsByClassName("circle");    for(var i=0;i<n;i++){
        circles[i].onclick=function(e){

            //currentTarget表示当前处理该事件的元素、文档或窗口,childNodes是子节点的意思,这里遍历子节点
            e.currentTarget.childNodes.forEach(function(v) {

                //把文本节点找出,不然html代码也会输出的
                if(v instanceof Text) {                    //文字节点为Text()实例,用data或者wholeText可以取到String类型的文本
                    //解决方法参照:https://segmentfault.com/q/1010000009913772/a-1020000009914008
                    console.log(v.data);                    // console.log(v.wholeText);
                }
            });
        }
    }

ok啦,就是這麼簡單。
好學的同學一定想看看事件捕獲了,乾脆我把兩種都寫出來吧,讓大家看看整個事件流是怎麼樣的

circles[i].onclick =function(e){}這種寫法是dom0級的寫法,只能寫一個事件,再寫一個會覆蓋,而且只支援冒泡事件
addEventListener則不一樣,它可以寫多個事件,不會覆蓋

//这段代码包含了上面的js代码哦var circles=document.getElementsByClassName("circle");for(var i=0;i<n;i++){
    circles[i].addEventListener("click",function(e){
        e.currentTarget.childNodes.forEach(function(v) {
            if(v instanceof Text) {
                console.log(v.data+" 捕获阶段");
            }
        });        //true表示事件句柄在捕获阶段执行; 
        //false- 默认。事件句柄在冒泡阶段执行
    },true);            
    circles[i].addEventListener("click",function(e){
        e.currentTarget.childNodes.forEach(function(v) {
            if(v instanceof Text) {
                console.log(v.data+" 冒泡阶段");
            }
        });
    },false);
}

這時候,點擊15,就會出現下面的效果啦
js事件流以及擴充應用程式實例

ok啦,其實事件冒泡有一個很好的應用哦,就是事件代理

事件代理也即事件委託

傳統的事件處理中,需要為每個元素新增事件處理器。 js事件代理程式則是一種簡單有效的技巧,透過它可以把事件處理器加入到一個父級元素上,從而避免把事件處理器加入到多個子級元素上。

事件代理的原理用到的就是事件冒泡和目標元素,把事件處理器加入父元素,等待子元素事件冒泡,並且父元素能夠透過target(IE為srcElement)判斷是哪個子元素,從而做相應處理。

事件代理程式的好處
 ● 將多個事件處理器減少到一個,因為事件處理器要駐留內存,這樣就提高了效能。想像如果有一個100行的表格,對比傳統的為每個單元格綁定事件處理器的方式和事件代理(即table上添加一個事件處理器),不難得出結論,事件代理確實避免了一些潛在的風險,提高了性能。
 ● DOM更新無需重新綁定事件處理器,因為事件代理程式對不同子元素可採用不同處理方法。如果新增其他子元素(a,span,p等),直接修改事件代理程式的事件處理函數即可,不需要重新綁定處理器,不需要再次循環遍歷。

例如,現在我想,點擊15的圓的時候,就輸出15,我們先用傳統循環的方法來寫,再用事件委託的方法來寫

var circles=document.getElementsByClassName("circle");for(var i=0;i<n;i++){
    circles[i].addEventListener("click",function(e){
        e.currentTarget.childNodes.forEach(function(v) {
            if(v instanceof Text) {
                console.log(v.data);
            }
        });        //阻止冒泡哦!!!不然不止输出15了
        e.stopPropagation();
    },false);
}

這種方法其實是耗性能的,循環幾次,編譯時就會寫幾次,所以還是不如事件代理,只需要寫一次:

//获取外面的大圆,只需要交给大圆来处理就okvar circle=document.getElementById("circle");
circle.addEventListener("click",function(e){
    e=e||window.event;    var targetElement=e.target||e.srcElement;
    targetElement.childNodes.forEach(function(v) {
        if(v instanceof Text) {
            console.log(v.data);
        }
    });
})

哈哈,有沒有人想問,那上面用了那麼多循環,怎麼不也用事件代理寫了呢?我想了一下,還真可以寫哦

var circle=document.getElementById("circle");
circle.addEventListener("click",function(e){
       e=e||window.event;       var targetElement=e.target||e.srcElement;       while(targetElement.nodeName!="BODY"){
        targetElement.childNodes.forEach(function(v) {
            if(v instanceof Text) {
                console.log(v.data);
            }
        });
        targetElement=targetElement.parentNode;
    }
},false)

相關推薦:

##js之DOM事件流詳解

JavaScript事件學習之事件流、處理程序及物件總結

什麼是JavaScript事件流及事件處理程序詳解#

以上是js事件流以及擴充應用程式實例的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn