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 剪切板应用clipboardData详细解析
Dec 17 Javascript
简单谈谈javascript代码复用模式
Jan 28 Javascript
JS实现title标题栏文字不间断滚动显示效果
Sep 07 Javascript
AngularJS入门教程之路由机制ngRoute实例分析
Dec 13 Javascript
jQuery实现按比例缩放图片的方法
Apr 29 jQuery
基于jQuery的$.getScript方法去加载javaScript文档解析
Nov 08 jQuery
微信小程序实现图片懒加载的示例代码
Dec 13 Javascript
解决JSON.stringify()自动将中文转译成unicode的问题
Jan 05 Javascript
vue 微信授权登录解决方案
Apr 10 Javascript
深入理解react 组件类型及使用场景
Mar 07 Javascript
详解小程序退出页面时清除定时器
Apr 28 Javascript
JavaScript offset实现鼠标坐标获取和窗口内模块拖动
May 30 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
php开发中的页面跳转方法总结
2015/04/26 PHP
PHP中error_reporting()用法详解
2015/08/31 PHP
Zend Framework教程之请求对象的封装Zend_Controller_Request实例详解
2016/03/07 PHP
php中请求url的五种方法总结
2017/07/13 PHP
js身份证判断方法支持15位和18位
2014/03/18 Javascript
javascript对象的创建和访问
2016/03/08 Javascript
Bootstrap表格和栅格分页实例详解
2016/05/20 Javascript
关于网页中的无缝滚动的js代码
2016/06/09 Javascript
jQuery基本选择器和层次选择器学习使用
2017/02/27 Javascript
使用Bootrap和Vue实现仿百度搜索功能
2017/10/26 Javascript
JS实现的类似微信聊天效果示例
2019/01/29 Javascript
使用layui前端框架弹出form表单以及提交的示例
2019/10/25 Javascript
OpenLayers实现图层切换控件
2020/09/25 Javascript
JS实现超级好看的鼠标小尾巴特效
2020/12/01 Javascript
教你用Python创建微信聊天机器人
2020/03/31 Python
windows下添加Python环境变量的方法汇总
2018/05/14 Python
解决已经安装requests,却依然提示No module named requests问题
2018/05/18 Python
python在html中插入简单的代码并加上时间戳的方法
2018/10/16 Python
python实现批量视频分帧、保存视频帧
2019/05/31 Python
Python datetime包函数简单介绍
2019/08/28 Python
Python笔记之观察者模式
2019/11/20 Python
Tensorflow全局设置可见GPU编号操作
2020/06/30 Python
PyCharm 2020.2下配置Anaconda环境的方法步骤
2020/09/23 Python
Pycharm操作Git及GitHub的步骤详解
2020/10/27 Python
五分钟学会怎么用python做一个简单的贪吃蛇
2021/01/12 Python
一文带你掌握Pyecharts地理数据可视化的方法
2021/02/06 Python
年度考核自我评价
2014/01/25 职场文书
司机职责范本
2014/03/08 职场文书
企业元宵节主持词
2014/03/25 职场文书
食品委托检验协议书范本
2014/09/12 职场文书
2014年教育教学工作总结
2014/11/13 职场文书
爱情保证书
2015/01/17 职场文书
2015年社区中秋节活动总结
2015/03/23 职场文书
初二英语教学反思
2016/02/15 职场文书
浅谈CSS不规则边框的生成方案
2021/05/25 HTML / CSS
通过shell脚本对mysql的增删改查及my.cnf的配置
2021/07/07 MySQL