Vue 3.0のProxyを簡単に理解
9431 ワード
目次 Proxy Vue 2.0使用 Vue 3.0使用 Proxyの他のアプリケーション Proxy
エージェントとは、オブジェクトの前に「ブロック」を設定し、そのオブジェクトがアクセスされると、このレイヤを通過しなければならないと理解できます.このブロックでさまざまな操作を行うことができることを意味します.たとえば、このレイヤブロックで元のオブジェクトを処理し、戻りたいデータ構造を返すことができます.
ES 6は、Proxyコンストラクション関数を原生的に提供し、MDNでは、Proxyオブジェクトが基本操作を定義するためのカスタム動作(属性検索、付与、列挙、関数呼び出しなど)として解釈されます.
まず使い方を見てみましょう.
注意Proxyはオブジェクトを操作するために使用されます.エージェントの目的は、オブジェクトの能力を拡張することです.
もう1つの例を見ると、オブジェクトのnameプロパティを外部で変更することはできません.
babelは、新しいAPI(Array.from、Array.prototype.includesなど)のように、構文を変換するために使用されます.[core-js/stable]()や[regenerator-runtime/runtime](PS:babel 7.x以降@babel/polyfillは推奨されていません)など、追加のパッケージをインストールしてサポートする必要があります.その後、API(String#normalize、Proxy、fetchなど)もあります.
core-js#missing-polyfills .
vue 2.xはどのようにデータの応答を実現しますか?
dataのデータを再帰的に巡回し、Object.defineProperty()getterとsetterをハイジャックし、getterでデータ依存収集処理を行い、setterでデータの変化を傍受し、現在のデータを購読する場所を通知する.部分ソースsrc/core/observer/index.js#L 156-L 193、バージョン2.6.11は以下の通り
このようにするのはどんな問題がありますか.オブジェクト属性の追加と削除が検出されない:オブジェクトに属性を追加した場合 配列の下付き文字の変化をモニタできず、直接配列の下付き文字で配列に値を設定し、リアルタイムで応答できない. data中のデータが多く、階層が深い場合、data中のすべてのデータを遍歴して応答式に設定するため、パフォーマンスに問題があります.
vue 3.0はProxyを使用しています
vue 3.0はまだ正式にリリースされていませんが、vue-nextの関連コードはすでにオープンソースで、現在Alphaバージョンにあります.
どうしてProxyを使って上記の問題を解決できるのですか?主にProxyはブロック対象であるため、
簡単な
以下、それぞれ
使用
上のコードの実行結果は
オブジェクトに属性が追加され、内部では傍受されていないことがわかります.追加された属性は手動で再使用する必要があります
以下、使用
次の出力が表示されます
Reflect(ES 6導入)は、JavaScript操作をブロックする方法を提供する内蔵オブジェクトです.Objectオブジェクトのいくつかを明らかに言語の内部の方法に属します(例えば
MDN
Proxyのその他の応用
まもなくリリースされるdobjs/dobmobxをproxyで書き換える一案です. immer可変データ型を実現する.immerのやり方はstateを内部で維持し、すべての操作をハイジャックし、内部で変化があるかどうかを判断し、最終的にどのように戻るかを決定することであり、具体的な内容はmmer.jsの概要とソースコードの概要この文章を見ることができる.
いずれも、オブジェクトを読み書きブロックし、読み書きに追加の判断と操作を行うために使用されます.
まとめ
リファレンス しんとうおうとうしきのげんり リストレンダリング ECMAScript 6入門-Proxy MDN-proxy 面接官:双方向バインドProxyの実現はdefinepropertyより優劣はどうですか。 申し訳ありませんが、Proxyをマスターするのは本当にやりたいことができます。 immer.jsの概要とソースコードの概要
Object.defineProperty()
データ応答の実現Proxy
エージェントとは、オブジェクトの前に「ブロック」を設定し、そのオブジェクトがアクセスされると、このレイヤを通過しなければならないと理解できます.このブロックでさまざまな操作を行うことができることを意味します.たとえば、このレイヤブロックで元のオブジェクトを処理し、戻りたいデータ構造を返すことができます.
ES 6は、Proxyコンストラクション関数を原生的に提供し、MDNでは、Proxyオブジェクトが基本操作を定義するためのカスタム動作(属性検索、付与、列挙、関数呼び出しなど)として解釈されます.
まず使い方を見てみましょう.
const p = new Proxy(target, handler);
target
:ブロックする対象オブジェクト(オリジナル配列、関数、さらには別のエージェントを含む任意のタイプのオブジェクト)handler
:1つのオブジェクト、ブロックする行為を定義するconst p = new Proxy({}, {
get(target, propKey) {
return ' , ';
}
});
console.log(p.name);
// ,
注意Proxyはオブジェクトを操作するために使用されます.エージェントの目的は、オブジェクトの能力を拡張することです.
もう1つの例を見ると、オブジェクトのnameプロパティを外部で変更することはできません.
const p = new Proxy({}, {
set(target, propKey, value) {
if (propKey === 'name') {
throw new TypeError('name ');
}
// name ,
target[propKey] = value;
}
});
p.name = 'proxy';
// TypeError: name
p.a = 111;
console.log(p.a); // 111
babelは、新しいAPI(Array.from、Array.prototype.includesなど)のように、構文を変換するために使用されます.[core-js/stable]()や[regenerator-runtime/runtime](PS:babel 7.x以降@babel/polyfillは推奨されていません)など、追加のパッケージをインストールしてサポートする必要があります.その後、API(String#normalize、Proxy、fetchなど)もあります.
core-js
中はしばらくpolyfillを提供していないので、具体的には公式文書を見ることができますcore-js#missing-polyfills .
Proxy
サポートされているブロック操作は全部で13種類あり、詳細は閲覧可能MDN.vue 2.xはどのようにデータの応答を実現しますか?
dataのデータを再帰的に巡回し、Object.defineProperty()getterとsetterをハイジャックし、getterでデータ依存収集処理を行い、setterでデータの変化を傍受し、現在のデータを購読する場所を通知する.部分ソースsrc/core/observer/index.js#L 156-L 193、バージョン2.6.11は以下の通り
let childOb = !shallow && observe(val)
// data ,
Object.defineProperty(obj, key, {
enumerable: true,
configurable: true,
get: function reactiveGetter () {
const value = getter ? getter.call(obj) : val
if (Dep.target) {
//
dep.depend()
if (childOb) {
childOb.dep.depend()
if (Array.isArray(value)) {
// , , 。
dependArray(value)
}
}
}
return value
},
set: function reactiveSetter (newVal) {
const value = getter ? getter.call(obj) : val
/* eslint-disable no-self-compare */
if (newVal === value || (newVal !== newVal && value !== value)) {
return
}
/* eslint-enable no-self-compare */
if (process.env.NODE_ENV !== 'production' && customSetter) {
customSetter()
}
if (getter && !setter) return
if (setter) {
setter.call(obj, newVal)
} else {
val = newVal
}
// observe,
childOb = !shallow && observe(newVal)
//
dep.notify()
}
})
このようにするのはどんな問題がありますか.
newProperty
現在追加されているこの属性は、vue検出データ更新のメカニズムを追加していない(初期化後に追加されたため).vue.$set
あなたが属性を追加したことをvueに知らせることができます.それはあなたに処理します.$set
内部も呼び出しです.Object.defineProperty()
処理します.vue 3.0はProxyを使用しています
vue 3.0はまだ正式にリリースされていませんが、vue-nextの関連コードはすでにオープンソースで、現在Alphaバージョンにあります.
どうしてProxyを使って上記の問題を解決できるのですか?主にProxyはブロック対象であるため、
に対して「ブロック」を行い、外部からのアクセスは、まずこのレベルでブロックしなければならない.オブジェクトにアクセスするプロパティにかかわらず、以前に定義されたプロパティも追加されたプロパティもブロックに移動します.簡単な
以下、それぞれ
Object.defineProperty()
とProxy
で簡単なデータ応答を実現使用
Object.defineProperty()
実装:class Observer {
constructor(data) {
// data , this
for(let key of Object.keys(data)) {
if(typeof data[key] === 'object') {
data[key] = new Observer(data[key]);
}
Object.defineProperty(this, key, {
enumerable: true,
configurable: true,
get() {
console.log(' ' + key);
return data[key]; // , ;
},
set(newVal) {
console.log(' ' + key);
console.log(' ' + key + '=' + newVal);
if(newVal === data[key]) {
return;
}
data[key] = newVal;
}
})
}
}
}
const obj = {
name: 'app',
age: '18',
a: {
b: 1,
c: 2,
},
}
const app = new Observer(obj);
app.age = 20;
console.log(app.age);
app.newPropKey = ' ';
console.log(app.newPropKey);
上のコードの実行結果は
// obj age
age
age=20
age
20
//
オブジェクトに属性が追加され、内部では傍受されていないことがわかります.追加された属性は手動で再使用する必要があります
Object.defineProperty()
傍受を行います.その理由vue 2.x
ではオブジェクト属性の追加と削除が検出されないため、内部提供$set
は呼び出しObject.defineProperty()
で処理される.以下、使用
Proxy
代替Object.defineProperty()
実装const obj = {
name: 'app',
age: '18',
a: {
b: 1,
c: 2,
},
}
const p = new Proxy(obj, {
get(target, propKey, receiver) {
console.log(' ' + propKey);
return Reflect.get(target, propKey, receiver);
},
set(target, propKey, value, receiver) {
console.log(' ' + propKey);
console.log(' ' + propKey + '=' + value);
Reflect.set(target, propKey, value, receiver);
}
});
p.age = '20';
console.log(p.age);
p.newPropKey = ' ';
console.log(p.newPropKey);
次の出力が表示されます
// age
age
age=20
age
20
//
newPropKey
newPropKey=
newPropKey
Proxy
オブジェクトに対する操作であり、オブジェクトにアクセスすればProxy
の論理に進むため、新しい属性は、応答式処理を再追加する必要はないことがわかります.Reflect(ES 6導入)は、JavaScript操作をブロックする方法を提供する内蔵オブジェクトです.Objectオブジェクトのいくつかを明らかに言語の内部の方法に属します(例えば
Object.defineProperty()
)Reflect
対象上.いくつかのObjectメソッドの戻り結果を修正し、より合理的にします.Object操作を関数動作にします.詳細の表示MDN
Proxyのその他の応用
まもなくリリースされる
vue 3.0
他に、どのようなライブラリが使用されているProxy
でしょうか.いずれも、オブジェクトを読み書きブロックし、読み書きに追加の判断と操作を行うために使用されます.
まとめ
Proxy
オブジェクトを操作するための、オブジェクトを広げる能力です.Object.defineProperty()
オブジェクト属性の操作です.vue2.x
使用Object.defineProperty()
データの応答式を実現するがObject.defineProperty()
オブジェクト属性に対する操作であるため、オブジェクトに対して深さ遍歴して属性を操作する必要がある.vue3.0
用Proxy
オブジェクトをブロック操作し、オブジェクトに対してどのような操作をしてもProxyの処理ロジックに進むvue3.0
・dobjs/dob
・immer
などのライブラリは現在使用されているProxy
対象を読み書きブロックし、追加の処理を行う.リファレンス