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进行拖拽
Jul 20 Javascript
使用TextRange获取输入框中光标的位置的代码
Mar 08 Javascript
直接生成打开窗口代码,不必下载
May 14 Javascript
用JS提交参数创建form表单在FireFox中遇到的问题
Jan 16 Javascript
showModelDialog弹出文件下载窗口的使用示例
Nov 19 Javascript
css配合jquery美化 select
Nov 29 Javascript
javascript正则匹配汉字、数字、字母、下划线
Apr 10 Javascript
关于JavaScript数组你所不知道的3件事
Aug 24 Javascript
Vue.js在使用中的一些注意知识点
Apr 29 Javascript
最简单的JS实现json转csv的方法
Jan 10 Javascript
微信小程序调用天气接口并且渲染在页面过程详解
Jun 24 Javascript
jQuery实现带进度条的轮播图
Sep 13 jQuery
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生成带有雪花背景的验证码
2008/09/28 PHP
Eclipse的PHP插件PHPEclipse安装和使用
2014/07/20 PHP
在textarea文本域中显示HTML代码的方法
2007/03/06 Javascript
JavaScript 对象成员的可见性说明
2009/10/16 Javascript
入门基础学习 ExtJS笔记(一)
2010/11/11 Javascript
JQuery扩展插件Validate 1 基本使用方法并打包下载
2011/09/05 Javascript
javascript改变position值实现菜单滚动至顶部后固定
2013/01/18 Javascript
jquery创建表格(自动增加表格)代码分享
2013/12/25 Javascript
Node.js中使用mongoskin操作mongoDB实例
2014/09/28 Javascript
BootStrap智能表单实战系列(七)验证的支持
2016/06/13 Javascript
遍历json 对象的属性并且动态添加属性的实现
2016/12/02 Javascript
js实现简易计算器功能
2019/10/18 Javascript
webpack4 optimization使用总结
2019/11/10 Javascript
vue单应用在ios系统中实现微信分享功能操作
2020/09/07 Javascript
Python中利用函数装饰器实现备忘功能
2015/03/30 Python
python特性语法之遍历、公共方法、引用
2018/08/08 Python
Python实现随机创建电话号码的方法示例
2018/12/07 Python
python+selenium实现简历自动刷新的示例代码
2019/05/20 Python
Python的缺点和劣势分析
2019/11/19 Python
Python使用py2neo操作图数据库neo4j的方法详解
2020/01/13 Python
python编写一个会算账的脚本的示例代码
2020/06/02 Python
python统计mysql数据量变化并调用接口告警的示例代码
2020/09/21 Python
用python爬虫批量下载pdf的实现
2020/12/01 Python
使用css3绘制出各种几何图形
2016/08/17 HTML / CSS
细说CSS3中box属性中的overflow-x属性和overflow-y属性值的效果
2014/07/21 HTML / CSS
Css3新特性应用之形状总结
2016/12/08 HTML / CSS
日本最佳原创设计品牌:Felissimo(芬理希梦)
2019/03/19 全球购物
会计自荐信范文
2014/03/09 职场文书
开展创先争优活动总结
2014/08/28 职场文书
基层党员学习党的群众路线教育实践活动心得体会
2014/11/04 职场文书
告知书格式
2015/07/01 职场文书
JVM入门之类加载与字节码技术(类加载与类的加载器)
2021/06/15 Java/Android
Vue elementUI表单嵌套表格并对每行进行校验详解
2022/02/18 Vue.js
Golang入门之计时器
2022/05/04 Golang
一文搞懂Java中的注解和反射
2022/06/21 Java/Android
ECharts transform数据转换和dataZoom在项目中使用
2022/12/24 Javascript