車を運転する人は車の構造を理解していないことが多いですが、車の構造を深く理解することでさらに大きな効果が得られる可能性があります。
vue3.x のニュースが増えるにつれて、
proxy についての議論も増えています。
Object.defineProperty と比較した場合、
proxy の違い、利点、用途は何ですか?この記事では、
proxy について説明する前に、
Object.defineProperty を確認しましょう。ご存知のとおり、
vue2.x とそれ以前のバージョンでは、
Object.defineProperty を使用してデータの双方向バインドを実現しています。単純に実装しましょう
function observer(obj) { if (typeof obj === 'object') { for (let key in obj) { defineReactive(obj, key, obj[key]) } } } function defineReactive(obj, key, value) { //针对value是对象,递归检测 observer(value) //劫持对象的key Object.defineProperty(obj, key, { get() { console.log('获取:' + key) return value }, set(val) { //针对所设置的val是对象 observer(val) console.log(key + "-数据改变了") value = val } }) } let obj = { name: '守候', flag: { book: { name: 'js', page: 325 }, interest: ['火锅', '旅游'], } } observer(obj)
コンソール、正常に動作するように見えます
Object.defineProperty 問題は次のとおりです。
gender を追加すると、実行中、
observer(obj) にはこの属性がないため、監視できません。
を追加すると削除された属性は監視できません。vue
は
$setを使用して操作する必要があります。
$setObject.defineProperty
は内部的に操作にも使用されます
##問題 2. 配列の変更を監視できません
##上の図からわかるように、実際には配列属性は正常に変更されていますが、監視することはできません
質問 3。 オブジェクトは再帰的に走査されるため、Object.defineProperty
を使用してオブジェクトのプロパティがハイジャックされます。走査されるオブジェクト レベルが比較的深い場合は、時間がかかり、パフォーマンスの問題が発生する可能性もあります proxy
簡単に言うと、ターゲット オブジェクトにインターセプトのレイヤーを設定できます。ターゲット オブジェクトに対してどのような操作が実行される場合でも、このインターセプト層を通過する必要があります。
proxy
はObject.defineProperty よりも使いやすいようです。実際、それだけです。プロキシを使用して上記のコードを書き換えて試してみましょう
function observerProxy(obj) { let handler = { get(target, key, receiver) { console.log('获取:' + key) // 如果是对象,就递归添加 proxy 拦截 if (typeof target[key] === 'object' && target[key] !== null) { return new Proxy(target[key], handler) } return Reflect.get(target, key, receiver) }, set(target, key, value, receiver) { console.log(key + "-数据改变了") return Reflect.set(target, key, value, receiver) } } return new Proxy(obj, handler) } let obj = { name: '守候', flag: { book: { name: 'js', page: 325 }, interest: ['火锅', '旅游'], } } let objTest = observerProxy(obj)
同じ効果
##そして、Object.defineProperty Things属性
gender の追加などの実行できない操作は、
も監視できます。
最後に、黒板をノックして、2 つの違いを簡単にまとめます。1.
Object.definePropertyインターセプトされるのはオブジェクトのプロパティです。これにより、元のオブジェクトが変更されます。
proxy はオブジェクト全体をインターセプトし、元のオブジェクトを変更せずに new を通じて新しいオブジェクトを生成します。 2.
proxy
上記の get および set に加えて、他にも 11 個のインターセプト メソッドがあります。プロキシを選択するにはさまざまな方法があり、配列の監視、オブジェクト プロパティの追加と削除の監視など、
ではできない一部の操作を監視することもできます。 プロキシの使用シナリオ
これを見ると、この 2 つの違いと proxy
の利点がすでにわかりました。しかし、開発では、
はどのようなシナリオで使用できますか? 発生する可能性のあるいくつかの状況を次に示します 負のインデックス配列
[1,2,3][-1] このコードでは 3 を出力できません。上記のコードを出力 3 にするには、
proxy を使用することもできます。
rreeee<h3 class="heading" data-id="heading-5"><span style="font-size: 16px;">表单校验</span></h3>
<p>在对表单的值进行改动的时候,可以在 <code>set
里面进行拦截,判断值是否合法
let ecValidate = { set(target, key, value, receiver) { if (key === 'age') { //如果值小于0,或者不是正整数 if (value < 0 || !Number.isInteger(value)) { throw new TypeError('请输入正确的年龄'); } } return Reflect.set(target, key, value, receiver) } } let obj = new Proxy({ age: 18 }, ecValidate) obj.age = 16obj.age = '少年'
比如有一个需求,保证用户输入正确身份证号码之后,把出生年月,籍贯,性别都添加进用户信息里面
众所周知,身份证号码第一和第二位代表所在省(自治区,直辖市,特别行政区),第三和第四位代表所在市(地级市、自治州、盟及国家直辖市所属市辖区和县的汇总码)。第七至第十四位是出生年月日。低17位代表性别,男单女双。
const PROVINCE_NUMBER = { 44 : '广东省', 46 : '海南省' } const CITY_NUMBER = { 4401 : '广州市', 4601 : '海口市' } let ecCardNumber = { set(target, key, value, receiver) { if (key === 'cardNumber') { Reflect.set(target, 'hometown', PROVINCE_NUMBER[value.substr(0, 2)] + CITY_NUMBER[value.substr(0, 4)], receiver) Reflect.set(target, 'date', value.substr(6, 8), receiver) Reflect.set(target, 'gender', value.substr( - 2, 1) % 2 === 1 ? '男': '女', receiver) } return Reflect.set(target, key, value, receiver) } } let obj = new Proxy({ cardNumber: '' }, ecCardNumber)
比如有一个需求,需要传时间戳给到后端,但是前端拿到的是一个时间字符串,这个也可以用 proxy
进行拦截,当得到时间字符串之后,可以自动加上时间戳。
let ecArrayProxy = { get(target, key, receiver) { let _index = key < 0 ? target.length + Number(key) : key return Reflect.get(target, _index, receiver) } } let arr = new Proxy([1, 2, 3], ecArrayProxy)
推荐教程:《JS教程》
以上がJS Proxyのメリットと利用シーンの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。