Реакционная способность для переменных, не связанных с данными, вычисляемыми и т. Д. - PullRequest
1 голос
/ 13 апреля 2019

После долгих испытаний и чтения vue.js я взялся за свое первое приложение с компонентами и т. Д. Я обнаружил, что сложно связать внешний объект с данными и выяснить, в каких условиях Vue связывает эти внешние объекты с атрибутами data / computed / watch / props . Я столкнулся с некоторыми странными сюрпризами с моими компонентами и решил изучить некоторые случаи с codepen . Моя главная проблема, например, когда у вас есть a: b, в разделе data, а b - это внешняя сущность, такая как значение, массив, объект, простой или глубоко вложенный, как он работает с привязкой к DOM в {{a}} и v-bind в основном.

К моему удивлению, во время этих испытаний я впервые увидел, что {{b}} также был реактивным. Почему нет, потому что b объявлено в разделе data. Все стало странно, когда я попытался {{c}}, где c - это внешняя сущность, которой нет нигде в объекте Vue. DOM реагировал на c тоже!

Более странно, я наблюдал это явление только в части HTML / шаблона: watch реагирует только на a и computed на a и b, но не на c.

Я также заметил, что props, кажется, реагирует на a, b и c.

Все эти тесты объединены в codepen , где я задаю перемещение своих внешних данных на setInterval. Это здесь: https://codepen.io/Djee/pen/qwXjRw

В более широком смысле, я не нашел ни статьи, ни материала, касающегося тех аспектов, которые я впервые упомянул, и, в частности, такого рода автосвязки объектов, непосредственно связанных в руле и живущих, не упомянутых нигде в Vue объект. Я что-то пропустил? Есть ли какой-то материал, исследующий / объясняющий эти аспекты? Спасибо за помощь.

PS: в моем проекте использование this.$watch(cb, {deep: true}); в функции created() более эффективно, чем watch. Еще одна странность для меня, не включенная в этот codepen , на момент написания. Может быть, я добавлю это.

1 Ответ

0 голосов
/ 05 мая 2019

Я думаю, что это ключевая часть вашего вопроса:

как это работает с привязкой к DOM

То, как вы написали свой код, делает этот вопрос простым, но здесь есть несколько этапов, которые не очевидны сразу.

  1. При создании экземпляра Vue содержимое вашего элемента container используется в качестве шаблона. Сами DOM-узлы затем выбрасываются. Это важно понимать, так как он значительно отличается от того, как много других фреймворков работают. Вы ничего не привязываете к этим узлам DOM, они просто шаблон.
  2. Этот шаблон затем компилируется в render функцию. Именно эту render функцию вызовет Vue для визуализации компонента.
  3. Во время рендеринга функция render возвращает виртуальные узлы DOM (VDOM). Некоторые из этих узлов будут соответствовать элементам HTML, а другие будут ссылаться на дочерние компоненты. Дочерний компонент будет отображаться по очереди, и в конце концов, когда все компоненты будут отображены, все сводится к узлам HTML VDOM.
  4. Во время первоначального рендеринга эти узлы 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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...