написать впереди
Эта тема довольно часто упоминается на собеседованиях, но если вы напишете в резюме: «Умение пользоватьсяVueи прочтите его исходный код», то интервьюер, скорее всего, задаст вам этот вопрос.
Какой?你简历上不写阅读过源码,那面试官也很有可能会问你是否阅读过响应式相关的源码
Продолжаем петь со словами:
挣不脱 逃不过
眉头解不开的结
命中解不开的劫
Общий процесс
как передняя частьMVVMРамка,Vueосновные идеи иAngular,ReactРазницы нет, ядро такое: при изменении данных автоматически обновлять страницуDOM, что позволяет намDOMОсвобожден от работы, чтобы сконцентрироваться на обработке бизнес-логики.
ЭтоVueдвусторонняя привязка данных (он же реактивный принцип). Двусторонняя привязка данныхVueОдна из самых уникальных особенностей. Здесь мы используем официальную блок-схему, чтобы кратко объяснитьVueВесь поток реактивной системы:
существуетVue, каждый экземпляр компонента имеет соответствующийwatcherЭкземпляр объекта, который будет записывать свойства как зависимости во время рендеринга компонента, а затем использовать их как зависимостиsetterПри вызове он уведомитwatcherПересчитать, что приведет к обновлению связанных с ним компонентов.
Это типичный паттерн наблюдателя.
ключевая роль
В логике реализации двусторонней привязки данных Vue есть три ключевые роли:
-
Observer: его роль заключается в добавлении к свойствам объектаgetterа такжеsetter, для сбора зависимостей и отправки обновлений -
Dep: используется для сбора зависимостей текущего реактивного объекта, каждый реактивный объект, включая подобъекты, имеетDepэкземпляр (внутриsubsдаWatcherмассив экземпляров), когда данные изменятся, он пройдетdep.notify()уведомить каждогоwatcher. -
Watcher: объект-наблюдатель, экземпляр разделен на渲染 watcher (render watcher),计算属性 watcher (computed watcher),侦听器 watcher(user watcher)три
Отношения между Наблюдателем и Депом
Почему этому вопросу должен быть посвящен отдельный раздел? Потому что большинство студентов знают только:VueПринцип отзывчивостиObject.definePropertyосуществленный. одеялоObject.definePropertyСвяжитесь на цели, это станет «адаптивной» технологией. То есть, чтобы изменить предмет, когда триггерgetа такжеsetмероприятие.
Однако не очень понятно про конкретные объектные зависимости внутри, что дает интервьюеру вид: вы просто запомнили ответ, и у вас не очень четкое представление о деталях внутренней реализации отзывчивости.
оWatcher 和 Dep 的关系На самом деле, я сначала не очень ясно представлял себе этот вопрос, но после ознакомления с соответствующими материалами я постепенно получил четкое представление о конкретной реализации.
новичок вDepСтуденты этого слова будут сбиты с толку:DepДля чего его используют? мы проходимdefineReactiveметод будетdataПосле того, как данные в представлении реагируют, хотя изменения в данных можно отслеживать, как мы обрабатываем обновление представления уведомлений?
Depпросто помогите нам依赖管理из.
Как показано выше: свойство может иметь несколько зависимостей, по одной для каждых реактивных данных.Depдля управления его зависимостями.
Параграф, резюмирующий принцип
Столько всего было сказано выше, так что позвольте мне подытожить.Vue响应式Основные идеи дизайна:
при созданииVueпример,vueпройдетdataсвойства опциона, используяObject.definePropertyдобавить в собственностьgetterа такжеsetterВзлом чтения данных (getterдля сбора зависимостей,setterиспользуется для отправки обновлений) и отслеживает внутренние зависимости, уведомляя об изменениях при доступе к свойствам и их изменении.
Каждый экземпляр компонента будет иметь соответствующийwatcherНапример, будут записываться все атрибуты данных зависимостей во время рендеринга компонента (сбор зависимостей иcomputed watcher,user watcherэкземпляр), когда зависимости будут изменены позже,setterметод будет уведомлять зависимости с этимdataизwatcherЭкземпляр повторно вычисляет (отправляет обновления), вызывая повторную визуализацию связанных с ним компонентов.
На данный момент мы поняли «рутину», давайте используем псевдокод для ее реализации.Vueотзывчивый!
основная реализация
/**
* @name Vue数据双向绑定(响应式系统)的实现原理
*/
// observe方法遍历并包装对象属性
function observe(target) {
// 若target是一个对象,则遍历它
if (target && typeof target === "Object") {
Object.keys(target).forEach((key) => {
// defineReactive方法会给目标属性装上“监听器”
defineReactive(target, key, target[key]);
});
}
}
// 定义defineReactive方法
function defineReactive(target, key, val) {
const dep = new Dep();
// 属性值也可能是object类型,这种情况下需要调用observe进行递归遍历
observe(val);
// 为当前属性安装监听器
Object.defineProperty(target, key, {
// 可枚举
enumerable: true,
// 不可配置
configurable: false,
get: function () {
return val;
},
// 监听器函数
set: function (value) {
dep.notify();
},
});
}
class Dep {
constructor() {
this.subs = [];
}
addSub(sub) {
this.subs.push(sub);
}
notify() {
this.subs.forEach((sub) => {
sub.update();
});
}
}