プロキシは、その名前が示すように、オブジェクトとその属性値の間にプロキシを設定し、オブジェクトの値を取得または設定し、インスタンス化やその他の多くの操作をインターセプトします。この後、次の処理を行うことができます。 1 つのレイヤーを統合して「エージェント」と考えることができます。
問題の紹介:
//问题: 能够在obj.data修改成222之前拦截到这个操作
/*
本质上, 我们想要在修改属性值的同时, 去修改DOM值, 即做到同步更新页面
*/
let obj = {
data: "111"
}
obj.data = "222"
ES6 以前の方法で解決する場合は、Object.defineProperty(object, property, {}) を使用します。
let obj = {}
Object.defineProperty(obj, "data", {
get() {
console.log("get"); // 属性被访问时调用
},
set() {
console.log("set"); // 属性被修改时调用
}
})
console.log(obj.data); // get undefined <-此时调用get
obj.data = "test" // set <-此时调用set
実用的なアプリケーション: オブジェクトのプロパティを更新し、ページを同時に更新する
let obj = {}
Object.defineProperty(obj, "data", {
get() {
console.log("get");
return box.innerHTML
},
set(value) {
console.log("set");
box.innerHTML = value
}
})
console.log(obj.data);
obj.data = "test"
注: vue3 以降、Object.defineProperty は Proxy に置き換えられます。
Object.defineProperty の欠点を要約すると、次のようになります。
1 - 一度にインターセプトできる属性は 1 つだけです
2- オブジェクトのみを傍受できます
プロキシのメソッドは次のとおりです。
get メソッド: プロパティにアクセスするとトリガーされます
let target = {}
let proxy = new Proxy(target,{
get(target,prop){
return target[prop]
}
})
set メソッド: プロパティが変更されたときにトリガーされます
let target = {}
let proxy = new Proxy(target,{
get(target,prop){
return target[prop]
},
set(target,prop,value){
if(prop==="data"){
box.innerHTML = value
}
target[prop] = value;
}
})
has メソッド: 特定の属性があるかどうかを判断します (プロキシの下で使用し、”属性” in proxy
判定に渡す必要があります**)**
let target = {
_prop: "内部数据"
}
let proxy = new Proxy(target, {
get(target, prop) {
return target[prop]
},
set(target, prop, value) {
if (prop === "data") {
box.innerHTML = value
}
target[prop] = value;
},
has(target, key) {
if (key[0] === '_') {
return false;
}
return key in target;
}
})
注:”属性” in proxy
メソッドを使用して、オブジェクトに属性があるかどうかを判断できます。
この質問
プロキシの get と set の this はプロキシを指しているため、オブジェクト メソッドの場合は this を変更する必要があります。
let s = new Set()
let proxy = new Proxy(s, {
get(target, key) {
// 如果是方法, 需要修正this指向
let value = target[key]
if(value instanceof Function) {
return value.bind(target)
}
return value
},
set() {
console.log("set");
}
})
//proxy.add(1) // Uncaught TypeError: Method Set.prototype.add called on incompatible receiver #<Set>
//修改后:
console.log(proxy.add(1)); // Set(1) {1}
プロキシは本質的にメタプログラミングの非破壊的なデータハイジャックであり、元のオブジェクトに影響を与えることなく、元のオブジェクトに基づいて関数を派生するものであり、疎結合と高凝集性の設計概念に準拠しています。