скажи привет
Всем привет, я Дерек, и я снова с вами встречаюсь.
Когда я на шестой день пожаловался, почему праздник такой короткий, был уже седьмой день.
Желаю всем счастливого седьмого дня и хорошего начала работы! ! !
коммерческое время:
- Добро пожаловать на мой github:github.com/dravenww
- Добро пожаловать, чтобы пометить мой блоб:адрес блога
Текст начинается здесь.
Прокси-реализация Vue2
Как мы все знаем, способ реализации прокси в Vue2 — это перехват данных, то есть использованиеObject.defineProperty; Простой пример выглядит следующим образом:
var obj = {};
var initValue = 20;
Object.defineProperty(obj, "age", {
get: function () {
console.log('get')
return initValue;
},
set: function (value) {
console.log('set')
initValue = value;
}
});
console.log(obj.age);
obj.age = 22;
console.log(obj.age);
Как и выше, консоль выведет:
В Vue2 перехват данных фактически реализован таким образом, при котором get будет собирать зависимости:depend, набор вызовет зависимости --notify;прямой исходный код vue-defineReactive
Конечно, есть и обработка массивов, потому что массивы — это относительно особый тип данных, методы массивов в Vue2 были переупакованы, и методы изменения исходных данных массива были переупакованы следующим образом:push、pop、shift、unshift、splice、sort、reverse;Массив vue переупаковывает исходный код напрямую
Что касается того, как реализовано наблюдение в Vue2, я не буду здесь слишком много объяснять, вы можете прочитать эту статью.Интерпретация исходного кода Vue2 — наблюдение
Проблемы с прокси Vue2
В Vue2, даже если массив будет переупакован, все равно будут проблемы, а именно:
var list = ['tom', 'jack', 'draven', 'ifil']
// 直接改变数组的长度,Vue2是监听不到的,
list.length = 3;
// 直接改变数组中的某个元素,Vue2中也是监听不到的,
list[2] = 'luckyDraven';
Хотя Vue2 предоставляет метод Vue.$set для компенсации модификации массива в приведенном выше коде, он также создает дополнительную нагрузку для разработчиков. Официальная документация Vue2 об этой части также объясняет это.О массивах
Прокси для Vue3
Vue3 отказался от перехвата данных в пользуProxy+Reflectдля реализации брокера данных.
что такое прокси
Объект Proxy используется для создания прокси для объекта, позволяющего перехватывать и настраивать основные операции (такие как поиск свойств, назначение, перечисление, вызов функций и т. д.). Синтаксис конструктора Proxy:
const p = new Proxy(target, handler)
- target: целевой объект для переноса с помощью прокси (может быть объект любого типа, включая собственные массивы, функции или даже другой прокси).
- обработчик: объект, который обычно имеет функции в качестве атрибутов, и функции в каждом атрибуте определяют поведение прокси p при выполнении различных операций.
Методы, которые могут содержать обработчики (также называемые ловушками), следующие:
// Object.getPrototypeOf 方法的捕捉器。
handler.getPrototypeOf()
// Object.setPrototypeOf 方法的捕捉器。
handler.setPrototypeOf()
// Object.isExtensible 方法的捕捉器。
handler.isExtensible()
// Object.preventExtensions 方法的捕捉器。
handler.preventExtensions()
// Object.getOwnPropertyDescriptor 方法的捕捉器。
handler.getOwnPropertyDescriptor()
// Object.defineProperty 方法的捕捉器。
handler.defineProperty()
// in 操作符的捕捉器。
handler.has()
// 属性读取操作的捕捉器。
handler.get()
// 属性设置操作的捕捉器。
handler.set()
// delete 操作符的捕捉器。
handler.deleteProperty()
// Object.getOwnPropertyNames 方法和 Object.getOwnPropertySymbols 方法的捕捉器。
handler.ownKeys()
// 函数调用操作的捕捉器。
handler.apply()
// new 操作符的捕捉器。
handler.construct()
Вот официальный пример:
const handler = {
get: function(obj, prop) {
return prop in obj ? obj[prop] : 37;
}
};
const p = new Proxy({}, handler);
p.a = 1;
p.b = undefined;
console.log(p.a, p.b); // 1, undefined
console.log('c' in p, p.c); // false, 37
В приведенном выше простом примере, когда имя свойства не существует в объекте, возвращаемое значение по умолчанию равно 37. В приведенном выше коде показан сценарий использования обработчика get. Подробное описание можно перенестиОфициальный сайт Прокси
Что такое отражение
Reflect — это встроенный объект, предоставляющий методы для перехвата операций JavaScript. Эти методы такие же, как у обработчиков прокси. Reflect не является функциональным объектом, поэтому его нельзя построить.
В отличие от большинства глобальных объектов Reflect не является конструктором, поэтому его нельзя вызвать с помощью оператора new или объекта Reflect как функции. Все свойства и методы Reflect статичны (точно так же, как объекты Math).
Объекты Reflect предоставляют следующие статические методы, связанные сproxy handler methodsназываются одинаково.
грамматика:
// 对一个函数进行调用操作,同时可以传入一个数组作为调用参数。
// 和 Function.prototype.apply() 功能类似。
Reflect.apply(target, thisArgument, argumentsList)
// 对构造函数进行 new 操作,相当于执行 new target(...args)。
Reflect.construct(target, argumentsList[, newTarget])
// 和 Object.defineProperty() 类似。如果设置成功就会返回 true
Reflect.defineProperty(target, propertyKey, attributes)
// 作为函数的delete操作符,相当于执行 delete target[name]。
Reflect.deleteProperty(target, propertyKey)
// 获取对象身上某个属性的值,类似于 target[name]。
Reflect.get(target, propertyKey[, receiver])
// 类似于 Object.getOwnPropertyDescriptor()。
// 如果对象中存在该属性,则返回对应的属性描述符, 否则返回 undefined.
Reflect.getOwnPropertyDescriptor(target, propertyKey)
// 类似于 Object.getPrototypeOf()。
Reflect.getPrototypeOf(target)
// 判断一个对象是否存在某个属性,和 in 运算符 的功能完全相同。
Reflect.has(target, propertyKey)
// 类似于 Object.isExtensible().
Reflect.isExtensible(target)
// 返回一个包含所有自身属性(不包含继承属性)的数组。
// (类似于 Object.keys(), 但不会受enumerable影响).
Reflect.ownKeys(target)
// 类似于 Object.preventExtensions()。返回一个Boolean。
Reflect.preventExtensions(target)
// 将值分配给属性的函数。返回一个Boolean,如果更新成功,则返回true。
Reflect.set(target, propertyKey, value[, receiver])
// 设置对象原型的函数. 返回一个 Boolean, 如果更新成功,则返回true。
Reflect.setPrototypeOf(target, prototype)
Например:
-
Проверить, есть ли у объекта определенное свойство
const duck = { name: 'Maurice', color: 'white', greeting: function() { console.log(`Quaaaack! My name is ${this.name}`); } } Reflect.has(duck, 'color'); // true Reflect.has(duck, 'haircut'); // false -
Присвоить значение объекту и получить все свойства объекта
const duck = { name: 'Maurice', color: 'white', greeting: function() { console.log(`Quaaaack! My name is ${this.name}`); } } Reflect.set(duck, 'eyes', 'black'); // returns "true" if successful console.log(Reflect.ownKeys(duck)); // ["name", "color", "greeting", "eyes"]
Часть реализации
Прочитав это, вы должны увидеть, что существует однозначное соответствие между обработчиком в Proxy и статическими методами, поддерживаемыми в Reflect.
В Vue3 прокси-сервер данных реализуется через прокси-сервер в сочетании с Reflect для полного прокси-сервера. Для части анализа исходного кода вы можете проверить эту статьюИнтерпретация исходного кода Vue3 — createReactiveObject.
В Vue3 прокси данных реализуется путем вызова разных обработчиков через разные API. Вставьте картинку в интерпретацию исходного кода:
Сравнение прокси между Vue2 и Vue3
- через Vue2
Object.definePropertyМониторинг массивов не поддерживается, поддерживается только мониторинг объектов; - Давайте посмотрим на пример использования Proxy+Reflect в Vue3.
var list = ["tom", "jack"]; var proxy = new Proxy(list, { set: function (target, key, value) { Reflect.set(target, key, value); } }); proxy.length = 3; console.log(list); // ["tom", "jack", undefined] proxy[2] = "draven"; console.log(list); // ["tom", "jack", "draven"]
Видно, что длину и прямое назначение в Vue2 нельзя отслеживать с помощью Proxy+Reflect.
the last
Конечно, преимущества Proxy — это не только часть вышеперечисленного массива, но и некоторые другие преимущества, вы можете перейти на официальный сайт для более подробного ознакомления.
Все любят новое, на самом деле важен не результат, а исследованиеОбработать~
Спасибо за прочтение и удачи всем~
Если вы думаете, что это хорошо, поставьте большой палец вверх и вау~