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随笔中已经介绍,在本文中不做赘述 本 ...
随机推荐
- 使用Razor
新建一个名称为Rezor的mvc空项目,定义一个模型内容 public class Product { //定义模型 public int ProductID { get; set; } public ...
- mac解决系统设置安全与隐私没有允许所有来源
解决系统设置安全与隐私没有允许所有来源:sudo spctl --master-disable
- 前端自动分环境打包(vue和ant design)
现实中的问题:有时候版本上线的时候,打包时忘记切换环境,将测试包推上正式服务器,那你就会被批了. 期望:在写打包的命令行的时候就觉得自己在打包正式版本,避免推包时候的,不确信自己的包是否正确. 既然有 ...
- [JAVA小项目]GUI界面的局域网聊天室
思路: 1.服务端: 1.1 创建ServerSocket 监听本地端口 1.2 循环接收多个客户端的连接,并且把多个客户端连接的每个管道都为其创建线程. 服务端类的成员:链表--每个成员都是线程类- ...
- 富文本编辑框和防止xss攻击
一.后台管理页面构建 1.创建后台管理url urlpatterns = [ ... # 后台管理url re_path("cn_backend/$", views.cn_back ...
- SQLAlchemy的使用---查询的更多操作
# 查询更多操作 from create_table import User, engine from sqlalchemy.orm import sessionmaker Session = ses ...
- vue1.0 与 Vue2.0的一些区别 及用法
1.Vue2.0的模板标记外必须使用元素包起来: eg:Vue1.0的写法 <!DOCTYPE html> <html> <head> <meta chars ...
- mysql 常用操作语句
1 根据表中的其中一个字段的值来修改同行某字段的值 UPDATE radar a INNER JOIN radar b ON a.id=b.id SET a.letter=LEFT(b.filena ...
- Ubuntu setup ftp server.
http://www.cnblogs.com/bcsflilong/p/4200139.html Steps 1. Install vsftpd sudo apt-get install vsftpd ...
- 开通cnblogs博客
开通博客,准备记录学习和开发过程