Для людей, которые знают Respo, это похоже на React. Я реализовал более простую версию алгоритмов виртуального DOM с помощью ClojureScript, и она хорошо работает в моих личных проектах, которые включают меньше побочных эффектов компонентов.



И вспомни, это ново. У меня появилась идея после изучения React. С React мы можем выполнять горячую замену кода в браузерах. Но этого недостаточно, если я хочу перезагрузить чат во время обновления кода на сервере, как React поможет мне в этом. Поэтому я начал свой собственный проект под названием Cumolo. Recollect — это пакет для выполнения shouldComponentUpdate задачи.



Постоянные данные и реактивное программирование

Теперь мы уже знакомы с React и его проблемами. Виртуальный рендеринг требует памяти, дифференциация требует ресурсов ЦП, все это большие полезные нагрузки. Оптимизация, сделанная сообществом React, заключается в повторном использовании компонентов, созданных после последнего рендеринга. Таким образом, создание и сравнение виртуального DOM становится намного более производительным и тривиальным.

Это не новая технология. Это похоже на постоянную структуру данных, которая обычно используется в чисто функциональных языках программирования, чтобы избежать мутаций в структурах данных. Это также не ново в мире JavaScript, поскольку ClojureScript компилируется в JavaScript, поэтому они просто реализовали его с помощью JavaScript, который позже вдохновил immutable.js.

В Clojure это часть данных. В другом сценарии, таком как React, нам нужно не только создавать данные, но и сам виртуальный DOM похож на большой кусок памяти, и нам нужно делиться его частичными структурами. Я имею в виду, что структура DOM отличается. Это не похоже на фрагмент данных, который мы называем операционной функцией, такой как assoc или update , он генерируется каждый раз, когда вносятся изменения в хранилище.

Этот случай представил реактивное программирование в виртуальном рендеринге DOM. Не путайте его с Rx.js, это его специальное использование. Под реактивным подразумеваются виртуальные обновления DOM по мере сохранения изменений, например, выполнение наблюдений, но в реактивном программировании это просто происходит, поскольку разработано на языке, и нет необходимости в ручном наблюдении.

Сочетая их, наш виртуальный DOM здесь является частью реактивной системы, а внутри он является частичным общим и постоянным. Это то, что нам нужно. В случае с Cumulo следует использовать не только виртуальный DOM, который состоит из элементов и его дочерних элементов, но и тривиальные структуры данных, такие как HashMaps, Vectors, Sequences, HashSets.

Повторное использование компонентов при создании виртуального DOM

В React концептуальная формула построения виртуального DOM выглядит так:

f(store, states) = virtual-dom

Хотя у нас есть мемоизация для функционального программирования, она не используется по умолчанию в реальных языковых реализациях. Я не уверен насчет React, но в Respo я использовал решение, похожее на React, для повторного использования структур. Это как:

f(prev-store, prev-states, nil)    = virtual-dom
f(store, states, prev-virtual-dom) = virtual-dom

Я передам старый виртуальный DOM в качестве параметра, поэтому функция рендеринга может выбрать определенные части и использовать их повторно. В частности, создание виртуального DOM не является рекурсивным вызовом функций. Это двухэтапный процесс:

  1. На первом этапе я вызываю create-element и create-component для рендеринга данных, компоненты здесь ненастоящие, они представляют собой HashMaps, содержащие функции рендеринга и параметры, просто не оцененные.
  2. На втором этапе это похоже на force в Clojure, но, поскольку у него есть доступ к prev-virtual-dom, он сравнивает средство визуализации и параметры и решает, использовать последний результат или создать новый.

Делая это, большую часть времени рендеринг выбирает повторное использование, поскольку данные в основном частично обновляются.

При каждом следующем рендеринге он будет рассматривать предыдущий результат и пытаться повторно использовать его как можно больше. Я называю это последовательным рендерингом. Возможно, в истории функционального программирования есть имя получше. Но я просто называю это так. Прокомментируйте эту строку, если у вас есть идеи.

Повторное использование данных при сборке данных

Чтобы повторно использовать данные в Recollect, мне нужен более общий алгоритм. Виртуальные элементы DOM похожи на HashMaps, у которых есть ключи в каждой единице, чтобы средство визуализации могло найти предыдущий результат. С другими структурами данных сложнее.

Я использую HashMap в своем примере для простоты. В приведенном ниже фрагменте я создам тип с именем Twig как компонент, играющий роль кэширования. Помните 2 этапа выше? Я делаю это с HashMaps. Из журналов видно, что мой код частично использует данные повторно:

В рамках Cumulo вы можете думать, что база данных/клиенты/браузеры подобны хранилищу/«виртуальному DOM»/«настоящему DOM». Магазин обновляется при каждом действии.виртуальный DOM частично отображается при каждом изменении хранилища на основе предыдущего виртуального DOM. Со временем виртуал последовательно обновляется.

Вывод

Итак, в этом посте я расскажу о своем опыте последовательного рендеринга в Respo и Recollect. С моей точки зрения, веб-приложения спроектированы как Flux, даже начиная с базы данных. Архитектура while похожа на реактивную и постоянную систему, и мы используем diff/patch для исправления сложных частей, таких как DOM и сеть. Последовательный рендеринг полезен, особенно в функциональном программировании, хотя это скорее псевдоним того, что мы уже использовали.