天天看點

salesforce lightning零基礎學習(五) 事件階段(component events phase)

上一篇介紹了lightning component events的簡單介紹。此篇針對上一篇進行深入,主要講的内容為component event中的階段(Phase)。

一. 階段(Phase)的概念

lightning對于 component event提供了兩種Phase方式,Capture(捕獲階段)以及Bubble(冒泡階段)。這兩種方式和javascript中針對事件處理的Capture以及Bubble很相似。先以javascript中的針對DOM結構事件監聽進行描述。

以一個demo進行講解。

<html>
    <body>
        <div id="sampleDivId">
            <a id="sampleAId">
                <span id="sampleSpanId">
                    test event phase
                </span>
            </a>
        </div>
    </body>

    <script>
        function clickHandler(e) {
            console.log(e.currentTarget.tagName);
        }


        //第三個參數為 true/false. true代表 capture 方式,false代表bubble方式,預設為false
        document.getElementById('sampleSpanId').addEventListener('click',clickHandler);
        //document.getElementById('sampleDivId').addEventListener('click',clickHandler);這種方式和下面方式等同,預設為bubble
        document.getElementById('sampleDivId').addEventListener('click',clickHandler,false);
        document.getElementById(sampleAId).getEventListener('click',clickHandler,false);
    </script>
</html>      

當我們點選 test event phase 時,因為span,a,div都有事件綁定,是以會執行三個事件,那順序應該如何呢?首先先引入兩個概念:

1. target: 實際觸發者,即設定事件的元素,此處為span元素;

2. currentTarget: 目前觸發事件的元素,即目前在執行事件的元素。

針對包含多個元素的執行順序,首先先要知道DOM結構中的事件傳播方式。DOM中針對事件的傳播有三個階段:

1. capture(捕獲階段):從根元素到事件目标元素(不算目标元素)從上到下,例子中為 document -> body -> div -> a

2. target(事件目标階段):目标元素,例子中為 span

3. bubble(冒泡階段)從目标元素(不算目标元素)到根元素從下到上,例子中為 a -> div -> body -> document

針對每個事件來說, 傳播的順序為 capture -> target -> bubble , 例子中為 document -> body -> div -> a -> span -> a -> div -> body -> document

通過傳播順序我們可以看到,除了事件源,其他元素在傳播的時候都會經曆兩次,但針對其事件僅會調用一次,是以這就是 事件綁定時需要聲明你的事件階段為 capture 還是 bubble,因為不同的階段會有不同的事件的調用順序,即不同的傳播路徑。

demo中針對預設bubble的調用,是以列印出來的結果為:

SPAN

A

DIV

如果把demo中的參數從false轉換為true,

document.getElementById('sampleSpanId').addEventListener('click',clickHandler,true);
document.getElementById('sampleDivId').addEventListener('click',clickHandler,true);
document.getElementById('sampleAId').addEventListener('click',clickHandler,true);      

則列印出來的結果為:

如果将demo中的參數部分div标簽設定為false,a标簽設定為true,

document.getElementById('sampleSpanId').addEventListener('click',clickHandler,true);
document.getElementById('sampleDivId').addEventListener('click',clickHandler,false);
document.getElementById('sampleAId').addEventListener('click',clickHandler,true);      

二.階段(Phase)在lightning中的使用

官方文檔裡面給出了一個例子很好,在這裡直接引用過來。

1. 建立一個事件:compEvent

1 <aura:event type="COMPONENT" description="Event template">
2 </aura:event>      

2.建立eventBubblingEmitter.cmp及其對應的controller.js用于注冊事件以及點選按鈕後觸發事件。

1 <aura:component>
2     <aura:registerEvent name="bubblingEvent" type="c:compEvent" />
3     <lightning:button onclick="{!c.fireEvent}" label="Start Bubbling"/>
4 </aura:component>      
1 ({
2     fireEvent : function(cmp) {
3         var cmpEvent = cmp.getEvent("bubblingEvent");
4         cmpEvent.fire();
5     }
6 })      

3.建立eventBubblingGrandChild.cmp,包含了eventBubblingEmitter元件以及添加了事件的handler,一個元素可以通過<aura:handler>标簽執行他自身的事件。

1 <aura:component>
2     <aura:handler name="bubblingEvent" event="c:compEvent" action="{!c.handleBubbling}"/>
3     <div class="grandchild">
4         <c:eventBubblingEmitter />
5     </div>
6 </aura:component>      
1 ({
2     handleBubbling : function(component, event) {
3         console.log("Grandchild handler for " + event.getName());
4     }
5 })      

4.建立eventBubblingChild.cmp。此事件緊使用aura:handler聲明了句柄,并未包含任何其他的component

1 <aura:component>
2     <aura:handler name="bubblingEvent" event="c:compEvent" action="{!c.handleBubbling}"/>
3     <div class="child">
4         {!v.body}
5     </div>
6 </aura:component>      
1 ({
2     handleBubbling : function(component, event) {
3         console.log("Child handler for " + event.getName());
4     }
5 })      

5.建立eventBubblingParent.cmp以及對應的controller。

1 <aura:component>
2     <aura:handler name="bubblingEvent" event="c:compEvent" action="{!c.handleBubbling}"/>
3     <div class="parent">
4         <c:eventBubblingChild>
5             <c:eventBubblingGrandchild />
6         </c:eventBubblingChild>
7     </div>
8 </aura:component>      
1 ({
2     handleBubbling : function(component, event) {
3         console.log("Parent handler for " + event.getName());
4     }
5 })      

 6. 建立eventBubblingParentApp.app.用于可視化顯示這些元件元素。

1 <aura:application>
2     <c:eventBubblingParent />
3 </aura:application>      

結果展示:

salesforce lightning零基礎學習(五) 事件階段(component events phase)

這裡可能有兩個疑問:

1.為什麼第一個注冊了事件以後,後期的直接使用aura:handler來進行執行事件,而不是每一個都需要注冊事件?

2.為什麼輸出的結果是兩項,而不是三項Log?

分析:

1. 當父元素元件在他的标簽裡面執行個體化了子元素的元素元件後,可以直接使用aura:handler來執行事件。

2.我們可以看到eventBubblingParent.cmp中層級結構為 eventBubblingParent > eventBubblingChild > eventBubblingGrandchild. 盡管eventBubblingChild是eventBubblingGrandchild的父級結構,但是lightning component event中,在元件元素中,隻有最外層元素元件事件才可以被處理。是以這裡面隻會執行上述兩個。

我們來将eventBubblingChild.cmp修改一下:

1 <aura:component>
2     <aura:handler name="bubblingEvent" event="c:compEvent" action="{!c.handleBubbling}"/>
3     <!-- <div class="child">
4         {!v.body}
5     </div> -->
6     <div class="child">
7         <c:eventBubblingGrandchild />
8     </div>
9 </aura:component>      

此元件元素中, eventBubblingChild 變成了eventBubblingGrandchild的最外層的元件元素,是以輸出的時候回輸出三個log結果。

salesforce lightning零基礎學習(五) 事件階段(component events phase)

我們可以看一下這些元件元素構成的傳播順序:

Parent handler -> Child handler -> grandchild -> Child handler -> Parent handler.

針對Bubble方式,從事件源到根為 grandchild -> Child handler -> Parent handler

針對Capture方式,從根到事件源為Parent handler -> Child handler -> grandchild.

上面的例子都是使用Bubble方式的,下面再次修改eventBubblingChild,使他 handler方式修改成capture。差別僅限于添加phase屬性。

1 <aura:component>
2     <aura:handler name="bubblingEvent" event="c:compEvent" action="{!c.handleBubbling}" phase="capture"/>
3     <!-- <div class="child">
4         {!v.body}
5     </div> -->
6     <div class="child">
7         <c:eventBubblingGrandchild />
8     </div>
9 </aura:component>      
salesforce lightning零基礎學習(五) 事件階段(component events phase)

 事件Event對象也包含了很多方法,常用的有以下幾種:

1.event.setParam(obj):此方法用于事件處理時,添加事件的參數,正常事件聲明時,允許有param,此demo中因為便于展示,是以沒有添加param,參看上節;

2.event.fire():此方法用于觸發事件;

3.event.stopPropagation(): 此方法用于停止事件在其他的元件元素傳播;

上面内容中将Grandchild handler 的controller.js修改成以下:

1 ({
2     handleBubbling : function(component, event) {
3         console.log("Grandchild handler for " + event.getName());
4         event.stopPropagation();
5     }
6 })      

結果展示:事件執行完 Grandchild handler以後,因為handler中執行了 stopPropagation方法,則後續的handler均不再執行。

salesforce lightning零基礎學習(五) 事件階段(component events phase)

4.event.pause():用于暫停正在執行的事件,直到調用event.resume()方法以後才會繼續傳播事件。這種常用于通過異步傳回結果來判斷後續要如何執行的場景;

5.event.resume():和 event.pause()一組。

總結:此篇主要講解lightning component event中事件的兩個階段的差別以及用法,兩種用法沒有什麼缺點和優點的劃分,具體要使用哪種階段需要考慮你的業務場景要怎樣的順序傳播事件。篇中内容有錯誤的地方歡迎指正,有不懂得地方歡迎留言。

作者:zero

部落格位址:http://www.cnblogs.com/zero-zyq/

本文歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接配接

個人下載下傳了一些相關學習的PDF檔案,如果需要下載下傳請通路百度雲 點選此處通路 密碼:jhuy

如果文章的内容對你有幫助,歡迎點贊~

為友善手機端檢視部落格,現正在将部落格遷移至微信公衆号:Salesforce零基礎學習,歡迎各位關注。

繼續閱讀