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 相关文章推荐
JQuery SELECT单选模拟jQuery.select.js
Nov 12 Javascript
JQUERY的属性选择符和自定义选择符使用方法(二)
Apr 07 Javascript
JavaScript兼容性总结之获取非行间样式案例
Aug 07 Javascript
jQuery学习之DOM节点的插入方法总结
Jan 22 Javascript
详解windows下vue-cli及webpack 构建网站(二)导入bootstrap样式
Jun 17 Javascript
JavaScript实现单击网页任意位置打开新窗口与关闭窗口的方法
Sep 21 Javascript
vue项目中跳转到外部链接的实例讲解
Sep 20 Javascript
jQuery访问json文件中数据的方法示例
Jan 28 jQuery
layui的表单验证支持ajax判断用户名是否重复的实例
Sep 06 Javascript
微信小程序图片自适应实现解析
Jan 21 Javascript
Vue解决echart在element的tab切换时显示不正确问题
Aug 03 Javascript
vue实现日历表格(element-ui)
Sep 24 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中使用Imagick操作PSD文件实例
2015/01/26 PHP
php微信开发之谷歌测距
2018/06/14 PHP
php JWT在web端中的使用方法教程
2018/09/06 PHP
jQuery)扩展jQuery系列之一 模拟alert,confirm(一)
2010/12/04 Javascript
JQuery实现用户名无刷新验证的小例子
2013/03/22 Javascript
javascript引用类型指针的工作方式
2015/04/13 Javascript
jQuery 1.9.1源码分析系列(十)事件系统之主动触发事件和模拟冒泡处理
2015/11/24 Javascript
AngularJS使用ngMessages进行表单验证
2015/12/27 Javascript
easyui 中的datagrid跨页勾选问题的实现方法
2017/01/18 Javascript
Angular.js实现多个checkbox只能选择一个的方法示例
2017/02/24 Javascript
vue+vux实现移动端文件上传样式
2017/07/28 Javascript
详解js几个绕不开的事件兼容写法
2017/08/30 Javascript
微信小程序实现底部导航
2018/11/05 Javascript
vue 内置过滤器的使用总结(附加自定义过滤器)
2018/12/11 Javascript
JS/HTML5游戏常用算法之路径搜索算法 随机迷宫算法详解【普里姆算法】
2018/12/13 Javascript
原生js实现获取form表单数据代码实例
2019/03/27 Javascript
基于AngularJS拖拽插件ngDraggable.js实现拖拽排序功能
2019/04/02 Javascript
微信小程序如何实现五星评价功能
2019/10/15 Javascript
vue封装可复用组件confirm,并绑定在vue原型上的示例
2019/10/31 Javascript
vue中根据时间戳判断对应的时间(今天 昨天 前天)
2019/12/20 Javascript
详解Vue中Axios封装API接口的思路及方法
2020/10/10 Javascript
vue调用微信JSDK 扫一扫,相册等需要注意的事项
2021/01/03 Vue.js
[05:37]DOTA2-DPC中国联赛 正赛 Elephant vs iG 选手采访
2021/03/11 DOTA
在阿里云服务器上配置CentOS+Nginx+Python+Flask环境
2016/06/18 Python
django 使用 request 获取浏览器发送的参数示例代码
2018/06/11 Python
python实现可变变量名方法详解
2019/07/01 Python
python利用xlsxwriter模块 操作 Excel
2020/10/14 Python
项目合作意向书范本
2014/04/01 职场文书
法学专业毕业生求职信
2014/06/12 职场文书
2014年平安建设工作总结
2014/11/19 职场文书
向女朋友道歉的话
2015/01/20 职场文书
百家讲坛观后感
2015/06/12 职场文书
2015年学校总务工作总结
2015/07/20 职场文书
教师个人工作总结范文2015
2015/10/14 职场文书
优秀家长事迹材料(2016推荐版)
2016/02/29 职场文书
python - timeit 时间模块
2021/04/06 Python