Можете ли вы написать от руки принципы отзывчивости Vue2?

Vue.js опрос
Можете ли вы написать от руки принципы отзывчивости Vue2?

написать впереди

Эта тема довольно часто упоминается на собеседованиях, но если вы напишете в резюме: «Умение пользоваться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();
    });
  }
}