Vue数据驱动模拟实现3


Posted in Javascript onJanuary 11, 2017

一、前言

在"模拟Vue之数据驱动2"中,我们实现了个Observer构造函数,通过它可以达到监听已有数据data中的所有属性。

但,倘若我们想在某个对象中,新增某个属性呢?

如下:

Vue数据驱动模拟实现3

那么岂不是,新增的infor属性,以及它的对象属性,没有得到监听。

此时,应该怎么处理呢?

通过走读Vue源码,发现他是采用另增属性方法$set实现的。

就是说,如果我们采用常规方法为对象增加属性(如上),我们没法得知并监控它,所以,我们为每个对象扩展一个$set方法,用于另增属性使用,即可,如下:

data.user.$set('infor', {msg: 'happy'});

好了,下面,我们就一同实现这个$set方法吧。

二、$set方法实现

首先,我们得创建一个恒定extendObj对象,用于将$set方法绑定在其中。

你可能会想,为什么我们需要一个extendObj对象呢?直接将$set函数赋值给每个需要监听的对象不就完了么?

是的,这样也可以,但是随着需求增长,倘若我们又想为每个监听对象扩展其他方法呢?难道又要去Observer里面为对象,一一赋值?

so,创建恒定extendObj对象,如下:

const extendObj = {};

因为,我们将$set绑定到extendObj中,且让$set为不可枚举型,所以会用到Object.defineProperty,固将其提取出来,作为一个方法如下:

function proxyObject(obj, key, val, enume){
  Object.defineProperty(obj, key, {
    value: val,
    enumerable: !!enume,
    writable: true,
    configurable: true
  });  
};

接下来,就是实现$set方法了,整体结构如下:

proxyObject(extendObj, '$set', function(key, val){
  //this指向extendObj
  if(this.hasOwnProperty(key)){
    return;
  }else{
    /*
     TODO:在extendObj中监听key属性,
     且,若key属性值为对象,再次监听key属性值
    */     
  }  
});

看到上面的TODO注释,是否似曾相识,不就是是在“模拟Vue之数据驱动2”遇见过的嘛,通过Observer.prototype.convert监听key属性,通过new Observer再次监听key属性值不就完啦。

的确,但是一旦这样做了,不就和上面我们提到的“直接将$set赋予监听对象”问题一样嘛,耦合性太大,且随着需求上涨,不易维护。

固而,在此需要一点小技巧:在observer模块中为每个监听对象赋予一个$Observer属性,其值指向Observer自身实例,如下:

//observer.js
p.walk = function(data){
  let keys = Object.keys(data);
  keys.forEach( key => {
    let val = data[key];
    if(typeof val === 'object'){
      new Observer(val);
    }
    this.convert(key, val);
  });
  //$Observer属性指向Observer自身实例
  data.$Observer = this;
}
//新增一个observe方法
p.observe = function(data){
  if(typeof data === 'object'){
    new Observer(data);  
  }  
}

好了,这样之后,得$set整体实现如下:

proxyObject(extendObj, '$set', function(key, val){
  if(this.hasOwnProperty(key)){
    return;
  }else{
    proxyObject(this, key, val, true);
    let ob = this.$Observer;
    ob.observe(val);
    ob.convert(key, val);  
  }  
});

到此,一个简单的$set方法构建完毕。

在上面我们提到,之所以需要一个恒定extendObj对象,是为了更好的代码管理。且,到目前为止,需要监听的对象上并没有扩展$set方法呢,所以,下面的事情就是为了达到以上效果,如下:

//observer.js
function Observer(data){
  if(!(this instanceof Observer)){
    return new Observer(data);
  }
  //将监听对象的隐指针指向我们的extendObj对象
  data.__proto__ = extendObj;
  this.data = data;
  this.walk(data);  
}

好了,一切完毕,接下来就测试下吧:

<script src="./extendObj.js"></script>
<script src="./observer.js"></script>
<script>
  let data = {
    user: {
      name: 'Monkey',
      age: 24
    },
    lover: {
      name: 'Dorie',
      age: 23
    }
  };
  Observer(data);
</script>

效果如下:

Vue数据驱动模拟实现3

Perfect,完整代码见github。

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

Javascript 相关文章推荐
html下载本地
Jun 19 Javascript
对setInterval在火狐和chrome切换标签产生奇怪的效果之探索,与解决方案!
Oct 29 Javascript
js获得网页背景色和字体色的方法
Mar 21 Javascript
jquery防止重复执行动画避免页面混乱
Apr 22 Javascript
js实现顶部可折叠的菜单工具栏效果实例
May 09 Javascript
angularjs表格ng-table使用备忘录
Mar 09 Javascript
JavaScript排序算法动画演示效果的实现方法
Oct 18 Javascript
webpack配置文件和常用配置项介绍
Apr 28 Javascript
JS实现自动轮播图效果(自适应屏幕宽度+手机触屏滑动)
Jun 19 Javascript
Angularjs按需查询实例代码
Oct 30 Javascript
微信小程序云开发如何使用npm安装依赖
May 18 Javascript
layer ui插件显示tips时,修改字体颜色的实现方法
Sep 11 Javascript
jQuery实现判断控件是否显示的方法
Jan 11 #Javascript
jQuery Form表单取值的方法
Jan 11 #Javascript
vue实现ajax滚动下拉加载,同时具有loading效果(推荐)
Jan 11 #Javascript
浅谈JavaScript中promise的使用
Jan 11 #Javascript
JS多文件上传的实例代码
Jan 11 #Javascript
微信小程序开发(一) 微信登录流程详解
Jan 11 #Javascript
Javascript中return的使用与闭包详解
Jan 11 #Javascript
You might like
MOTOROLA 摩托罗拉 MODEL 66-XI五灯中波收音机
2021/03/02 无线电
php使用codebase生成随机数
2014/03/25 PHP
php观察者模式应用场景实例详解
2017/02/03 PHP
php+mysql开发的最简单在线题库(在线做题系统)完整案例
2019/03/30 PHP
JavaScript面向对象之体会[总结]
2008/11/13 Javascript
javascript日期转换 时间戳转日期格式
2011/11/05 Javascript
关注jquery技巧提高jquery技能(前端开发必学)
2015/11/02 Javascript
所见即所得的富文本编辑器bootstrap-wysiwyg使用方法详解
2016/05/27 Javascript
基于jQuery实现瀑布流页面
2017/04/11 jQuery
vue调用高德地图实例代码
2017/04/28 Javascript
详解win7 cmd执行vue不是内部命令的解决方法
2017/07/27 Javascript
gulp教程_从入门到项目中快速上手使用方法
2017/09/14 Javascript
vue init失败简单解决方法(终极版)
2017/12/22 Javascript
Vue2.0生命周期的理解
2018/08/20 Javascript
微信小程序引入Vant组件库过程解析
2019/08/06 Javascript
js实现盒子移动动画效果
2020/08/09 Javascript
[01:06:42]VP vs NewBee Supermajor 胜者组 BO3 第二场 6.5
2018/06/06 DOTA
python生成随机验证码(中文验证码)示例
2014/04/03 Python
使用70行Python代码实现一个递归下降解析器的教程
2015/04/17 Python
Python实现八大排序算法
2016/08/13 Python
详解Numpy数组转置的三种方法T、transpose、swapaxes
2019/05/27 Python
mac系统下Redis安装和使用步骤详解
2019/07/09 Python
PyTorch中的C++扩展实现
2020/04/02 Python
Python unittest discover批量执行代码实例
2020/09/08 Python
Kmeans均值聚类算法原理以及Python如何实现
2020/09/26 Python
python实现录音功能(可随时停止录音)
2020/10/26 Python
html5中为audio标签增加停止按钮动作实现方法
2013/01/04 HTML / CSS
AE美国鹰日本官方网站: American Eagle Outfitters
2016/12/10 全球购物
Chain Reaction Cycles芬兰:世界上最大的在线自行车商店
2017/12/06 全球购物
苹果台湾官网:Apple台湾
2019/01/05 全球购物
酒店服务实习自我鉴定
2013/09/22 职场文书
《争吵》教学反思
2014/02/15 职场文书
工作违纪检讨书
2014/02/17 职场文书
土木工程师职业规划范文
2014/03/07 职场文书
师范生见习报告
2014/10/31 职场文书
会计专业求职信范文
2015/03/19 职场文书