Пишите впереди:Утром 16 ноября автор Vue.js, Юда, сделал превью в своем программном выступлении на Vue Toronto.Некоторые новые функции Vue.js 3.0, одно из важных изменений заключается в том, что Vue3 будет использовать прокси-сервер ES6 в качестве механизма наблюдения, заменив ранее использовавшийся Object.defineProperty. Я считаю, что у многих студентов есть глубокое понимание. Во многих интервью Object.defineProperty является часто встречающейся точкой проверки фреймворка vue. Сначала все были немного незнакомы с этим свойством, и постепенно все больше и больше людей используют vue. , Это свойство часто используется всеми для исследования, и как раз после того, как все постепенно освоятся с этим свойством, автор Vue планирует заменить его на Proxy в следующей версии Vue. , ты не можешь выбраться Ха-ха. Хотя официальный релиз vue3 подождет до второй половины следующего года, мы можем изучить механизм наблюдателя, основанный на Proxy, и предсказать код vue3 на части Proxy (хотя, похоже, это не очень полезно, ха-ха).
1. Зачем заменять Object.defineProperty
Поскольку он заменит Object.defineProperty, у него должны быть некоторые очевидные недостатки, которые можно свести к следующим двум:
- Во Vue Object.defineProperty не может отслеживать изменение индекса массива, что приводит к установке значения массива напрямую через индекс массива, и не может реагировать в реальном времени. Чтобы решить эту проблему, можно использовать следующие методы для мониторинга массива после внутренней обработки Vue. (Как упоминалось в области комментариев, Object.defineProperty сам может отслеживать изменения индексов массива. Подробнее см.Почему Vue не может обнаружить изменения массива)
push()
pop()
shift()
unshift()
splice()
sort()
reverse()
Так как были взломаны только вышеперечисленные восемь методов, атрибуты других массивов не могут быть обнаружены, и они все еще имеют определенные ограничения.
- Object.defineProperty может только перехватывать свойства объектов, поэтому нам нужно перебирать каждое свойство каждого объекта. В Vue мониторинг данных достигается за счет рекурсии и обхода объекта данных.Если значение атрибута также является объектом, то требуется глубокий обход.Очевидно, что если весь объект может быть захвачен, это окажет большое влияние на работоспособность и производительность продвигать.
Прокси для его замены имеет следующие два преимущества;
- Может захватить весь объект и вернуть новый объект
- Проведено 13 операций по угону.
Увидев это, некоторые учащиеся могут задать вопрос: «Поскольку прокси может решить две вышеупомянутые проблемы, а атрибут прокси существует до vue2.x, почему vue2.x не использует прокси? Очень важная причина:
- Proxy — это новая функция, предоставляемая es6, и совместимость с ней плохая, самое главное, что это свойство не может быть совместимо с polyfill.
В комментариях напомнили, что на данный момент эффективного совместимого решения для Proxy нет, в будущем 3.0 и 2.0 будут распараллелены, и выбор IE 2.0 нужно поддерживать.
Что касается Object.defineProperty для реализации механизма наблюдателя, вы можете обратиться кАнализ принципа Vue и реализация двусторонней привязки MVVMВ этой статье следующий контент в основном знакомит с тем, как реализовать механизм наблюдения vue на основе прокси.
2. Что такое прокси
1. Значение:
- Прокси — это новая функция в ES6, которая переводится как «прокси» и используется здесь для обозначения «прокси» некоторых операций. Прокси позволяет нам контролировать внешний доступ к объектам лаконичным и понятным способом. Его функциональность очень похожа на шаблон прокси в шаблонах проектирования.
- Прокси можно понимать как настройку уровня «перехвата» перед целевым объектом, и доступ к объекту из внешнего мира должен сначала пройти этот уровень перехвата, поэтому он обеспечивает механизм фильтрации и перезаписи доступа к внешнему миру. .
- Основное преимущество использования Proxy заключается в том, что он может обрабатывать некоторую неосновную логику (например: ведение журнала перед чтением или установкой некоторых свойств объекта; перед установкой значений некоторых свойств объекта требуется аутентификация; контроль доступа к некоторым свойства) Подождите). Таким образом, объекту нужно сосредоточиться только на основной логике, чтобы добиться разделения задач и уменьшить сложность объекта.
2. Основное использование:
let p = new Proxy(target, handler);
параметр:
target— это проксируемый объект (который может быть объектом любого типа, включая собственные массивы, функции или даже другой прокси), обернутый в прокси.
handler— это объект, который объявляет некоторые операции для цели агента и чьи свойства являются функциями, определяющими поведение агента при выполнении операции.
pявляется проксируемым объектом. Каждый раз, когда внешний мир работает с p, выполняются некоторые методы объекта-обработчика. Прокси имеет в общей сложности 13 операций захвата.Некоторые распространенные методы прокси-обработчика следующие:
get:读取
set:修改
has:判断对象是否有该属性
construct:构造函数
3. Пример:
Давайте используем Proxy для определения получения и установки объекта в качестве базовой демонстрации.
let obj = {};
let handler = {
get(target, property) {
console.log(`${property} 被读取`);
return property in target ? target[property] : 3;
},
set(target, property, value) {
console.log(`${property} 被设置为 ${value}`);
target[property] = value;
}
}
let p = new Proxy(obj, handler);
p.name = 'tom' //name 被设置为 tom
p.age; //age 被读取 3
Когда p считывает значение свойства, он фактически выполняет handler.get() : выводит информацию на консоль и считывает свойства проксируемого объекта obj.
Когда p устанавливает значение свойства, он фактически выполняет handler.set() : выводит информацию на консоль и устанавливает значение свойства проксируемого объекта obj.
Основное использование Proxy было представлено выше.На самом деле у этого свойства много содержимого.Для получения подробной информации см.Документация по прокси
3. Двусторонняя привязка на основе прокси
Без дальнейших церемоний, давайте воспользуемся Proxy для реализации классического списка задач с двусторонней привязкой.Во-первых, просто напишите небольшую html-структуру:
<div id="app">
<input type="text" id="input" />
<div>您输入的是: <span id="title"></span></div>
<button type="button" name="button" id="btn">添加到todolist</button>
<ul id="list"></ul>
</div>
Сначала приходит прокси для реализации двустороннего отображения поля ввода:
const obj = {};
const input = document.getElementById("input");
const title = document.getElementById("title");
const newObj = new Proxy(obj, {
get: function(target, key, receiver) {
console.log(`getting ${key}!`);
return Reflect.get(target, key, receiver);
},
set: function(target, key, value, receiver) {
console.log(target, key, value, receiver);
if (key === "text") {
input.value = value;
title.innerHTML = value;
}
return Reflect.set(target, key, value, receiver);
}
});
input.addEventListener("keyup", function(e) {
newObj.text = e.target.value;
});
Этот код включаетReflectАтрибут, это также новая функция es6, студенты, которые мало что о ней знают, могут сослаться на нее.Отразить документацию.
Следующий шаг — добавить список задач и сначала отобразить массив на странице:
// 渲染todolist列表
const Render = {
// 初始化
init: function(arr) {
const fragment = document.createDocumentFragment();
for (let i = 0; i < arr.length; i++) {
const li = document.createElement("li");
li.textContent = arr[i];
fragment.appendChild(li);
}
list.appendChild(fragment);
},
addList: function(val) {
const li = document.createElement("li");
li.textContent = val;
list.appendChild(li);
}
};
Еще один прокси для добавления Todolist:
const arr = [];
// 监听数组
const newArr = new Proxy(arr, {
get: function(target, key, receiver) {
return Reflect.get(target, key, receiver);
},
set: function(target, key, value, receiver) {
console.log(target, key, value, receiver);
if (key !== "length") {
Render.addList(value);
}
return Reflect.set(target, key, value, receiver);
}
});
// 初始化
window.onload = function() {
Render.init(arr);
};
btn.addEventListener("click", function() {
newArr.push(parseInt(newObj.text));
});
Таким образом, реализуется простая двусторонняя привязка Todolist с помощью прокси. Конкретный код см.proxy.html
4. Реализация механизма наблюдателя vue на основе Proxy
1.Прокси реализует наблюдение
observe(data) {
const that = this;
let handler = {
get(target, property) {
return target[property];
},
set(target, key, value) {
let res = Reflect.set(target, key, value);
that.subscribe[key].map(item => {
item.update();
});
return res;
}
}
this.$data = new Proxy(data, handler);
}
В этом коде объект, возвращаемый прокси, проксируетсяthis.$data,Прямо сейчасthis.$dataобъект после прокси, каждый раз, когда внешнийthis.$dataПри выполнении операции фактически выполняется метод объекта-обработчика в этом коде.
2.компилировать и смотреть
Студенты, более знакомые с vue, совершенно ясно понимают, что vue2.x следует за new Vue(). Vue вызовет функцию _init для инициализации, она инициализирует жизненный цикл, события, реквизиты, методы, данные, вычисляемые и наблюдаемые данные и т. д. Наиболее важным из них является установка функций установки и получения через Object.defineProperty для достижения «отзывчивости» и «сбора зависимостей». Подобно следующей внутренней блок-схеме:
И мы использовали выше, прокси заменил Object.defineProperty эту часть механизма просмотра, и для достижения основного процесса привязки mvvm, в дополнение к ряду механизмов наблюдения, также необходимо скомпилировать и наблюдать, и мы здесь, как работа по компиляции шаблона, будет не запускать. Он описывает, для достижения добавленного Totolist на основе vue Proxy, где просто напишите компилировать и наблюдать за наблюдателем для поддержки работы конкретной ссылки на кодproxyVue,Этот код эквивалентен упрощенной версии vue на основе Proxy,в основном для реализации функции двусторонней привязки.Для удобства в html страницу вынесен js.Запустив его локально можно найти текущий эффект и Эффект третьей главы Достигнут консенсус Когда vue3 будет выпущен в следующем году, механизм наблюдателя, основанный на Proxy в его исходном коде, может сильно отличаться от реализации здесь Эта статья в основном представляет функцию Proxy и некоторые из ее приложений , И сам автор тоже многому научился, исследуя механизм наблюдателя Proxy, поэтому он интегрировал ресурсы и резюмировал эту статью. Надеюсь поделиться с вами. Выше мы увидимся в следующий раз.