Vue数据驱动模拟实现5


Posted in Javascript onJanuary 13, 2017

一、前言

在"模拟Vue之数据驱动4"中,我们实现了push、pop等数组变异方法。

但是,在随笔末尾我们提到,当pop、sort这些方法触发后,该怎么办呢?因为其实,它们并没有往数组中新增属性呢。

而且,当数据改动后,如果我们在变动数据处,就立即更改数据也未免性能不够,此时,走读Vue源码,发现他用了一个很巧妙的方法,就是职责链模式。当某个数据有所变动时,它会向上传递,通俗点就是冒泡至根结点,这样我们也可以在自己代码中使用事件代理咯,哇卡哇卡。

示意图如下所示:

Vue数据驱动模拟实现5

好了,说了这么多,我们下面就一起来实现下吧。

二、正文

注:以下代码皆编写在observer.js文件中。

首先,当数据变动,或者触发某个事件时,我们需要与变动数据关联一个自定义事件(自定义事件详情见here),如果触发某个事件,那么就执行,如下:

绑定事件方法:

//let p = Observer.prototype
p.on = function(eventName, fn){
 let listener = this.listener = this.listener || [];
 if(typeof eventName === 'string' && typeof fn === 'function'){
  if(!listener[eventName]){
   listener[eventName] = [fn];
  }else{
   listener[eventName].push(fn);
  }
 } 
}

取消事件方法:

//let p = Observer.prototype
p.off = function(eventName, fn){
 let listener = this.listener = this.listener || [];
 let actionArray = listener[eventName];
 if(typeof eventName === 'string' && Array.isArray(actionArray)){
  if(typeof fn === 'function'){
   actionArray.forEach( (func, i, arr) => {
    if(func === fn){
     arr.splice(i,1); 
    }
   });
  }
 }
}

触发事件方法:

//let p = Observer.prototype
p.emit = function(eventName){
 let listener = this.listener = this.listener || [];
 let actionArray = listener[eventName];
 if(Array.isArray(actionArray)){
  actionArray.forEach( func => {
   if(typeof func === 'function'){
    func(); 
   }
  }); 
 }
}

其次,就是当数据变动,触发自身相关事件后,怎么一路冒泡到根结点的处理了。

怎么冒泡到根结点呢?

那就自身结点关联父结点嘛,这样不就可以追溯到根节点了么。

所以,我们在Observer.walk时,就将自己的父节点记录即可,如下:

//let p = Observer.prototype
p.observe = function(key, data){
 if(typeof data === 'object'){
  let ob = new Observer(data); 
  //关联父节点
  ob._parent = {
   key,
   ob: this
  };
 } 
}

最后,有了子父结点的依赖关系,那么冒泡方法就OK啦,如下:

//let p = Observer.prototype
p.notify = function(eventName){
 let ob = this._parent && this._parent.ob;
 let key = ob && this._parent.key || 'root';
 console.log('parent--'+key+' event--'+eventName);
 this.emit(eventName);
 //判断节点是否有父节点,若有,就向上传递事件
 ob && ob.notify(eventName); 
}

Perfect,具体代码详见github.

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
动态控制Table的js代码
Mar 07 Javascript
JavaScript判断两种格式的输入日期的正确性的代码
Mar 25 Javascript
JQuery 表格操作(交替显示、拖动表格行、选择行等)
Jul 29 Javascript
一行代码实现纯数据json对象的深度克隆实现思路
Jan 09 Javascript
使用js实现雪花飘落效果
Aug 26 Javascript
浅谈nodeName,nodeValue,nodeType,typeof 的区别
Jan 13 Javascript
jQuery实现鼠标滑过点击事件音效试听
Aug 31 Javascript
jQuery实现可高亮显示的二级CSS菜单效果
Sep 01 Javascript
Angular ng-animate和ng-cookies用法详解
Apr 18 Javascript
angular6根据environments配置文件更改开发所需要的环境的方法
Mar 06 Javascript
angular使用md5,CryptoJS des加密的方法
Jun 03 Javascript
react 原生实现头像滚动播放的示例
Apr 21 Javascript
利用HTML5+Socket.io实现摇一摇控制PC端歌曲切换
Jan 13 #Javascript
使用jQuery的ajax方法向服务器发出get和post请求的方法
Jan 13 #Javascript
jquery,js简单实现类似Angular.js双向绑定
Jan 13 #Javascript
jQuery实现的简单排序功能示例【冒泡排序】
Jan 13 #Javascript
js实现淡入淡出轮播切换功能
Jan 13 #Javascript
js仿百度音乐全选操作
Jan 13 #Javascript
js实现tab选项卡切换功能
Jan 13 #Javascript
You might like
php字符编码转换之gb2312转为utf8
2013/10/28 PHP
phpmailer发送邮件之后,返回收件人是否阅读了邮件的方法
2014/07/19 PHP
php的4种常见运行方式
2015/03/20 PHP
PHP简单日历实现方法
2016/07/20 PHP
Yii框架布局文件的动态切换操作示例
2019/11/11 PHP
用javascript实现的激活输入框后隐藏初始内容
2007/06/29 Javascript
javascript 动态参数判空操作
2008/12/22 Javascript
深入理解JavaScript系列(3) 全面解析Module模式
2012/01/15 Javascript
Jquery的hide及toggle方法让超链接慢慢消失
2013/09/06 Javascript
uploadify多文件上传参数设置技巧
2015/11/16 Javascript
客户端验证用户名和密码的方法详解
2016/06/16 Javascript
JavaScript中如何使用cookie实现记住密码功能及cookie相关函数介绍
2016/11/10 Javascript
Bootstrap模态窗口源码解析
2017/02/08 Javascript
js实现简单的二级联动效果
2017/03/09 Javascript
js中DOM三级列表(代码分享)
2017/03/20 Javascript
2种在vue项目中使用百度地图的简单方法
2018/09/28 Javascript
微信小程序picker组件关于objectArray数据类型的绑定方法
2019/03/13 Javascript
Vue Element UI + OSS实现上传文件功能
2019/07/31 Javascript
详解NodeJs项目 CentOs linux服务器线上部署
2019/09/16 NodeJs
vue实现百度搜索功能
2020/12/28 Javascript
在vue中使用echars实现上浮与下钻效果
2019/11/08 Javascript
Vue-cli3多页面配置详解
2020/03/22 Javascript
Vue+scss白天和夜间模式切换功能的实现方法
2021/01/05 Vue.js
[01:06]DOTA2隆重推出2016冬季勇士令状 内含上海特级锦标赛互动指南
2016/02/17 DOTA
零基础写python爬虫之神器正则表达式
2014/11/06 Python
Flask框架单例模式实现方法详解
2019/07/31 Python
Python图片处理模块PIL操作方法(pillow)
2020/04/07 Python
澳大利亚家具和家居用品在线商店:Interiors Online
2018/03/05 全球购物
苹果台湾官网:Apple台湾
2019/01/05 全球购物
澳大利亚家用电器在线商店:Billy Guyatts
2020/05/05 全球购物
存储过程和函数的区别
2013/05/28 面试题
中学门卫岗位职责
2013/12/26 职场文书
社会实践心得体会
2014/01/03 职场文书
物流专业大学生职业生涯规划书范文
2014/01/15 职场文书
清明节演讲稿
2014/05/27 职场文书
2014年个人思想工作总结
2014/11/27 职场文书