Vue数据驱动模拟实现2


Posted in Javascript onJanuary 11, 2017

一、前言

在随笔“模拟Vue之数据驱动1”结尾处,我们说到如果监听的属性是个对象呢?那么这个对象中的其他属性岂不就是监听不了了吗?

如下:

 Vue数据驱动模拟实现2

倘若user中的name、age属性变化,如何知道它们变化了呢?

今儿,就来解决这一问题。

通过走读Vue源码,发现他是利用Observer构造函数为每个对象创建一个Observer对象,来监听数据的,如果数据中的属性又是一个对象,那么就又通过Observer来监听嘛。

其实,核心思想就是树的先序遍历(关于树,可参考here)。如我们将上述Demo中的data数据,图形化一下,就更加明白了,如下:

Vue数据驱动模拟实现2 

好了,理清了大体思路,下面我们就一起来创建一个Observer吧。

二、Observer构造

Observer整体结构如下:

function Observer(data){
 //如若this不是Observer对象,即创建一个
 if(!(this instanceof Observer)){
 return new Observer(data);
 }
 this.data = data;
 this.walk(data); 
}

let p = Observer.prototype = Object.create(null);

p.walk = function(data){
 /*
 TODO:监听data数据中的所有属性,
 并查看data中属性值是否为对象,
 若为对象,就创建一个Observer实例
 */ 
}

p.convert = function(key, val){
 //TODO:通过Object.defineProperty监听数据 
}

好了,下面,我们一起来完成walk以及convert方法吧。

-walk-

首先,我们在walk方法中实现对data对象中的所有属性监听,如下:

p.walk = function(data){
 let keys = Object.keys(data);
 keys.forEach( key => {
 let val = data[key];
 this.convert(key, val);
 });
}

且,由于属性中可能又会是一个对象,那么,我们就有必要监听它们。

怎么办呢?

如果是个对象,再次利用Observer构造函数,处理它不就完了么。

如下:

p.walk = function(data){
 let keys = Object.keys(data);
 keys.forEach( key => {
 let val = data[key];
 //如果val为对象,则交给Observer处理
 if(typeof val === 'object'){
  Observer(val);
 }
 this.convert(key, val);
 });
}

你可能会有这样的疑问,如果直接利用Observer处理对象,那么不就与父对象失去关联了么?

然而并没有,因为JavaScript对于对象是指向地址关系,所以怎么会失去关联呢。

-convert-

对于convert方法,就比较简单了,一如既往就是利用Object.defineProperty监听数据,如下:

p.convert = function(key, val){
 Object.defineProperty(this.data, key, {
 get: ()=>{
  console.log('访问了'+key+' 值为'+val);
  return val;
 },
 set: (newVal)=>{
  console.log('设置了'+key+' 值为'+newVal);
  if(newVal !== val){
  val = newVal;
  }
 }
 });
}

好了,到此,一个简单的Observer就构造完成,下面我们就来测试下,是否成功监听了每个属性。

<script src="./observer.js"></script>
<script>
 let data = {
 user: {
  name: 'Monkey',
  age: 24
 },
 lover: {
  name: 'Dorie',
  age: 23
 }
 };
 Observer(data);
</script>

效果如下:

Vue数据驱动模拟实现2

Perfect,完整代码见github。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
JavaScript在IE中“意外地调用了方法或属性访问”
Nov 19 Javascript
自定义右键属性覆盖浏览器默认右键行为实现代码
Feb 02 Javascript
node.js中的fs.unlinkSync方法使用说明
Dec 15 Javascript
浅谈重写window对象的方法
Dec 29 Javascript
JavaScript中的console.trace()函数介绍
Dec 29 Javascript
Javascript自执行匿名函数(function() { })()的原理浅析
May 15 Javascript
Javascript之图片的延迟加载的实例详解
Jul 24 Javascript
ES6新特性:使用export和import实现模块化详解
Jul 31 Javascript
JavaScript实现百度搜索框效果
Mar 26 Javascript
详解Angular5/Angular6项目如何添加热更新(HMR)功能
Oct 10 Javascript
微信小程序 轮播图实现原理及优化详解
Sep 29 Javascript
JavaScript实现拖拽效果
Mar 16 Javascript
jQuery实现对象转为url参数的方法
Jan 11 #Javascript
将鼠标焦点定位到文本框最后(代码分享)
Jan 11 #Javascript
移动端界面的适配
Jan 11 #Javascript
bootstrapValidator bootstrap-select验证不可用的解决办法
Jan 11 #Javascript
HTML5 js实现拖拉上传文件功能
Nov 20 #Javascript
Bootstrap表单控件使用方法详解
Jan 11 #Javascript
老生常谈的跨域处理
Jan 11 #Javascript
You might like
Notice: Trying to get property of non-object problem(PHP)解决办法
2012/03/11 PHP
分享一个PHP数据流应用的简单例子
2012/06/01 PHP
Yii2实现ActiveForm ajax提交
2017/05/26 PHP
PHP简单计算两个时间差的方法示例
2017/06/20 PHP
PHP使用标准库spl实现的观察者模式示例
2018/08/04 PHP
javascript 极速 隐藏/显示万行表格列只需 60毫秒
2009/03/28 Javascript
javascript appendChild,innerHTML,join性能比较代码
2009/08/29 Javascript
js 覆盖和重载 函数
2009/09/25 Javascript
jquery模拟按下回车实现代码
2011/09/20 Javascript
如何解决Jquery库及其他库之间的$命名冲突
2013/09/15 Javascript
javascript跨浏览器的属性判断方法
2014/03/16 Javascript
Js实现手机发送验证码时按钮延迟操作
2014/06/20 Javascript
jquery插件corner实现圆角边框的方法
2015/03/09 Javascript
JavaScript实现在页面间传值的方法
2015/04/07 Javascript
js使用highlight.js高亮你的代码
2017/08/18 Javascript
bootstrap响应式工具使用详解
2017/11/29 Javascript
基于jQuery实现无缝轮播与左右点击效果
2018/05/13 jQuery
浅析Angular 实现一个repeat指令的方法
2019/07/21 Javascript
jquery ui 实现 tab标签功能示例【测试可用】
2019/07/25 jQuery
JS Array.from()将伪数组转换成数组的方法示例
2020/03/23 Javascript
Python装饰器基础详解
2016/03/09 Python
python中requests小技巧
2017/05/10 Python
Python使用正则表达式过滤或替换HTML标签的方法详解
2017/09/25 Python
python3中的eval和exec的区别与联系
2019/10/10 Python
python与idea的集成的实现
2020/11/20 Python
施华洛世奇匈牙利官网:SWAROVSKI匈牙利
2019/07/06 全球购物
抽象方法、抽象类怎样声明
2014/10/25 面试题
网站编辑求职信
2013/10/17 职场文书
《只有一个地球》教学反思
2014/02/14 职场文书
拉歌口号大全
2014/06/13 职场文书
另类冲刺标语
2014/06/24 职场文书
校园元旦活动总结
2014/07/09 职场文书
2015年护士医德医风自我评价
2015/03/03 职场文书
“5.12”护士节主持词
2015/07/04 职场文书
2016年公司新年寄语
2015/08/17 职场文书
2019通用版导游词范本!
2019/08/07 职场文书