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高级程序设计 读书笔记之九 本地对象Array
Feb 27 Javascript
可在线编辑网页文字效果代码(单击)
Mar 02 Javascript
简单漂亮的js弹窗可自由拖拽且兼容大部分浏览器
Oct 22 Javascript
js如何判断访问是来自搜索引擎(蜘蛛人)还是直接访问
Sep 14 Javascript
BootstrapTable与KnockoutJS相结合实现增删改查功能【二】
May 10 Javascript
ion content 滚动到底部会遮住一部分视图的快速解决方法
Sep 06 Javascript
老生常谈Bootstrap媒体对象
Jul 06 Javascript
深入掌握 react的 setState的工作机制
Sep 27 Javascript
前端html中jQuery实现对文本的搜索功能并把搜索相关内容显示出来
Nov 14 jQuery
微信小程序实现炫酷的弹出式菜单特效
Jan 28 Javascript
d3.js 地铁轨道交通项目实战
Nov 27 Javascript
vue实现div单选多选功能
Jul 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
PHP通过插入mysql数据来实现多机互锁实例
2014/11/05 PHP
PHP图片处理之使用imagecopyresampled函数实现图片缩放例子
2014/11/19 PHP
php+ajax实现文章自动保存的方法
2014/12/30 PHP
初识通用数据库操作类――前端easyui-datagrid,form(php)
2015/07/31 PHP
php无法连接mysql数据库的正确解决方法
2016/07/01 PHP
YII框架批量插入数据的方法
2017/03/18 PHP
PHP正则表达式处理函数(PCRE 函数)实例小结
2019/05/09 PHP
jQuery UI-Draggable 参数集合
2010/01/10 Javascript
firefox火狐浏览器与与ie兼容的2个问题总结
2010/07/20 Javascript
理解Javascript文件动态加载
2016/01/29 Javascript
jquery操作select元素和option的实例代码
2016/02/03 Javascript
整理关于Bootstrap导航的慕课笔记
2017/03/29 Javascript
bootstrap timepicker在angular中取值并转化为时间戳
2017/06/13 Javascript
10 种最常见的 Javascript 错误(频率最高)
2018/02/08 Javascript
JavaScript中0、空字符串、'0'是true还是false的知识点分享
2019/09/16 Javascript
jQuery实现的上拉刷新功能组件示例
2020/05/01 jQuery
[47:22]Mineski vs Winstrike 2018国际邀请赛小组赛BO2 第二场 8.16
2018/08/17 DOTA
[06:43]2018DOTA2国际邀请赛寻真——VGJ.Thunder
2018/08/11 DOTA
python实现dnspod自动更新dns解析的方法
2014/02/14 Python
在python中的socket模块使用代理实例
2014/05/29 Python
Python实现ssh批量登录并执行命令
2016/10/25 Python
Python 模拟购物车的实例讲解
2017/09/11 Python
python 编写简单网页服务器的实例
2018/06/01 Python
python自动循环定时开关机(非重启)测试
2019/08/26 Python
露营世界:Camping World
2017/02/02 全球购物
软件设计的目标是什么
2016/12/04 面试题
2014年教师政治学习材料
2014/06/02 职场文书
项目申报专员岗位职责
2014/07/09 职场文书
2014年保卫工作总结
2014/12/05 职场文书
单位同意报考证明
2015/06/17 职场文书
2019运动会广播加油稿汇总
2019/08/21 职场文书
MySQL中的引号和反引号的区别与用法详解
2021/10/24 MySQL
零基础学java之带返回值的方法的定义和调用
2022/04/10 Java/Android
vue 把二维或多维数组转一维数组
2022/04/24 Vue.js
Java 多态分析
2022/04/26 Java/Android
python区块链持久化和命令行接口实现简版
2022/05/25 Python