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);

则打印出来的结果为:

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 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>

结果展示:

这里可能有两个疑问:

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

结果展示:

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

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>

结果展示:

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

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

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

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

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏GreenLeaves

JavaScript之充实文档的内容

1、我们在平时的开发中会碰到一些缩略语如:XML,HTML,API等专业术语;为了能使用户,更好的了解术语的意思,我们通常会给<abbr></abbr>标签加一...

20760
来自专栏施炯的IoT开发专栏

《101 Windows Phone 7 Apps》读书笔记-Silly Eye

课程内容 Ø Animation Ø Event Triggers Ø Named Resources Ø Settings Page Ø Color...

21570
来自专栏HTML5学堂

如何优化前端页面 / 如何优化网页

HTML5学堂:如何优化前端页面 / 如何优化网页。作为前端开发人员来说,不但要开发出能兼容各大主流浏览器的页面,而且还需要懂得去优化前端页面。本文主要给大家讲...

49780
来自专栏练小习的专栏

如何让一个层位于iframe之上.flash之上

蓝色理想 goos 摘录一段CSS参考手册的话: z-index 属性设置元素的堆叠顺序。拥有更高堆叠顺序的元素总是会处于堆叠顺序较低的元素的前面。 注释:元素...

21790
来自专栏xx_Cc的学习总结专栏

iOS-UITextField 全面解析iOS中UITextField 使用全面解析UITextField的代理方法通知UITextField 在storyboard 中设置属性

66460
来自专栏柠檬先生

NEC html规范

HTML规范 - 整体结构 HTML基础设施 文件应以“<!DOCTYPE ......>”首行顶格开始,推荐使用“<!DOCTYPE html>”。 必须申明...

30850
来自专栏阮一峰的网络日志

CSS in JS 简介

1、 以前,网页开发有一个原则,叫做"关注点分离"(separation of concerns)。 ? 它的意思是,各种技术只负责自己的领域,不要混合在一起,...

36370
来自专栏全沾开发(huā)

总结CSS3新特性(Animation篇)

总结CSS3新特性(Animation篇) 动画(Animation),是CSS3的亮点.//之一 通过animation属性指定@k...

34360
来自专栏Linux驱动

24.QTableView函数使用,右击菜单实现

对于QStandardItem的setData()成员 函数的第二个参数role 是模型数据角色 

15140
来自专栏hightopo

基于 HTML5 的电力接线图 SCADA 应用

19530

扫码关注云+社区

领取腾讯云代金券