Vue数据驱动模拟实现4
一、前言
在"模拟vue之数据驱动3"中,我们实现了为每个对象扩展一个$set方法,用于新增属性使用,这样就可以监听新增的属性了。
当然,数组也是对象,也可以通过$set方法实现新增属性。
但是,对于数组而言,通常我们是通过push之类的方法吧。
ps:vue中明确指出push、pop、shift、unshift、splice、sort、reverse方法为变异方法,可以通过它们监听属性变化,触发视图更新(详情见)
下面,我们就一起来实现这些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.
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
上一篇: 解救被百度搜索降权网站关键词的两种方法
推荐阅读
-
利用Python如何实现数据驱动的接口自动化测试
-
php 数据处理之四舍五入取整实现4种方法
-
Vue Cli3.x-4.x 实现rem适配
-
vue.js通过自定义指令实现数据拉取更新的实现方法
-
vue 使用 async 和 await 实现异步 axios 同步化(实战案例:数据异步校验通过后,再执行保存)
-
Spring boot + mybatis + Vue.js + ElementUI 实现数据的增删改查实例代码(一)
-
Spring boot + mybatis + Vue.js + ElementUI 实现数据的增删改查实例代码(二)
-
Vue2.0实现组件之间数据交互和通信操作示例
-
深入浅出 Vue 系列 -- 数据劫持实现原理
-
Vue源码学习之关于对Array的数据侦听实现