Я думаю, что это ключевая часть вашего вопроса:
как это работает с привязкой к DOM
То, как вы написали свой код, делает этот вопрос простым, но здесь есть несколько этапов, которые не очевидны сразу.
- При создании экземпляра Vue содержимое вашего элемента
container
используется в качестве шаблона. Сами DOM-узлы затем выбрасываются. Это важно понимать, так как он значительно отличается от того, как много других фреймворков работают. Вы ничего не привязываете к этим узлам DOM, они просто шаблон.
- Этот шаблон затем компилируется в
render
функцию. Именно эту render
функцию вызовет Vue для визуализации компонента.
- Во время рендеринга функция
render
возвращает виртуальные узлы DOM (VDOM). Некоторые из этих узлов будут соответствовать элементам HTML, а другие будут ссылаться на дочерние компоненты. Дочерний компонент будет отображаться по очереди, и в конце концов, когда все компоненты будут отображены, все сводится к узлам HTML VDOM.
- Во время первоначального рендеринга эти узлы VDOM HTML довольно точно преобразуются в HTML DOM. Во время обновлений (повторного рендеринга) новый VDOM сравнивается с предыдущим VDOM, а фактический DOM обновляется только в том случае, если произошли изменения.
С точки зрения реактивности, render
очень похоже на вычисляемое свойство. Любые реактивные данные, которых касается функция render
, будут отслеживаться. Если эти данные впоследствии изменятся, это вызовет повторную визуализацию этого компонента.
Любые данные, которые не являются реактивными, отслеживаться не будут. Обновление этих данных не вызовет повторного рендеринга, не обновит вычисленные свойства и не вызовет watch
слушателей.
В вашем примере у вас есть один большой шаблон, который будет скомпилирован в одну render
функцию. Если какие-либо из реактивных данных изменятся, это вызовет повторную визуализацию. Это запустит всю функцию render
и создаст новое дерево VDOM. Доступ к данным осуществляется по мере необходимости и включает как реактивные, так и нереактивные данные.
Однако, если вы просто измените нереактивные данные, повторный рендеринг не сработает. В этом случае функция render
не будет вызвана и изменения DOM не произойдут.
Не позволяйте имени v-bind
сбить вас с толку. Это просто означает «это выражение JavaScript» и не обязательно связано с созданием зависимости. Зависимости отслеживаются на уровне функции render
, и нет специальной обработки для связи зависимостей напрямую с их узлами DOM. Если какая-либо зависимость изменится, вся функция render
будет перезапущена. Это не так дорого, как кажется, так как функция render
создает только VDOM. Дорогой процесс обновления DOM будет использовать различие / обновление VDOM, чтобы вносить только минимальные изменения, необходимые для обновления узлов DOM, которые в этом нуждаются. Прямая связь между данными и DOM, которая, по-видимому, существует в шаблоне, не сохраняется после выполнения шаблона.
Вычисленные свойства работают аналогично. Их значения кэшируются и пересчитываются только при обновлении реактивной зависимости. Если у них есть нереактивная зависимость, то это не сделает недействительным кэшированное значение. Однако если реактивная зависимость делает недействительным кэшированное значение, то любые измененные нереактивные зависимости будут по-прежнему извлекаться при вычислении нового значения.
Самый простой способ выяснить, является ли объект / массив реагирующим, состоит в том, чтобы зарегистрировать его на консоли. Когда Vue делает объект реактивным, он заменяет все его свойства геттерами и сеттерами, и это меняет его внешний вид в консоли.
Обычно Vue активирует объект только один раз, когда он впервые добавляется в data
. Только свойства, которые существуют в этой точке, будут иметь созданные методы получения и установки, что приводит к общей проблеме, заключающейся в том, что любые новые добавленные свойства не будут реагировать. Вот для чего Vue.set
и vm.$set
:
https://vuejs.org/v2/api/#vm-set
Vue недавно добавлено Vue.observable
, что позволяет сделать объекты реактивными без прохождения data
:
https://vuejs.org/v2/api/#Vue-observable