一、前言
在"模拟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);
}
好了,一切完毕,接下来就测试下吧:
Vue,数据驱动
免责声明:本站文章均来自网站采集或用户投稿,网站不提供任何软件下载或自行开发的软件! 如有用户或公司发现本站内容信息存在侵权行为,请邮件告知! 858582#qq.com
《魔兽世界》大逃杀!60人新游玩模式《强袭风暴》3月21日上线
暴雪近日发布了《魔兽世界》10.2.6 更新内容,新游玩模式《强袭风暴》即将于3月21 日在亚服上线,届时玩家将前往阿拉希高地展开一场 60 人大逃杀对战。
艾泽拉斯的冒险者已经征服了艾泽拉斯的大地及遥远的彼岸。他们在对抗世界上最致命的敌人时展现出过人的手腕,并且成功阻止终结宇宙等级的威胁。当他们在为即将于《魔兽世界》资料片《地心之战》中来袭的萨拉塔斯势力做战斗准备时,他们还需要在熟悉的阿拉希高地面对一个全新的敌人──那就是彼此。在《巨龙崛起》10.2.6 更新的《强袭风暴》中,玩家将会进入一个全新的海盗主题大逃杀式限时活动,其中包含极高的风险和史诗级的奖励。
《强袭风暴》不是普通的战场,作为一个独立于主游戏之外的活动,玩家可以用大逃杀的风格来体验《魔兽世界》,不分职业、不分装备(除了你在赛局中捡到的),光是技巧和战略的强弱之分就能决定出谁才是能坚持到最后的赢家。本次活动将会开放单人和双人模式,玩家在加入海盗主题的预赛大厅区域前,可以从强袭风暴角色画面新增好友。游玩游戏将可以累计名望轨迹,《巨龙崛起》和《魔兽世界:巫妖王之怒 经典版》的玩家都可以获得奖励。

