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
<aura:event type="COMPONENT" description="Event template">
</aura:event>
2.创建eventBubblingEmitter.cmp及其对应的controller.js用于注册事件以及点击按钮后触发事件。
<aura:component>
<aura:registerEvent name="bubblingEvent" type="c:compEvent" />
<lightning:button onclick="{!c.fireEvent}" label="Start Bubbling"/>
</aura:component>
({
fireEvent : function(cmp) {
var cmpEvent = cmp.getEvent("bubblingEvent");
cmpEvent.fire();
}
})
3.创建eventBubblingGrandChild.cmp,包含了eventBubblingEmitter组件以及添加了事件的handler,一个元素可以通过<aura:handler>标签执行他自身的事件。
<aura:component>
<aura:handler name="bubblingEvent" event="c:compEvent" action="{!c.handleBubbling}"/>
<div class="grandchild">
<c:eventBubblingEmitter />
</div>
</aura:component>
({
handleBubbling : function(component, event) {
console.log("Grandchild handler for " + event.getName());
}
})
4.创建eventBubblingChild.cmp。此事件紧使用aura:handler声明了句柄,并未包含任何其他的component
<aura:component>
<aura:handler name="bubblingEvent" event="c:compEvent" action="{!c.handleBubbling}"/>
<div class="child">
{!v.body}
</div>
</aura:component>
({
handleBubbling : function(component, event) {
console.log("Child handler for " + event.getName());
}
})
5.创建eventBubblingParent.cmp以及对应的controller。
<aura:component>
<aura:handler name="bubblingEvent" event="c:compEvent" action="{!c.handleBubbling}"/>
<div class="parent">
<c:eventBubblingChild>
<c:eventBubblingGrandchild />
</c:eventBubblingChild>
</div>
</aura:component>
({
handleBubbling : function(component, event) {
console.log("Parent handler for " + event.getName());
}
})
6. 创建eventBubblingParentApp.app.用于可视化显示这些组件元素。
<aura:application>
<c:eventBubblingParent />
</aura:application>
结果展示:
这里可能有两个疑问:
1.为什么第一个注册了事件以后,后期的直接使用aura:handler来进行执行事件,而不是每一个都需要注册事件?
2.为什么输出的结果是两项,而不是三项Log?
分析:
1. 当父元素组件在他的标签里面实例化了子元素的元素组件后,可以直接使用aura:handler来执行事件。
2.我们可以看到eventBubblingParent.cmp中层级结构为 eventBubblingParent > eventBubblingChild > eventBubblingGrandchild. 尽管eventBubblingChild是eventBubblingGrandchild的父级结构,但是lightning component event中,在组件元素中,只有最外层元素组件事件才可以被处理。所以这里面只会执行上述两个。
我们来将eventBubblingChild.cmp修改一下:
<aura:component>
<aura:handler name="bubblingEvent" event="c:compEvent" action="{!c.handleBubbling}"/>
<!-- <div class="child">
{!v.body}
</div> -->
<div class="child">
<c:eventBubblingGrandchild />
</div>
</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属性。
<aura:component>
<aura:handler name="bubblingEvent" event="c:compEvent" action="{!c.handleBubbling}" phase="capture"/>
<!-- <div class="child">
{!v.body}
</div> -->
<div class="child">
<c:eventBubblingGrandchild />
</div>
</aura:component>
结果展示:
事件Event对象也包含了很多方法,常用的有以下几种:
1.event.setParam(obj):此方法用于事件处理时,添加事件的参数,正常事件声明时,允许有param,此demo中因为便于展示,所以没有添加param,参看上节;
2.event.fire():此方法用于触发事件;
3.event.stopPropagation(): 此方法用于停止事件在其他的组件元素传播;
上面内容中将Grandchild handler 的controller.js修改成以下:
({
handleBubbling : function(component, event) {
console.log("Grandchild handler for " + event.getName());
event.stopPropagation();
}
})
结果展示:事件执行完 Grandchild handler以后,因为handler中执行了 stopPropagation方法,则后续的handler均不再执行。
4.event.pause():用于暂停正在执行的事件,直到调用event.resume()方法以后才会继续传播事件。这种常用于通过异步返回结果来判断后续要如何执行的场景;
5.event.resume():和 event.pause()一组。
总结:此篇主要讲解lightning component event中事件的两个阶段的区别以及用法,两种用法没有什么缺点和优点的划分,具体要使用哪种阶段需要考虑你的业务场景要怎样的顺序传播事件。篇中内容有错误的地方欢迎指正,有不懂得地方欢迎留言。
salesforce lightning零基础学习(五) 事件阶段(component events phase)的更多相关文章
- salesforce lightning零基础学习(四) 事件(component events)简单介绍
lightning component基于事件驱动模型来处理用户界面的交互.这种事件驱动模型和js的事件驱动模型也很相似,可以简单的理解成四部分: 1.事件源:产生事件的地方,可以是页面中的输入框,按 ...
- salesforce lightning零基础学习(十五) 公用组件之 获取表字段的Picklist(多语言)
此篇参考:salesforce 零基础学习(六十二)获取sObject中类型为Picklist的field values(含record type) 我们在lightning中在前台会经常碰到获取pi ...
- salesforce lightning零基础学习(十七) 实现上传 Excel解析其内容
本篇参考: https://developer.mozilla.org/zh-CN/docs/Web/API/FileReader https://github.com/SheetJS/sheetjs ...
- salesforce lightning零基础学习(十一) Aura框架下APP构造实现
前面的一些lightning文章讲述了aura的基础知识,aura封装的常用js以及aura下的事件处理.本篇通过官方的一个superbadge来实现一个single APP的实现. superbad ...
- salesforce lightning零基础学习(八) Aura Js 浅谈一: Component篇
我们在开发lightning的时候,常常会在controller.js中写 component.get('v.label'), component.set('v.label','xxValue'); ...
- salesforce lightning零基础学习(九) Aura Js 浅谈二: Event篇
上一篇介绍了Aura Framework中 Component类的部分方法,本篇将要介绍Event常用的方法. 1. setParam (String key , Object value):设置事件 ...
- salesforce lightning零基础学习(二) lightning 知识简单介绍----lightning事件驱动模型
看此篇博客前或者后,看一下trailhead可以加深印象以及理解的更好:https://trailhead.salesforce.com/modules/lex_dev_lc_basics 做过cla ...
- salesforce lightning零基础学习(三) 表达式的!(绑定表达式)与 #(非绑定表达式)
在salesforce的classic中,我们使用{!expresion}在前台页面展示信息,在lightning中,上一篇我们也提及了,如果展示attribute的值,可以使用{!v.expresi ...
- salesforce lightning零基础学习(一) lightning简单介绍以及org开启lightning
lightning对于开发salesforce人员来说并不陌生,即使没有做过lightning开发,这个名字肯定也是耳熟能详.原来的博客基本都是基于classic基于配置以及开发,后期博客会以ligh ...
随机推荐
- nodejs+https 使用openssl (window)
HTML的getUsermedia必是要安全的连接 比如 localhost.127.0.0.1 .https chrome才让调用摄像头 1.申请域名.备案.域名解析 2.openssl生成 打开g ...
- css3回顾 checkbox
<div class="checkBox"> <input type="checkbox" id="check1"> ...
- vba文件对比并高亮显示
每月月底要和人事要离职人员名单,并账号列表里删除已经离职人员的账号,如下代码通过将账号列表与人事发来的离职清单进行对比,高亮找出离职人员的账号,并进行删除. Sub DeleteMain() Dim ...
- react 子元素修改父元素值的一个偏方,虽然简单,但是不建议用,
this.state.obj = { name: "小明" } <Zizujian obj={this.state.obj} /> // 子组件这样修改父元素的值 // ...
- Win 10 安装手机驱动
直接上图,看图操作即可.
- flask更改已有的response
今天遇到个问题,需要更改返回的response,但框架已经生成了一个response,所以需要直接更改. 试着找了找解决办法,最终解决方式如下: #下文中payload的类型是 # class Res ...
- C#Dictionary源码
Dictionary Dictionary与hashtable的区别:dictionary支持泛型. 通常处理哈希冲突的方法有:开放地址法,再哈希法,链地址法,建立一个公共栈区等. 在哈希表上进行查 ...
- 走进JDK(六)------ArrayList
对于广大java程序员来说,ArrayList的使用是非常广泛的,但是发现很多工作了好几年的程序员不知道底层是啥...这我觉得对于以后的发展是非常不利的,因为java中的每种数据结构的设计都是非常完善 ...
- s6-2 UDP
User Datagram Protocol UDP 是一个无连接的(connectionless)的传输层协议 UDP传输数据段,无须建立连接 UDP 在 RFC 768中描述 很多 ...
- 《mysql必知必会》学习_第14章_20180806_欢
第14章:使用子查询. 子查询是镶嵌在其他查询里面,相当其他的select查询的条件来. P91 select order_num from where prod_id='tnt2'; #检索条件 ...