Les gens qui conduisent des voitures ne comprennent souvent pas la structure de la voiture, mais une compréhension approfondie de la structure de la voiture peut être encore plus puissante
À mesure que les nouvelles de vue3.x
augmentent, les discussions sur proxy
augmentent également. Par rapport à Object.defineProperty
, quelles sont les différences, les avantages et les applications de proxy
? Cet article présente brièvement
Avant de parler de proxy
, passons en revue Object.defineProperty
d'abord. Comme nous le savons tous, vue2.x
et les versions précédentes utilisent Object.defineProperty
pour réaliser une liaison bidirectionnelle de données. Quant à savoir comment les lier ? Implémentons simplement
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)
et exécutons-le dans console
du navigateur. Il semble fonctionner normalement
Mais en fait, Object.defineProperty
a le. problèmes suivants Plusieurs
questions 1. La suppression ou l'ajout d'attributs d'objet ne peut pas être surveillé
Par exemple, l'ajout d'un attribut gender
, car il n'y a pas un tel attribut lors de l'exécution de observer(obj)
, donc ceci ne peut pas être surveillé arriver. Les attributs supprimés ne peuvent pas être surveillés. Lorsque
ajoute des attributs,
vue
doit utiliser$set
pour fonctionner, et$set
utilise égalementObject.defineProperty
pour fonctionner en interne
Problème 2. Les modifications dans le tableau ne peuvent pas être surveillées
Comme le montre l'image ci-dessus, bien que les attributs du tableau soient effectivement modifié avec succès Mais il ne peut pas être surveillé
Question 3.
Puisque l'objet est parcouru de manière récursive, Object.defineProperty
est utilisé pour détourner les propriétés de l'objet. Si le niveau de l'objet traversé est profond, cela prendra beaucoup de temps et il peut même y avoir des problèmes de performances
, la description sur mdn est : L'objet est utilisé pour définir des comportements personnalisés pour les opérations de base (telles que la recherche d'attributs, l'affectation, l'énumération, l'appel de fonction, etc.) proxy
est plus facile à utiliser que proxy
et est beaucoup plus simple, et c'est en fait le cas . Utilisons un proxy pour réécrire le code ci-dessus et essayons 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)
ne peut pas do , par exemple, l'ajout d'un attribut Object.defineProperty
peut surveiller le tableau d'opérations gender
Ce qui est intercepté est l'attribut de l'objet, qui changera l'objet d'origine. Object.defineProperty
intercepte l'objet entier et génère un nouvel objet via new sans changer l'objet d'origine. proxy
. Il existe de nombreuses façons de choisir. Le proxy peut également surveiller certaines opérations qui ne peuvent pas être surveillées par proxy
, telles que la surveillance des tableaux, la surveillance de l'ajout et de la suppression d'attributs d'objet, etc. Object.defineProperty
, en raison des limitations d'espace, en voici quelques-uns. Vous pouvez en trouver davantage sur mes notes github ou. mdn. proxy
. Mais en développement, quels sont les scénarios dans lesquels proxy
peut être utilisé ? Voici quelques situations que vous pouvez rencontrer : proxy
, splice(-1)
Lors de l'utilisation de l'API, lorsqu'un nombre négatif est saisi, le dernier élément du tableau sera positionné. Cependant, les nombres négatifs ne peuvent pas être utilisés sur des tableaux ordinaires. slice(-1)
Ce code n'affiche pas 3 . Pour que le code ci-dessus génère 3, vous pouvez également utiliser [1,2,3][-1]
pour y parvenir. proxy
<br>
在对表单的值进行改动的时候,可以在 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)
<br>
推荐教程:《JS教程》 <br>
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!