vue中 点击事件的写法_vue中的事件:原生事件与自定义事件__Vue.js
模板编译 processAttrs
对于ast attributes处理(v-on/@)
利用onRE与dirRE来捕获事件
这里最重要的就是dynamic的判断,vue中可以用动态参数来命名事件名称,如@[prop],prop为data中的值。不过通常都是一个静态的事件名称如 @click
另一个核心方法就是addHandler
addHandler 往AST上添加events属性
1. 这里会对动态事件名称进行一些处理,也会对right,middle修饰符处理,另外对capture, passive, once的事件名称做了标记。分别添加 !, ~, # 符号。然后删除了对应属性值
2. 参数value为@click="handler"例子中的handler,在此处还在编译阶段handler本质上是一个string。然后对value做了处理,记录了模板解析event时候start和end的位置。
3. 对于单个事件有多回调函数绑定的情况,添加了一个important参数,以此来提前触发当前回调函数的执行
4. 另外,这里对鼠标的right和middle做了处理,在处理只有删除了对应属性值。对于键盘的事件没有做处理
AST -> code
修饰符:modifierCode
上面已经提到过了,本质上模板编译的时候会利用正则处理各种修饰符,然后根据对应关键词的生成代码。如常用的stop,prevent。
核心方法就是src/compiler/codegen/events.js的genHandler方法,以下是分析:
1. genHandlers
该方法就是简单的遍历events对象的键值对然后,对有无native修饰符与是否为dynamic事件做一个处理,其核心方法就是调用genHandler
genHandler
一些参数判断
事件函数的多种写法
在官方文档中演示了事件回调函数的多种写法,这些写法都在模板编译过程中进行了识别
下方三个正则表达式是模板编译时对event写法的判断依据,下面会有更详细的注释
1. 路径类写法
2. 箭头函数,匿名函数
3. 表达式 handler($event), a = 1
在vue中通常通过@click="handle($event)"来获取event对象,其实这里是vue在模板中做了一层包裹,将function($event){}套在handle($event)外部。
有修饰符的情况
修饰符在ast生成的过程中就已经捕获了,vue中对event事件的修饰符处理如下
先对修饰符做一个处理
最后座一层包裹,因为这里对键盘事件也做了处理,因此一定要拿到event对象
genCode
在处理完这些之后会生成字符串on:"…"/nativeOn:"…",最后生成render函数
组件初始化
组件初始化简单地说就是先对options做各种处理,最后执行渲染watcher,生成页面。
对native events的处理:
platforms/web/runtime/patch.js中有
const patch = createPatchFunction({nodeOps, modules})
modules源自:web/runtime/modules/index,导出含生命周期的对象**(非created周期)**
createPatchFunction
createPatchFunction往hooks内添加了updateDOMListeners,hooks为**并非是**组件的生命周期函数。在组件create与updated的时候就会触发updateDOMListeners函数。注册事件。
注意点: 这里create并非是组件created的**周期函数。**是在真实节点创建之后才会触发钩子,因此是可以拿到真实节点的。
updateDOMListeners
在调用modules.create的hook的时候触发了updateDOMListeners
其作用就是给用addEventListeners与removeEventListeners方法给真实dom节点添加事件。
updateListeners
将新旧事件进行对比更新。这里的add和remove可以给真实dom注册事件,也可以给组价注册事件。
占位符$vnode的真实dom事件:createComponent(部分)
对于组件而言,data.on赋值给listeners,把data.nativeOn赋值给data.on
data.on里面存放着的都是原生dom事件,组件内部的listeners都是用户自定义的事件。
因此,在组件patch过程中,创建组件的根节点的时候,就会把data.on内部的原生dom事件注册在dom上。
因此如果在h5元素使用native如 ,vue就会报错。这正是因为在这里做了处理,只有占位符vnode才可以有data.nativeOn的属性。是h5标签的节点不会调用createComponent方法,其data.on在创建节点的时候会绑定到节点上。
自定义事件(只针对组件间)
由createComponent函数可知,listeners存放了自定义事件。
在父子通讯的时候父组件只要v-on/@eventName,就可以监听到子组件emit出来的事件。
_init: initInternalComponent
创建子组件的时候会把占位符$vnode的$listeners传递给子组件的$options**(此时data.on已经是data.nativeOn,原始的data.on赋值给变量listeners)**
_init: initEvents
调用updateComponentListeners方法,最后还是调用了updateListeners方法(见前面文章注释)。
但是这里不同的是add和remove方法并非是document.addEventListener和document.removeEventListener
add/remove(vue中的发布订阅模式):
其实发布订阅模式比较简单,就不详细说明了,主要是add/remove方法。
小结
其实本质上,还是将父组件注册的回调函数传给了子组件的_events对象(让该函数存在于子组件中),但是看起来像是子组件调用了父组件的方法
eventBus
对于跨组件的组件通信,利用了vue实例可以有自身的_events对象,因此在Vue原型上创建一个空的vue实例,然后将vue所有组件上的函数都注册在这个实例对象的_events对象上,一次达到跨组件通信的目的
Vue.prototype.$bus=new Vue()
第三种情况:v-on="$listeners"
$listeners就是vnode.data.on的别称,因此通过$listeners就可以拿到父组件注册的非native事件。在爷孙组件通信的是可以使用$listeners通过父级组件将爷孙组件关联。
grand组件:
father组件: // 此处是grand的事件
son组件:this.$emit(“test”) // 将father的$listeners传入son,而father的$listeners包含grand的事件,因此就将grand的事件传入了son中。
AST解析
在模板解析的时候会用正则匹配v-on,对于v-on="$listeners",vue将这种写法视为指令(directive),有不同的策略
on指令
_g
这里将$listeners对象与data.on进行合并,通过v-on指令我们可以一次性对组件注册多个事件。
最后
vue的事件基本上就是这样,其实这里面牵扯到了最核心的组件初始化和更新流程,关于此部分在本文中并没有明确说明,只是大概提了一下,一是要单纯靠文字说明费时费力(代码含有大量递归),而是本文重点是关注vue中的事件,在后面的更深入了解整个机制后会尝试说明写一篇vue组件初始化及更新的文章。
版权声明:著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
作者: Simplyme0823
原文链接:https://juejin.im/post/6861206075744452622
vue中 点击事件的写法_vue中的事件:原生事件与自定义事件__Vue.js相关推荐
- vue中 点击事件的写法_vue实现绑定事件的方法实例代码详解
一.前言 vuejs中的事件绑定,使用来完成的,这里函数名是定义在Vue实例中的methods对象中的,Vue实例可以直接访问其中的方法. 二.事件绑定方式 1. 直接在标签中写js方法 执行方法的第 ...
- vue 点击div 获取位置_Vue中组件之间8种通信方式,值得收藏
之前写了一篇关于vue面试总结的文章, 有不少网友提出组件之间通信方式还有很多, 这篇文章便是专门总结组件之间通信的 vue是数据驱动视图更新的框架, 所以对于vue来说组件间的数据通信非常重要,那么 ...
- vue点击网页全屏_vue中实现点击变成全屏的多种方法
项目中有点击按钮实现全屏功能 方式一:js实现全屏 全屏 data: data() { return { fullscreen: false }; }, methods: screen() { let ...
- vue中 点击事件的写法_vue基础之事件v-onclick=函数用法示例
本文实例讲述了vue基础之事件v-οnclick=函数用法.分享给大家供大家参考,具体如下: v-on:click/mouseout/mouseover/dblclick/mousedown..... ...
- vue点击改变data值_vue 中自定义指令改变data中的值
通过局部自定义指令实现了一个拖动的指令 html: script: methods:{ set(x,y){ this.data.x=x; this.data.y=y; } }, directives: ...
- vue中进度条写法_vue中自制进度条
订单已提交,正在出票... :cell-style="{textAlign:'center'}" :data="tableData" border style= ...
- vue 关闭弹如何销毁子组件_vue中的eventBus会产生内存泄漏吗
eventBus是在vue中经常用来解决跨组件消息传递的问题,但对它的使用要特别注意,否则会产生很严重的后果. 引入 本文介绍了eventBus的实现原理,并介绍它如何在vue中使用,并举了一个具体的 ...
- props写法_Vue中props的用法知识点
Vue中props的详解 看一下官方文档: 组件实例的作用域是孤立的.这意味着不能 (也不应该) 在子组件的模板内直接引用父组件的数据.父组件的数据需要通过 prop 才能下发到子组件中. 也就是pr ...
- 前端vue里面点击加载更多_vue 原生添加滚动加载更多
vue中添加滚动加载更多,因为是单页面所以需要在跳出页面时候销毁滚动,要不会出现错乱.我们在mounted建立滚动,destroyed销毁滚动. mounted () { window.addEven ...
最新文章
- 再也不怕复现论文!arXiv携手Papers with Code,提交论文+上传代码一步到位
- 2018-2019-1 20165226 《信息安全系统设计基础》第4周学习总结
- css实现页面文字不换行、自动换行、强制换行
- python standardscaler_Python快速实战机器学习之数据预处理
- 实战演练!CISCO交换机端口安全一点通 (
- 浅谈:云桌面在我国高校的应用前景
- 计算机继续教育笔记,《继续教育中的学习技术》读书笔记
- git reset简介
- PHP数组常用方法(优化版)
- ANSI SQL标准和准则
- mac+python3+selenium做pc的界面自动化测试
- 访问学者博士后面签后的几种情况?
- session是什么?
- java url生成二维码
- mysql函数循环查询的数据_MySQL 查询树结构、循环查询、查看函数、视图、存储过程...
- Matlab产生正交矩阵
- 对于后台站点的用户活跃度统计 除了记录用户登陆时间进行筛选,还有没有别的方法
- GPS卫星同步时钟在超高压变电站中应用
- 边缘云平台架构及商用实践(联通)
- 深入浅出pytorch笔记——第三章,第四章
热门文章
- linux线程同步教程,多线程同步
- jmeter连接mysql数据库驱动_十八、JMeter实战-JDBC连接MySQL数据库
- 集成 websocket 的四种方案
- fastjson为什么默认是无序的
- springboot的thymeleaf一个页面中引入其它页面
- 华为鸿蒙热水器,美的华为跨界联合!搭载鸿蒙OS的美的产品双11上市
- java ssh 那一层应该捕获异常_ssh经典异常!
- linux时间跳变影响,MONGO 集群 修改linux主机时间后的影响
- 商城系统php功能模块,yershop商城系统的支付模块问题
- Spring Boot————Web应用启动时自动执行ApplicationListener用法