предисловие
Ответ данных Vue в основном зависит отObject.defineProperty()
, тогда на что похож весь процесс? Путь Vue с нашими собственными идеями на самом деле является конечной точкой принципа Vue.Давайте продвинем процесс реализации в обратном направлении.
Все коды в этой статье являются низкоуровневыми версиями, и многие места не являются строгими, например
if(typeof obj === 'object')
это судитьobj
является объектом, хотяobj
Также могут быть другие типы данных, такие как массивы, но для простоты в этой статье это будет написано непосредственно для представления объекта суждения.Array.isArray()
.
Преобразование данных
Давайте сначала попробуем написать функцию для преобразования объекта:
Зачем вообще писать эту функцию? Поскольку преобразование данных является самым основным и самым важным шагом, все последующие шаги будут зависеть от этого шага.
// 代码 1.1
function defineReactive (obj,key,val) {
Object.defineProperty(obj,key,{
enumerable: true,
configurable: true,
get: function () {
return val;
},
set: function (newVal) {
//判断新值与旧值是否相等
//判断的后半段是为了验证新值与旧值都为NaN的情况 NaN不等于自身
if(newVal === val || (newVal !== newVal && value !== value)){
return ;
}
val = newVal;
}
});
}
Напримерconst obj = {}
, а затем позвонитеdefineReactive(obj,'a',2)
метод, на этот раз внутри функции,val=2
, а затем получать каждый разobj.a
получается, когда значениеval
значение, наборobj.a
также устанавливается, когдаval
ценность . (каждый звонокdefineReactive
создаст замыкание для сохраненияval
Стоимость);
Обсуждение процесса
После проверки выясняется, что эту функцию действительно можно использовать. Затем давайте обсудим поток ответа:
- Входные данные
- преобразовать данные (
defineReactive()
) - Если данные изменяются => инициировать событие
Давайте посмотрим на третий шаг, как изменения данных вызывают последующие события? Хорошо подумайте, если вы хотите изменить данные, вы должны сначалаset
данные, то мы напрямуюset()
Можно добавить метод внутрь.
Тогда важный вопрос:
Коллекция зависимостей
Откуда мы знаем, какое событие должно запускаться при изменении данных? Во Вью:
Используйте данные => представление; используйте данные для рендеринга представления, тогда самое лучшее время для сбора зависимостей при получении данных.Vue генерирует атрибут данных при его преобразовании.Dep
Экземпляр для сбора зависимостей.
// 代码 1.2
class Dep {
constructor(){
//订阅的信息
this.subs = [];
}
addSub(sub){
this.subs.push(sub);
}
removeSub (sub) {
remove(this.subs, sub);
}
//此方法的作用等同于 this.subs.push(Watcher);
depend(){
if (Dep.target) {
Dep.target.addDep(this);
}
}
//这个方法就是发布通知了 告诉你 有改变啦
notify(){
const subs = this.subs.slice()
for (let i = 0, l = subs.length; i < l; i++) {
subs[i].update();
}
}
}
Dep.target = null;
Код 1.2Dep
Часть кода, временно только нужно знать роль двух методов на нем
-
depend()
--- Можно понимать как сбор зависимых событий, независимо от других аспектов, функция эквивалентнаaddSub()
-
notify()
--- Этот метод более интуитивен и выполняет все зависимыеupdate()
метод. Это изменить представление позже и так далее.
В этой статье в основном обсуждается процесс ответа на данные, а не подробное обсуждение
Watcher
Сорт,Dep
Если вы знаете метод в, вы можете сделать это.
Тогда стоит изменить код 1.1
//代码 1.3
function defineReactive (obj,key,val) {
const dep = new Dep();
Object.defineProperty(obj,key,{
enumerable: true,
configurable: true,
get: function () {
if(Dep.target){
//收集依赖 等同于 dep.addSub(Dep.target)
dep.depend()
}
return val;
},
set: function (newVal) {
if(newVal === val || (newVal !== newVal && val !== val)){
return ;
}
val = newVal;
//发布改变
dep.notify();
}
});
}
В этом коде есть сомнение,Dep.target
что это такое? зачемDep.target
Будет ли он собирать зависимости?
-
Dep
это класс,Dep.target
является свойством класса, а неdep
Свойства экземпляра. -
Dep
Класс доступен по всему миру, поэтомуDep.target
К нему можно получить глобальный доступ, и его значение может быть изменено произвольно. -
get
Этот метод очень распространен, и его невозможно вызывать каждый раз, когда вы используете его для получения значения данных.dep.depend()
. -
dep.depend()
фактическиdep.addSub(Dep.target)
. - Тогда лучше всего перед использованием
Dep.target
Установить на объект, установить после завершения подпискиDep.target = null
.
проверять
Время проверить доступность волны кода
//代码 1.4
const obj = {};//这一句是不是感觉很熟悉 就相当于初始化vue的data ---- data:{obj:{}};
//低配的不能再低配的watcher对象(源码中是一个类,我这用一个对象代替了)
const watcher = {
addDep:function (dep) {
dep.addSub(this);
},
update:function(){
html();
}
}
//假装这个是渲染页面的
function html () {
document.querySelector('body').innerHTML = obj.html;
}
defineReactive(obj,'html','how are you');//定义响应式的数据
Dep.target = watcher;
html();//第一次渲染界面
Dep.target = null;
На данный момент интерфейс в браузере такой
Затем откройте консоль, чтобы начать отладку, и введите:
obj.html = 'I am fine thank you'
Затем я обнаружил, что в тот момент, когда я нажал Enter, произошло чудо, и страница стала
конец
Шаблон проектирования ответа данных Vue немного похож на шаблон подписки и публикации, но отличается, каждыйdep
Экземпляр — это центр подписки, и каждый выпуск будет публиковать все подписки.
На самом деле, большая часть принципа отзывчивости Vue по-прежнему сохраняется. В этой статье в основном обсуждается, как Vue заставляет данные реагировать, но на самом деле есть много общих данных. Одни данные используются в нескольких местах. После изменения данных наблюдайте как наблюдать, как подписываться и как планировать — все еще в значительной степени не обсуждалось. три основные категорииDep
(собирать зависимости),Observer
(данные наблюдений),Watcher
(Подписчики, если данные изменились, сообщите подписчикам), только немного упомянул.
я писал ранееVue реактивный ---- метод мутации массива, чтобы обсудить преобразование массивов в Vue. Конечно, в будущем статей будет больше.Во всем процессе ответа на данные еще много контента.Три основных класса еще не обсуждались.
На самом деле читать исходный код - это не только знать, как работает исходный код, но и узнавать идеи и методы автора.Статьи, которые я писал, не длинные. Надеюсь, что смогу сосредоточиться на одном моменте и по-настоящему понять этот принцип. Конечно, я также хочу контролировать время чтения, чтобы не быть закрытым, когда все это увидят.