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 相关文章推荐
js中方法重载如何实现?以及函数的参数问题
Aug 01 Javascript
jquery实现input输入框实时输入触发事件代码
Jan 28 Javascript
JavaScript函数详解
Nov 17 Javascript
node.js中的console.log方法使用说明
Dec 09 Javascript
Bootstrap表格和栅格分页实例详解
May 20 Javascript
实现JavaScript高性能的数据存储
Dec 11 Javascript
基于hover的用法实例(推荐)
Jul 04 Javascript
node.js利用mongoose获取mongodb数据的格式化问题详解
Oct 06 Javascript
微信小程序判断用户是否需要再次授权获取个人信息
Jul 18 Javascript
javascript实现弹出层效果
Dec 10 Javascript
Ant Design的可编辑Tree的实现操作
Oct 31 Javascript
JavaScript实现下拉列表
Jan 20 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
Laravel 5 框架入门(二)构建 Pages 的管理功能
2015/04/09 PHP
PHP中curl_setopt函数用法实例分析
2015/04/16 PHP
PHP设计模式之策略模式原理与用法实例分析
2019/04/04 PHP
tp5.1 框架数据库-数据集操作实例分析
2020/05/26 PHP
jqGrid增加时--判断开始日期与结束日期(实例解析)
2013/11/08 Javascript
JS判断字符串长度的5个方法(区分中文和英文)
2014/03/18 Javascript
node.js中的console.timeEnd方法使用说明
2014/12/09 Javascript
fastclick插件导致日期(input[type=&quot;date&quot;])控件无法被触发该如何解决
2015/11/09 Javascript
详解cordova打包成webapp的方法
2017/10/18 Javascript
javascript验证form表单数据的案例详解
2019/03/25 Javascript
layui加载表格,绑定新增,编辑删除,查看按钮事件的例子
2019/09/06 Javascript
Vue SSR 即时编译技术的实现
2020/05/06 Javascript
vue图片裁剪插件vue-cropper使用方法详解
2020/12/16 Vue.js
[01:22:42]2014 DOTA2华西杯精英邀请赛 5 24 DK VS LGD
2014/05/26 DOTA
[00:39]DOTA2上海特级锦标赛 Liquid战队宣传片
2016/03/04 DOTA
[53:52]EG vs VGJ.T 2018国际邀请赛小组赛BO2 第一场 8.16
2018/08/17 DOTA
python实现批量改文件名称的方法
2015/05/25 Python
python虚拟环境的安装配置图文教程
2017/10/20 Python
windows下 兼容Python2和Python3的解决方法
2018/12/05 Python
对Python协程之异步同步的区别详解
2019/02/19 Python
对python3中的RE(正则表达式)-详细总结
2019/07/23 Python
Python帮你微信头像任意添加装饰别再@微信官方了
2019/09/25 Python
python3 pathlib库Path类方法总结
2019/12/26 Python
java字符串格式化输出实例讲解
2021/01/06 Python
戴森美国官网:Dyson美国
2016/09/11 全球购物
洛杉矶健身中心女性专用运动服饰品牌:Marika
2018/05/09 全球购物
新东方旗下远程教育网站:新东方在线
2020/03/19 全球购物
会计辞职信范文
2014/01/15 职场文书
公务员保密承诺书
2014/03/27 职场文书
小区物业门卫岗位职责
2014/04/10 职场文书
微笑服务标语
2014/06/24 职场文书
安全标兵事迹材料
2014/08/17 职场文书
实习推荐信格式模板
2015/03/27 职场文书
婚礼双方父亲致辞
2015/07/27 职场文书
用Python制作灯光秀短视频的思路详解
2021/04/13 Python
Promise静态四兄弟实现示例详解
2022/07/07 Javascript