一、前言
在"模拟Vue之数据驱动2"中,我们实现了个Observer构造函数,通过它可以达到监听已有数据data中的所有属性。
但,倘若我们想在某个对象中,新增某个属性呢?
如下:
那么岂不是,新增的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数据驱动模拟实现1,包括了Vue数据驱动模拟实现1的使用技巧和注意事项,需要的朋友参考一下 一、前言 Vue有一核心就是数据驱动(Data Driven),允许我们采用简洁的模板语法来声明式的将数据渲染进DOM,且数据与DOM是绑定在一起的,这样当我们改变Vue实例的数据时,对应的DOM元素也就会改变了。 如下: 当我们在chrome控制台,更改vm.name时,页面中的数据也
本文向大家介绍Vue数据驱动模拟实现4,包括了Vue数据驱动模拟实现4的使用技巧和注意事项,需要的朋友参考一下 一、前言 在"模拟Vue之数据驱动3"中,我们实现了为每个对象扩展一个$set方法,用于新增属性使用,这样就可以监听新增的属性了。 当然,数组也是对象,也可以通过$set方法实现新增属性。 但是,对于数组而言,通常我们是通过push之类的方法吧。 PS:Vue中明确指出push、pop、
本文向大家介绍vue实现动态数据绑定,包括了vue实现动态数据绑定的使用技巧和注意事项,需要的朋友参考一下 实现的步骤: 1.监听对象属性的读取与变化 Object.defineProperty() 方法会直接在对象上定义一个新的的属性,或者已经存在的属性并且返回这个属性 语法是 Object.defineProperty(obj, prop, descript) obj: 目标对象 prop:
本文向大家介绍vue新vue-cli3环境配置和模拟json数据的实例,包括了vue新vue-cli3环境配置和模拟json数据的实例的使用技巧和注意事项,需要的朋友参考一下 最近在研究学习vue,发现环境配置特麻烦,就是跟着文档步骤一步一步来,也会遇到各种想不到的坑,vue-cli3的配置比老的简洁了很多,与以往的配置也有所不同: 1、安装步骤以前是 现在是: 2、vue-cli2 新建项目 v
本文向大家介绍Vue实现动态响应数据变化,包括了Vue实现动态响应数据变化的使用技巧和注意事项,需要的朋友参考一下 Vue是MVVM模式,即Model-View-ViewModel,通过绑定数据即可以实时改变视图显示。 比如:使用v-blink动态绑定属性 使用v-html来绑定带有标签的内容(会解析标签) 使用v-text来绑定纯文本的内容(标签会以文本的形式输出) 无论通过哪种形式绑定,都需要
本文向大家介绍Linux模拟实现sleep函数,包括了Linux模拟实现sleep函数的使用技巧和注意事项,需要的朋友参考一下 先来说说工作原理,linux中的sleep函数能够让程序休眠一定的秒数,到时间后自动恢复运行。 实现思路 设定睡眠的秒数 睡眠(挂起) 恢复运行 实现机制 设定睡眠的秒数:采用alarm()函数设定需要睡眠的秒数,到时间后闹钟会发送SIGALRM信号给当前进程。但SIGA