继续浏览精彩内容
慕课网APP
程序员的梦工厂
打开
继续
感谢您的支持,我会继续努力的
赞赏金额会直接到老师账户
将二维码发送给自己后长按识别
微信支付
支付宝支付

salesforce lightning零基础学习(五) 事件阶段(component events phase)

慕森卡
关注TA
已关注
手记 380
粉丝 120
获赞 527

上一篇介绍了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);

则打印出来的结果为:

DIV
A
SPAN

如果将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);

则打印出来的结果为:

A

SPAN

DIV

二.阶段(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 ="{!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>

结果展示:

https://img2.mukewang.com/5b5494270001214f11590412.jpg

 


这里可能有两个疑问:

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结果。

结果展示:

https://img4.mukewang.com/5b549440000104f911060453.jpg

我们可以看一下这些组件元素构成的传播顺序:

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>

 

结果展示:

https://img.mukewang.com/5b54945700017d2d14380469.jpg

 事件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均不再执行。

https://img1.mukewang.com/5b549475000139cf12410455.jpg

4.event.pause():用于暂停正在执行的事件,直到调用event.resume()方法以后才会继续传播事件。这种常用于通过异步返回结果来判断后续要如何执行的场景;

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

总结:此篇主要讲解lightning component event中事件的两个阶段的区别以及用法,两种用法没有什么缺点和优点的划分,具体要使用哪种阶段需要考虑你的业务场景要怎样的顺序传播事件。篇中内容有错误的地方欢迎指正,有不懂得地方欢迎留言。

原文出处:salesforce lightning零基础学习(五) 事件阶段(component events phase)


打开App,阅读手记
0人推荐
发表评论
随时随地看视频慕课网APP