vue中的$on,$emit,$once,$off源码实现
这几种模式是基于订阅观察者模式的,维护一个事件中心,on的时候将事件按名称存在事件中心里,称之为订阅者,然后emit将对应的事件进行发布,去执行事件中心里的对应的监听器。
第一步就是创建一个构造构造,维护一个事件中心events
function EventEmiter(){
this.events = {}
}
$on
//event可以是事件名数组
EventEmiter.prototype.on = function(event,cb){
//多个事件
if(event instanceof Array){
event.forEach(fn=>this.on(fn,cb))
}
//单个事件
if(this.events[event]){
this.events[event].push(cb)
}else{
this.events[event] = [cb]
}
}
$emit
//cb 参数:单个事件名,args参数 this.emit('evt',a,b,c)
EventEmiter.prototype.emit = function(event){
let args = Array.from(arguments).slice(1)
let cbs = this.events[event];
if(cbs){
cbs.forEach(cb=>cb.apply(this,args))
}
}
$once
// 事件回调执行一次就清除事件,参数:单个事件名,单个监听器
EventEmiter.prototype.once = function(event,cb){
function oneTime(){
//先执行回调,然后清除该事件的对应回调
cb.apply(this,arguments)
this.off(event,cb)
}
//on函数的fn属性添加一个标记,cb,方便循环off清除(提供了事件与回调的时候)
oneTime.cbName = cb;
this.on(event,oneTime);
}
$off
/*移除自定义事件监听器。
如果没有提供参数,则移除所有的事件监听器;
如果只提供了事件,则移除该事件所有的监听器;
如果同时提供了事件与回调,则只移除这个回调的监听器。
*/
EventEmiter.prototype.off = function(event,cb){
if(!arguments){
this.events = Object.create(null)
}
if(event instanceof Array){
event.forEach(evt=>this.off(evt,cb))
}
if(!cb){
this.events[event] = null
}
if(cb){
let cbs = this.events[event]
if(cbs){
for(let i = 0;i<cbs.length;i++){
if(cb === cbs[i] || cb === cbs[i].cbName){
cbs.splice(i,1)
break
}
}
}
}
}
总结:其实原理非常简单,要注意的是$once 不是直接$on提交对应的回调函数,而是包装成另外的On函数,On函数作为回调Push进事件中心。On函数本身的作用是执行一次事件的回调,然后就立马$off去出该事件的监听回调。同时,On函数已经不是原来的cb回调了,所以为了待会$off的时候能准确找到背后的那个cb,所以给On函数添加了属性方便找到它
vue中的$on,$emit,$once,$off源码实现的更多相关文章
- Tyrion中文文档(含示例源码)
Tyrion是一个基于Python实现的支持多个WEB框架的Form表单验证组件,其完美的支持Tornado.Django.Flask.Bottle Web框架.Tyrion主要有两大重要动能: 表单 ...
- Tyrion 中文文档(含示例源码)
原文出处: Mr.Seven Tyrion是一个基于Python实现的支持多个WEB框架的Form表单验证组件,其完美的支持Tornado.Django.Flask.Bottle Web框架.Ty ...
- (转)Eclipse中需要查看某个类的源码,直接按住Ctrl 然后点击想要查看的类或则方法
文章转自:http://blog.sina.com.cn/s/blog_52f623240102vpcr.html 在Eclipse中需要查看某个类的源码,直接按住Ctrl 然后点击想要查看的 ...
- java中的==、equals()、hashCode()源码分析(转载)
在java编程或者面试中经常会遇到 == .equals()的比较.自己看了看源码,结合实际的编程总结一下. 1. == java中的==是比较两个对象在JVM中的地址.比较好理解.看下面的代码: ...
- maven项目在eclipse中debug时看不到源码?
就像图中一样,看不到源码,但是能step over,也可查看变量值,点击edit source lookup path,选定项目的一瞬间源码会出来,但马上又变回原样了,求大神指教~ 我也遇到这个问题了 ...
- Java生鲜电商平台-SpringCloud微服务架构中网络请求性能优化与源码解析
Java生鲜电商平台-SpringCloud微服务架构中网络请求性能优化与源码解析 说明:Java生鲜电商平台中,由于服务进行了拆分,很多的业务服务导致了请求的网络延迟与性能消耗,对应的这些问题,我们 ...
- Spring中AOP相关的API及源码解析
Spring中AOP相关的API及源码解析 本系列文章: 读源码,我们可以从第一行读起 你知道Spring是怎么解析配置类的吗? 配置类为什么要添加@Configuration注解? 谈谈Spring ...
- 将Android源码导入eclipse中的方法以及编译Android源码指定模块
本文博客地址:http://blog.csdn.net/qq1084283172/article/details/53365659 将android源码导入eclipse.androidstudio. ...
- Vue3中的响应式对象Reactive源码分析
Vue3中的响应式对象Reactive源码分析 ReactiveEffect.js 中的 trackEffects函数 及 ReactiveEffect类 在Ref随笔中已经介绍,在本文中不做赘述 本 ...
随机推荐
- js数组与字符串相互转换
一.数组转字符串(将数组元素用某个字符连接成字符串) var a, b;a = new Array(0,1,2,3,4);b = a.join("-"); 二.字符串转数组(将字符 ...
- mvc 中Request[""]与Request.QueryString[""]
1.Request[""]与Request.QueryString[""]获取不到值时返回null: 2.Request[""]与Reque ...
- Python3.4 获取百度网页源码并保存在本地文件中
最近学习python 版本 3.4 抓取网页源码并且保存在本地文件中 import urllib.request url='http://www.baidu.com' #上面的url一定要写明确,如果 ...
- java基础--常用函数总结
java基础--常用函数总结 2019-3-16-23:28:01-----云林原创 1.split()字符串分割函数 将一个字符串分割为子字符串,然后将结果作为字符串数组返回. 2.Math.flo ...
- 有关satement与preparedstatement
satement 用于写入数据,例子如下: connection conn=DBHelper.getConnection(); Statement stmt=conn.createStatement( ...
- html相对定位绝对定位
孔子说:“温故而知新,可以为师矣.”这几天参加了一个免费的前端课,每天晚上都有直播,讲解一个独立的案例.在听前端基础的时候,发现自己有不少东西没学会,平时在学校虽说html也写了不少,但有好大一部分都 ...
- ArcGIS Enterprise 10.5.1 静默安装部署记录(Centos 7.2 minimal)- 3、安装Portal for ArcGIS
安装Portal for ArcGIS 解压portal安装包,tar -xzvf Portal_for_ArcGIS_Linux_1051_156440.tar.gz 切换到arcgis账户静默安装 ...
- Win SDK 标准程序
//-Registering window class. //-Creating window. //-Creating message loop. //-Implement WndProc func ...
- ThinkPHP5专题
TinkPHP5中 1. model中select()后的查询结果是对象而不是数组 2. model中 假如有 $result=$this->field($fields)->where($ ...
- ring0 ShadowSSDTHook
SSDT:主要处理 Kernel32.dll中的系统调用,如openProcess,ReadFile等,主要在ntoskrnl.exe中实现(微软有给出 ntoskrnl源代码) ShadowSSDT ...