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 相关文章推荐
对YUI扩展的Gird组件 Part-1
Mar 10 Javascript
javascript 处理HTML元素必须避免使用的一种方法
Jul 30 Javascript
jQuery基于json与cookie实现购物车的方法
Apr 15 Javascript
JS实现添加,替换,删除节点元素的方法
Jun 30 Javascript
聊一聊Vue.js过渡效果
Sep 07 Javascript
javascript 中iframe高度自适应(同域)实例详解
May 16 Javascript
Vue.js学习教程之列表渲染详解
May 17 Javascript
react 兄弟组件如何调用对方的方法示例
Oct 23 Javascript
如何在微信小程序里面退出小程序的方法
Apr 28 Javascript
Vue组件化开发之通用型弹出框的实现
Feb 28 Javascript
Javascript中的解构赋值语法详解
Apr 02 Javascript
JavaScript组合继承详解
Nov 07 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
CodeIgniter使用phpcms模板引擎
2013/11/12 PHP
PHP连接MSSQL时nvarchar字段长度被截断为255的解决方法
2014/12/25 PHP
PHP连接数据库实现注册页面的增删改查操作
2016/03/27 PHP
让任务管理器中的CPU跳舞的js代码
2008/11/01 Javascript
js cookies实现简单统计访问次数
2009/11/24 Javascript
firefox下对ajax的onreadystatechange的支持情况分析
2009/12/14 Javascript
JavaScript中也使用$美元符号来代替document.getElementById
2010/06/19 Javascript
自己动手制作jquery插件之自动添加删除行功能介绍
2011/10/14 Javascript
jquery ajax请求方式与提示用户正在处理请稍等
2014/09/01 Javascript
AngularJS自动表单验证
2016/02/01 Javascript
VUEJS实战之构建基础并渲染出列表(1)
2016/06/13 Javascript
jQuery实现的简单百分比进度条效果示例
2016/08/01 Javascript
javascript+css3开发打气球小游戏完整代码
2017/11/28 Javascript
Vuex的API文档说明详解
2020/02/05 Javascript
搞笑的程序猿:看看你是哪种Python程序员
2015/06/12 Python
剖析Django中模版标签的解析与参数传递
2015/07/21 Python
Python实现TCP协议下的端口映射功能的脚本程序示例
2016/06/14 Python
Python爬取十篇新闻统计TF-IDF
2018/01/03 Python
python邮件发送smtplib使用详解
2020/06/16 Python
python skimage 连通性区域检测方法
2018/06/21 Python
在Mac下使用python实现简单的目录树展示方法
2018/11/01 Python
Python中new方法的详解
2019/01/15 Python
python 抓包保存为pcap文件并解析的实例
2019/07/23 Python
python二分法查找算法实现方法【递归与非递归】
2019/12/06 Python
Python脚本去除文件的只读性操作
2020/03/05 Python
使用HTML5拍照示例代码
2013/08/06 HTML / CSS
WoolOvers爱尔兰:羊绒、羊毛和棉针织品
2017/01/04 全球购物
阿迪达斯芬兰官方网站:adidas芬兰
2017/01/30 全球购物
夏威夷咖啡公司:Hawaii Coffee Company
2019/09/19 全球购物
在数据文件自动增长时,自动增长是否会阻塞对文件的更新
2014/05/01 面试题
岗位竞聘演讲稿
2014/01/10 职场文书
放飞蜻蜓反思
2014/02/05 职场文书
大学文艺委员竞选稿
2015/11/19 职场文书
js Proxy的原理详解
2021/05/25 Javascript
matplotlib如何设置坐标轴刻度的个数及标签的方法总结
2021/06/11 Python
python人工智能human learn绘图可创建机器学习模型
2021/11/23 Python