前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >24 事件绑定、事件修饰符与事件三阶段

24 事件绑定、事件修饰符与事件三阶段

作者头像
LIYI
发布2020-02-13 11:59:30
1.3K0
发布2020-02-13 11:59:30
举报
文章被收录于专栏:艺述论专栏艺述论专栏

问题:1,vue的capture修饰符是如何实现的?2,为什么要使用passive,vue的passive修饰符的功能是如何实现的?

代码语言:javascript
复制
目录

事件绑定的三种方式
事件修饰符
    1,stop
    2,多个修饰符串连
    3,只阻止默认行为
    4,capture
    5,self
    6,once
    7,passvie
js事件机制的三个阶段
源码

事件绑定的三种方式

在vue模板中的组件上绑定事件执行代码,有三种方式:

1,将代码直接内嵌写在v-on指令表达式中,例如:

代码语言:javascript
复制
<!-- 直接写在v-on指令表达式中 -->
<button v-on:click="counter += 1">Add 1</button>
<p>The button above has been clicked {{ counter }} times.</p>

2,绑定到一个事件方法上:

代码语言:javascript
复制
<!-- 绑定到事件方法 -->
<button v-on:click="greet">Greet</button>
name: "DealWithEvent",
  data: () => ({
    name: "xx",
  }),
greet: function(event) {
  console.log(this.name, event.target.tagName);
},

在事件方法中,默认第一个参数是特殊变量$event,不管在模板中有没有通过greet($event)显式传递。

在控制台中,打印的this.name并不是“DealWithEvent”,而是“xx”。事件方法的作用域是当前组件,this指向当前的组件实例vm。这是因为在vue源码中,new Function(code..)在执行时绑定的作用域就是当前的组件的作用域。

tagName是html元素的属性,是html5的特征,并不是vue设置的。

3,还有一种方式,在指令表达式中调用事件方法:

代码语言:javascript
复制
<!-- 在v-on指令表达式中调用方法 -->
    <button v-on:click="greet2({'name':123,'target':{'tagName':'button'}},$event)">Greet2</button>

这种方式的好处,就是可以主动使用特殊变量$event,还可以传递其它参数给事件方法。

那么三种方式如何使用呢?

如果是简单的代码,直接写在表达式中;如果代码较多,扩展出一个事件方法,写在mehtods中;如果默认的事件绑定方式不能满足需求,再用第三种方法。

事件修饰符

为简便开发,vue为事件绑定以声明的方式提供了一些修饰符。这些修饰符实现的功能,以代码同样也可以实现,但直接写在模板里,更简洁方便。

1,stop

在列表中阻止事件向上冒泡

代码语言:javascript
复制
<!-- 事件不再冒泡,停止传播 -->
<a
  v-on:click.prevent="doThat"
  style=".."
>
  <a
    v-on:click.stop="doThis"
    style=".."
  >阻止事件的默认行为</a>
</a>

使用prevent是阻止事件的默认行为,使用prevent相当于调用event.preventDefault()。

使用stop是阻止事件进一步派发,相当于调用event.stopPropagation()。

这个示例的运行效果是,当单击内部的链接a时,只执行一个doThis函数;而如何将stop修饰符去了,doThat也会派发。

2,多个修饰符串连

事件修饰符可以串连并用,例如:

代码语言:javascript
复制
<!-- 修饰符可以串联 -->
<a v-on:click.stop.prevent="doThat">prevent & stop</a>

一般两个修饰符都可以并用,只有passive与prevent两个是矛盾的,不能并用。

3,只阻止默认行为

只使用修饰符,不监听事件,例如:

代码语言:javascript
复制
<!-- 只有修饰符 -->
<form v-on:submit.prevent>prevent只有修饰符,没有事件监听</form>

这种情况下,只是阻止表单中submit按钮单击时的默认提交行为,但是并不监听任何事件。

在表单上使用该修饰符,相当于在该表单上的所有事件,默认都调用event.preventDefault。

4,capture

监听捕捉阶段的事件,例如:

代码语言:javascript
复制
<div v-on:click.capture.stop="doThis">
  capture捕获阶段..
  <br />
  <a
    v-on:click.prevent="doThat"
    style=".."
  >阻止事件的默认行为</a>
</div>

运行效果:

在这个示例中,当单击发生在内部的灰色区域上时,如果加了stop,只响应外部的监听;只有去掉stop,单击内部才有两个响应。

capture.stop同时使用的作用是,在捕捉阶段就监听事件,并且阻止事件进一步派发,也就是说,事件还没进门,就已经被门卫挂在门外了。

vue的capture修饰符是如何实现的?

capture修饰符的实现,是通过js的基本API完成的。在js的事件监听上,存在这样一种形式:

代码语言:javascript
复制
target.addEventListener(type, listener, useCapture);

第三个参数useCapture默认为false,只有为true时,才会在捕捉阶段触发事件函数的执行。

附useCapture的参数说明:

代码语言:javascript
复制
useCapture  可选
Boolean,在DOM树中,注册了listener的元素, 是否要先于它下面的EventTarget,调用该listener。 当useCapture(设为true) 时,沿着DOM树向上冒泡的事件,不会触发listener。当一个元素嵌套了另一个元素,并且两个元素都对同一事件注册了一个处理函数时,所发生的事件冒泡和事件捕获是两种不同的事件传播方式。事件传播模式决定了元素以哪个顺序接收事件。进一步的解释可以查看 事件流 及 JavaScript Event order 文档。如果没有指定, useCapture 默认为 false 。 

从说明可以看出,当使用useCapturetrue时,在从目标节点向上的冒泡阶段中,便不会再触发这个listener的执行。这也很理解,因为它在捕捉阶段已经被执行过了。但如果在同一个节点上,或相邻的其它节点上,使用useCapture=false注册了事件监听,其事件函数仍然是会执行的。

5,self

只在目标阶段监听事件,例如:

代码语言:javascript
复制
<!-- 只当在 event.target 是当前元素自身时触发处理函数 -->
<div v-on:click.self="doThat">self</div>

在这个示例中,只有单击发生在这个div上时,不是发生在包含它的父级上,是正好发生在它的身上,事件派发函数执行。

以js方式实现同样的效果,需要启用捕捉阶段的监听,并判断当前的事件对象是不是这个div,远不如加一个self修饰符简单。

6,once

只监听一次,例如:

代码语言:javascript
复制
<!-- 只监听一次 -->
<a v-on:click.once="doThis">once</a>

这个最简单,监听事件执行函数,执行完了就把事件监听移除了。在vue的事件机制中,vm.$once具有同样的功能。

7,passvie

使用passive修饰符,提高渲染效率

代码语言:javascript
复制
<!-- 使用passive及时渲染,改进渲染效果 -->
<div v-on:scroll.passive="onScroll" style="width:300px;height:300px;overflow-y: scroll;">
  <div v-for="n in 100" :key="n" style="width:100%;height:20px;background: gray;">{{n}}</div>
</div>

运行效果:

在这个示例中,使用了passive修饰符,不等函数体执行完,div的默认滚动行为就已经发生了。如果函数体的代码执行起来开销大,使用这个特性可以显著改善UE体验。

passive要求使用组件的默认滚动行为,所以与阻止默认行为的prevent修饰符就不能同时使用。prevent 是拦截默认事件,passive是不拦截默认事件。

那么使用passive的意义在哪里?

浏览器只有等内核线程执行到事件函数的代码时,才能知道函数内部是否会调用了preventDefault函数来阻止事件的默认行为,所以浏览器本身是没有办法对这种场景进行优化的。在这种场景下,如果涉及到用户交互的事件无法快速产生,会导致页面无法及时渲染而让用户感到页面卡顿。

现在加上passive就是为了告诉浏览器,不用每次查询了,我们没用preventDefault阻止默认动作。

对于一些频繁触发的交互事件,例如scroll、touchmove、mouseover等,都可以使用passive提高浏览器的工作效率。

vue的passive修饰符的功能是如何实现的?

vue是基于js本身的API实现的。事件监听函数有一个形式是这样的:

代码语言:javascript
复制
target.addEventListener(type, listener, options);

其实第三个参数options,可以包括一个passive属性:

代码语言:javascript
复制
passive: Boolean,设置为true时,表示 listener 永远不会调用 preventDefault()。如果 listener 仍然调用了这个函数,客户端将会忽略它并抛出一个控制台警告。

js事件机制的三个阶段

js是一门基于ECMAScript标准的语言,与ActionScript3是同源语言。js的事件机制与as3一样,具有三个阶段:

窗体Document先是监听到事件,然后一级一级向内部的子组件派发,直到找到目标节点,这是第一阶段:捕捉。

找到了目标节点,即鼠标或触控点点中的元素,这是第二阶段:目录。

从第二阶段向上走,一路冒泡派发,这是最后一个阶段:冒泡。

平时开发默认监听的事件,都不包括捕捉阶段。因为捕捉阶段的事件在开启监听时,需要显式将addEventListener的参数capture设置为true

组件在DOM树中是分层的,有父组件,有子组件。在每一层中派发的事件,称为代。方法event.stopPropagation()阻止的是事件向下一代派发;而方法event.stopImmediatePropagation()阻止的是同一代中其它事件函数的执行。

源码

代码语言:javascript
复制
https://git.code.tencent.com/shiqiaomarong/vue-go-rapiddev-example/tags/v20200120

涉及本文的源码主要在:

代码语言:javascript
复制
vue-and-go-example/simple-vue-project/src/DealWithEvent.vue

参考链接

  • https://developer.mozilla.org/en-US/docs/Web/API/Element/tagName
  • https://blog.csdn.net/ckxkobe/article/details/84820805
  • https://www.jianshu.com/p/b12d0d3ad4c1
  • https://developer.mozilla.org/zh-CN/docs/Web/API/EventTarget/addEventListener

相关阅读

  • 1 如何选择一个 vue ui 框架?
  • 2 梳理 50 年人机交互界面发展史,得出这个规律,开发框架的选择不再迷茫
  • 3 vue 开发常用工具及配置一
  • 4 vue 开发常用工具及配置二
  • 5 vue 开发常用工具及配置三
  • 6 vue 开发常用工具及配置四:推荐一个 mock 工具
  • 7 vue 开发常用工具及配置五:hash 与缓存控制
  • 8 vue 开发常用工具及配置六:认识各种 loader
  • 9 vue 开发常用工具及配置七:处理资源加载问题
  • 10 vue 开发常用工具及配置八:scoped CSS 模块化
  • 11 css 基本功:引入方式及选择器相关
  • 12 手写配置启动一个 vue2 项目
  • 13 声明式渲染与 data 函数
  • 14 上线后不想让人看到源码怎么做?
  • 15 v-if 条件渲染与 v-for 列表渲染
  • 16 处理表单数据与父子组件之间的数据交换
  • 17 vue 组件化基础
  • 18 vue 实例及其双向绑定的实现原理
  • 19 vue 模板语法及简要实现原理
  • 20 vue计算属性和侦听器
  • 21 vue 组件中 Class 的绑定
  • 22 内联样式的绑定
  • 23 列表渲染与“就地复用”原则
  • 24 事件绑定、事件修饰符与事件三阶
本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-01-20,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 艺述论 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 事件绑定的三种方式
  • 事件修饰符
    • 1,stop
      • 2,多个修饰符串连
        • 3,只阻止默认行为
          • 4,capture
            • 5,self
              • 6,once
                • 7,passvie
                • js事件机制的三个阶段
                • 源码
                • 参考链接
                • 相关阅读
                相关产品与服务
                腾讯云小微
                腾讯云小微,是一套腾讯云的智能服务系统,也是一个智能服务开放平台,接入小微的硬件可以快速具备听觉和视觉感知能力,帮助智能硬件厂商实现语音人机互动和音视频服务能力。
                领券
                问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档