大家都熟悉Vue中依靠Object.defineProperty()
來(lái)進(jìn)行數(shù)據(jù)劫持,他像一個(gè)攔截器一樣監(jiān)控著一個(gè)對(duì)象上屬性的改變荞雏。但是并不能深度監(jiān)測(cè)到對(duì)象屬性的變化箱蟆,雖然Vue重寫了一些array的原型鏈上的方法瞎疼,如push()
咏花、shift()
等矗蕊,Vue官方也提供了方法Vue.set( target, propertyName/index, value )
(target可以是數(shù)組也可以是對(duì)象)來(lái)解決這些問(wèn)題拿愧,但是手動(dòng)操作很不方便杠河。
在Vue迎來(lái)3.0更新的時(shí)候,同樣Vue將用proxy
來(lái)實(shí)現(xiàn)數(shù)據(jù)劫持浇辜,接下來(lái)介紹介紹proxy
有什么方便的地方吧券敌。
proxy
語(yǔ)法如下
// const p = new Proxy(target, handler)
const handler = {
get: function(obj, prop) {
return prop in obj ? obj[prop] : 37;
}
};
const p = new Proxy({}, handler);
p.a = 1;
p.b = undefined;
console.log(p.a, p.b); // 1, undefined
console.log('c' in p, p.c); // false, 37
很顯然proxy
相比Object.defineProperty()
可以攔截屬性的添加了,proxy不僅僅只有g(shù)et柳洋,set攔截操作
handler.getOwnPropertyDescriptor()
這些都可以很多方法操作進(jìn)行攔截
同樣Vue3.0在實(shí)現(xiàn)數(shù)據(jù)劫持的時(shí)候還用到了Reflect屬性
與大多數(shù)全局對(duì)象不同待诅,Reflect
不是一個(gè)構(gòu)造函數(shù)。你不能將其與一個(gè)new運(yùn)算符一起使用熊镣,或者將Reflect
對(duì)象作為一個(gè)函數(shù)來(lái)調(diào)用卑雁。Reflect
的所有屬性和方法都是靜態(tài)的(就像Math對(duì)象)。它可以修改一個(gè)對(duì)象的屬性等绪囱。在這里不再贅述测蹲。
使用proxy
實(shí)現(xiàn)雙向綁定
<div id="app">
<input type="text" id="input" />
<div>您輸入的是: <span id="title"></span></div>
<button type="button" name="button" id="btn">添加到todolist</button>
<ul id="list"></ul>
</div>
const obj = {};
const input = document.getElementById("input");
const title = document.getElementById("title");
const newObj = new Proxy(obj, {
get: function(target, key, receiver) {
console.log(`getting ${key}!`);
return Reflect.get(target, key, receiver);
},
set: function(target, key, value, receiver) {
console.log(target, key, value, receiver);
if (key === "text") {
input.value = value;
title.innerHTML = value;
}
return Reflect.set(target, key, value, receiver);
}
});
input.addEventListener("keyup", function(e) {
newObj.text = e.target.value;
});