模拟Vue之数据驱动4
一、前言 |
在"模拟Vue之数据驱动3"中,我们实现了为每个对象扩展一个$set方法,用于新增属性使用,这样就可以监听新增的属性了。
当然,数组也是对象,也可以通过$set方法实现新增属性。
但是,对于数组而言,通常我们是通过push之类的方法吧。
PS:Vue中明确指出push、pop、shift、unshift、splice、sort、reverse方法为变异方法,可以通过它们监听属性变化,触发视图更新(详情见here)
下面,我们就一起来实现这些Array的变异方法吧。
注:我们将Array变异方法实现,也写在extendObj.js中的,因为数组也是对象嘛。
二、Array变异方法实现 |
要实现这些变异方法,毫无疑问,我们会重写它们,那在Array.prototype里面重写吗?
当然不是,这样不就影响了所有数组对象的原型链了么!
为了避免这种情况,且,我们只是想在监听数据对象上继承这些变异数组方法,那么细心的你会发现,其实与我们在"模拟Vue之数据驱动3"中实现$set方法类似了。
首先,我们创建arrKeys对象用于保存需要变异的数组方法以及恒定对象extendArr,如下:
let arrKeys = ['push', 'pop', 'shift', 'unshift', 'splice', 'sort', 'reverse'];
const extendArr = [];
接着,就是在extendArr对象上,一一监听arrKeys中的方法了,与$set方法类似,整体结构如下:
!function(){
arrKeys.forEach(function(key){
proxyObject(extendArr, key, function(){
//TODO
});
});
}();
注:proxyObject方法其实核心就是Object.defineProperty,详见"模拟Vue之数据驱动3".
接下来,就是实现核心部分代码了,重写这些方法的目的,是为了监听数据变化,所以要在方法原有功能不变的情况下,重写它们,Array.xxx.apply即可实现原有功能。
且,push、unshift、splice这三个方法可以在原数组中,新增属性,故而,我们需要监听新增属性以及它们的属性值,这里就和$set方法完全一样了,通过$Observer,即可利用observe以及convert方法实现了。
实现代码如下:
!function(){
arrKeys.forEach(function(key){
proxyObject(extendArr, key, function(){
console.log('Fun ' + key + ' is observed');
let result;
let arrProto = Array.prototype;
let ob = this.$Observer;
let arr = arrProto.slice.call(arguments);
let inserted;
let index;
switch(key){
case 'push': {
inserted = arr;
index = this.length;
break;
}
case 'unshift': {
inserted = arr;
index = 0;
break;
}
case 'splice': {
inserted = arr.slice(2);
index = arr[0];
break;
}
}
result = arrProto[key].apply(this, arguments);
if(inserted){
inserted.forEach(val => {
ob.observe(val);
ob.convert(index++, val);
});
}
return result;
});
});
}();
代码稍长,请自行打开
最后,就是在需要监听的对象上继承这些变异方法咯,如下:
//observer.js
function Observer(data){
if(!(this instanceof Observer)){
return new Observer(data);
}
data.__proto__ = extendObj;
//继承变异方法push、pop等等
if(Array.isArray(data)){
data.__proto__.__proto__ = extendArr;
}
this.data = data;
this.walk(data);
}
好了,一切完毕,接下来就测试下呗:
<script src="./extendObj.js"></script>
<script src="./observer.js"></script>
<script>
'use strict';
let data = {
msg: [5, 2, 0],
user: {
name: 'Monkey',
age: 24
},
lover: {
name: 'Dorie',
age: 23
}
};
Observer(data);
</script>
效果如下:
Perfect,此时,你可能会想,数组方法中仅有push、unshift、splice会为数组新增属性,那么我们又何必将其他方法,例如sort、reverse重写呢,也没发现有什么猫腻呢?
不错,在此时,并没有什么卵用,但是,你要知道sort、reverse等这些方法,可是会引起数组变化的,那么就会影响视图展现,这些变化,又怎么通知数组呢?就是下篇随笔会具体说明的。
该篇随笔代码,详情见github.
模拟Vue之数据驱动4的更多相关文章
- 模拟Vue之数据驱动2
一.前言 在随笔“模拟Vue之数据驱动1”结尾处,我们说到如果监听的属性是个对象呢?那么这个对象中的其他属性岂不就是监听不了了吗? 如下: 倘若user中的name.age属性变化,如何知道它们变化了 ...
- 模拟Vue之数据驱动3
一.前言 在"模拟Vue之数据驱动2"中,我们实现了个Observer构造函数,通过它可以达到监听已有数据data中的所有属性. 但,倘若我们想在某个对象中,新增某个属性呢? 如下 ...
- 模拟Vue之数据驱动5
一.前言 在"模拟Vue之数据驱动4"中,我们实现了push.pop等数组变异方法. 但是,在随笔末尾我们提到,当pop.sort这些方法触发后,该怎么办呢?因为其实,它们并没有往 ...
- 模拟Vue之数据驱动
一.前言 在随笔"模拟Vue之数据驱动1"结尾处,我们说到如果监听的属性是个对象呢?那么这个对象中的其他属性岂不就是监听不了了吗? 如下: 倘若user中的name.age属性变化 ...
- 模拟Vue之数据驱动1
一.前言 Vue有一核心就是数据驱动(Data Driven),允许我们采用简洁的模板语法来声明式的将数据渲染进DOM,且数据与DOM是绑定在一起的,这样当我们改变Vue实例的数据时,对应的DOM元素 ...
- 模拟vue的tag属性,在react里实现自定义Link
我封装了一个简单的实现react里自定义Link的方法,方便大家使用. 因为普通组件没有metch.location.history等属性.只有在<Router>里面的<compon ...
- vue-toy: 200行代码模拟Vue实现
vue-toy 200行左右代码模拟vue实现,视图渲染部分使用React来代替Snabbdom,欢迎Star. 项目地址:https://github.com/bplok20010/vue-toy ...
- vue实现数据驱动视图原理
一.什么是数据驱动 数据驱动是vuejs最大的特点.在vuejs中,所谓的数据驱动就是当数据发生变化的时候,用户界面发生相应的变化,开发者不需要手动的去修改dom. 比如说我们点击一个button,需 ...
- 模拟vue实现简单的webpack打包
一.安装nodejs,查看是否安装成功 二.package.json项目初始化 npm init 电脑有node环境,在根目录下运行命令npm init初始化项目,根据提示输入项目相关信息,然后运行. ...
随机推荐
- Visual Studio 单元测试之三---压力测试
原文:Visual Studio 单元测试之三---压力测试 我们都知道大名鼎鼎的LoadRuner,但是很少有人知道Visual Studio自带的Test也可以做些简单的压力测试,下面我们就介绍一 ...
- .net操作PDF的一些资源(downmoon收集)
因为业务需要,搜集了一些.net操作pdf的一些资源,特在此分享. 1.如何从 Adobe 可移植文档格式 (PDF) 文件中复制文本和图形 http://support.microsoft.com/ ...
- 【jar包】JSON之解析利器GSON--【gson-2.2.4.jar】
Gson(又称Google Gson)是Google公司发布的一个开放源代码的Java库,主要用途为串行化Java对象为JSON字符串,或反串行化JSON字符串成Java对象.GSON核心jar包不到 ...
- WebService支持多平台上传文件的实现
WebService支持多平台上传文件的实现 要使用网站上传文件,在ASP.NET的范畴,我基本上能想到的有两类,一类是通过HTTP POST请求获得文件信息,另外一类是通过WebService或 ...
- 2008技术内幕:T-SQL语言基础
2008技术内幕:T-SQL语言基础 单表查询摘记 这里的摘抄来自<Microsoft SQL Server 2008技术内幕:T-SQL语言基础>,书中用到的案例数据库是这个 TSQLF ...
- Python的RotatingFileHandler的Bug
Python的库非常强大,基本能找到我们所有需要的lib.logging模块是Python中的日志记录库,借鉴了Java中的LOG4J模块的思想,能非常方便的用于记录软件执行日志. 最近有在开发自动化 ...
- 【GitHub】在Mac上配置/使用Github
以前一直听说过Github,但是自己一直不会用.最近不是太忙,于是想捣鼓捣鼓Github,没想到用了将近3个小时,才在Mac上配置成功. 首先简单介绍一下Git和Github 集中化的版本控制系统( ...
- [Usaco2008 Open] Clear And Present Danger 寻宝之路[最短路][水]
Description 农夫约翰正驾驶一条小艇在牛勒比海上航行. 海上有N(1≤N≤100)个岛屿,用1到N编号.约翰从1号小岛出发,最后到达N号小岛.一 张藏宝图上说,如果他的路程上 ...
- Leetcode:Minimus Depth of Binary Tree
The problem description: Given a binary tree, find its minimum depth. The minimum depth is the numbe ...
- CSS属性合写
animation:[[ animation-name ] || [ animation-duration ] || [ animation-timing-function ] || [ animat ...