Люди, которые водят автомобили, часто не понимают устройства автомобиля, но глубокое понимание устройства автомобиля может оказать сильное влияние.
1. Введение
вместе сvue3.x
все больше новостей,proxy
дискуссии увеличиваются. относительноObject.defineProperty
,proxy
В чем разница, в чем преимущества и где можно применить. Эта статья кратко знакомит
2.Object.defineProperty
разговариватьproxy
Прежде, давайте рассмотримObject.defineProperty
. каждый знает,vue2.x
и предыдущие версии использовалиObject.defineProperty
Чтобы добиться двусторонней привязки данных, как ее привязать? Вот простая реализация
function observer(obj) {
if (typeof obj ==='object') {
for (let key in obj) {
if(obj.hasOwnProperty(key)){
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)
в браузереconsole
Выполняйте, вроде работает нормально
Но на самом деле,Object.defineProperty
Проблемы следующие
Проблема 1. Удаление или добавление свойств объекта не может быть отслежено
например, добавление атрибутаgender
, с момента выполненияobserver(obj)
Когда нет этого свойства, значит, за этим нельзя следить. Удаленные свойства также невозможно обнаружить
При добавлении атрибутов
vue
Нужно использовать$set
работать,$set
также используется внутрьObject.defineProperty
действовать
Проблема 2. Изменения массива не отслеживаются
Как видно из приведенного выше рисунка, несмотря на то, что свойство массива на самом деле успешно изменено, его невозможно отследить.
Вопрос 3.
Поскольку объект проходится рекурсивно, используйтеObject.defineProperty
Перехват свойств объекта, если пройденный уровень объекта глубокий, это займет много времени, и могут быть даже проблемы с производительностью
3.proxy
дляproxy
, описание на mdn: Объекты используются для определения пользовательского поведения для основных операций (таких как поиск свойств, назначение, перечисление, вызовы функций и т. д.)
Проще говоря, вы можете установить слой перехвата на целевой объект. Независимо от того, какая операция выполняется над целевым объектом, он должен пройти этот уровень перехвата.
это звучит как,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
Вещи, которые не могут быть сделаны, такие как добавление атрибутаgender
, может контролировать
Манипулировать массивами, вы также можете контролировать
Наконец, постучите по доске и кратко изложите разницу между двумя
1.Object.defineProperty
Перехват свойств объекта, изменение исходного объекта.proxy
Он перехватывает весь объект и генерирует новый объект через новый без изменения исходного объекта.
2.proxy
В дополнение к вышеперечисленным методам получения и установки существует 11 методов перехвата. Есть много способов выбратьProxy, вы также можете отслеживать некоторыеObject.defineProperty
Операции, которые невозможно контролировать, например, мониторинг массивов, мониторинг добавления и удаления свойств объекта и т. д.
4. сценарии использования прокси
оproxy
Сценарии использования , ограничены пространством, вот лишь несколько, можно переместить большеmdn.
см. здесь, разницу между двумя, иproxy
Преимущества уже известны. Но в разработке, какие сценарии можно использоватьproxy
Ну вот список возможных ситуаций
4-1 Массивы отрицательных индексов
В использованииsplice(-1)
,slice(-1)
При ожидании API, когда вводится отрицательное число, он находит последний элемент массива, но в обычном массиве отрицательные числа использовать нельзя.[1,2,3][-1]
Этот код не выводит 3 . Чтобы сделать приведенный выше вывод кода 3 , вы также можете использовать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)
4-2. Проверка формы
При изменении значения формы вы можете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=16
obj.age='少年'
4-3. Добавьте дополнительные атрибуты
Например, требуется гарантировать, что после того, как пользователь введет правильный идентификационный номер, к информации о пользователе будут добавлены дата рождения, место происхождения и пол.
Как мы все знаем, первая и вторая цифры идентификационного номера представляют провинцию (автономный район, муниципалитет центрального подчинения, особый административный район), а третья и четвертая цифры представляют город (город уровня префектуры, автономная префектура). , лига и муниципалитет, находящиеся в прямом подчинении центрального правительства) Краткое изложение кодекса округов и округов). Цифры с седьмой по четырнадцатую – это дата рождения. Нижние 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)
4-4 Форматирование данных
Например, есть требование передать временную метку на серверную часть, но веб-интерфейс получает строку времени, которую также можно использовать.proxy
Перехват, когда строка времени получена, метка времени может быть добавлена автоматически.
let ecDate = {
set (target, key, value, receiver) {
if(key === 'date'){
Reflect.set(target, 'timeStamp', +new Date(value), receiver)
}
return Reflect.set(target, key, value, receiver)
}
}
let obj=new Proxy({date:''},ecDate)
Ссылка на ссылку
Простое и популярное понимание прокси в Vue3.0
резюме
proxy
а такжеObject.defineproperty
некоторые отличия иproxy
Здесь кратко представлены преимущества и сценарии использования. Эта статья не очень глубокая, и ее не сложно понять. Что касается прокси, то автор также намерен продолжить углубленное изучение, и если в будущем будет какой-либо выигрыш, я поделюсь им как можно скорее. Если в статье есть какие-либо ошибки или у вас есть какие-либо предложения, пожалуйста, оставьте сообщение в области комментариев.
------------------------- Великолепная разделительная линия --------------------
Если вы хотите узнать больше и пообщаться со мной, добавьте меня в WeChat. Или обратите внимание на мой паблик WeChat: В ожидании книжного магазина