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 相关文章推荐
javascript:以前写的xmlhttp池,代码
May 18 Javascript
javascript使用定时函数实现跳转到某个页面
Dec 25 Javascript
七个很有意思的PHP函数
May 12 Javascript
jQuery同步提交示例代码
Dec 12 Javascript
AngularJS入门教程之控制器详解
Jul 27 Javascript
微信小程序 icon组件详细及实例代码
Oct 25 Javascript
JavaScript复制内容到剪贴板的两种常用方法
Feb 27 Javascript
Angular 封装并发布组件的方法示例
Apr 19 Javascript
JavaScript事件冒泡与事件捕获实例分析
Aug 01 Javascript
node.js 模块和其下载资源的镜像设置的方法
Sep 06 Javascript
Element输入框带历史查询记录的实现示例
Jan 15 Javascript
微信小程序canvas截取任意形状的实现代码
Jan 13 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
DC漫画《蝙蝠侠和猫女》图透 猫女怀孕老爷当爹
2020/04/09 欧美动漫
php中使用__autoload()自动加载未定义类的实现代码
2013/02/06 PHP
Zend studio文件注释模板设置方法
2013/09/29 PHP
php读取excel文件示例分享(更新修改excel)
2014/02/27 PHP
javascript call和apply方法
2008/11/24 Javascript
jquery里的正则表达式说明
2011/08/03 Javascript
关于IE BUG与字符串截取substr的解决办法
2013/04/10 Javascript
jQuery设置和获取HTML、文本和值示例
2014/07/08 Javascript
jquery使用$(element).is()来判断获取的tagName
2014/08/24 Javascript
layDate日期控件使用方法详解
2018/11/15 Javascript
JavaScript实现小球沿正弦曲线运动
2020/09/07 Javascript
jquery中为什么能用$操作
2019/06/18 jQuery
Vue学习之组件用法实例详解
2020/01/06 Javascript
跟老齐学Python之总结参数的传递
2014/10/10 Python
python通过线程实现定时器timer的方法
2015/03/16 Python
Python通过future处理并发问题
2017/10/17 Python
Python Django框架实现应用添加logging日志操作示例
2019/05/17 Python
Djang的model创建的字段和参数详解
2019/07/27 Python
python代码实现逻辑回归logistic原理
2019/08/07 Python
python实现在线翻译功能
2020/03/03 Python
python中spy++的使用超详细教程
2021/01/29 Python
css背景图片的背景裁切、背景透明度、背景变换等效果运用
2012/12/24 HTML / CSS
浅谈css3中的渐进增强和优雅降级
2017/12/01 HTML / CSS
canvas绘制视频封面的方法
2018/02/05 HTML / CSS
AmazeUI 网格的实现示例
2020/08/13 HTML / CSS
说说在weblogic中开发消息Bean时的persistent与non-persisten的差别
2013/04/07 面试题
教育课题研究自我鉴定范文
2013/12/28 职场文书
早会主持词
2014/03/17 职场文书
群众路线教育党课主持词
2014/04/01 职场文书
诉讼代理人授权委托书
2014/04/08 职场文书
学校政风行风自查自纠报告
2014/10/21 职场文书
2014年应急管理工作总结
2014/11/26 职场文书
革命电影观后感
2015/06/18 职场文书
导游词之晋城蟒河
2019/12/12 职场文书
python 如何用map()函数创建多线程任务
2021/04/07 Python
了解Redis常见应用场景
2021/06/23 Redis