Начало работы со Snabbdom: рендеринг, обновление, хуки и многое другое

Snabbdom - это очень минимальная, но мощная виртуальная модель DOM. Еще один виртуальный DOM? Разве этого недостаточно с React и всеми остальными?

Хотя подход библиотек, подобных React, заключается в том, чтобы предложить готовый к работе опыт, Snabbdom создан не для этого. Вы увидите это в синтаксисе буквально через секунду.

Snabbdom больше похож на виртуальную модель DOM, предлагающую возможность построения поверх нее. Например, Vue.js был построен на основе Snabbdom. В официальном репозитории GitHub перечислены многие другие библиотеки и фреймворки, использующие Snabbdom под капотом.

Построение поверх Snabbdom возможно благодаря его бесхитростному, простому и расширяемому способу написания кода. Готовы изучить основы этой увлекательной низкоуровневой виртуальной DOM?

Начиная

Поскольку Snabbdom - это библиотека, а не целая экосистема с CLI, например React или Vue, мы создадим обычную настройку JS. Я буду использовать для этого Vite, потому что он очень быстрый и простой в использовании. Раньше ничего устанавливать не нужно.

Вот как начать:

yarn create vite virtual-dom --template vanilla
// or: 
// NPM 6.x: 
npm init vite@latest my-vue-app --template vue
// NPM 7.x: 
npm init vite@latest virtual-dom -- --template vue

Двойное тире в случае NPM не является ошибкой. Созданный каталог будет называться «виртуальный дом». После того, как Vite выполнит настройку, вы можете перейти к нему и установить все, что необходимо: npm install snabbdom.

В index.html у нас есть только минимальная настройка:

С npm run dev или yarn run dev сервер разработки Vite должен быть связан по умолчанию. Итак, не забудьте запустить его.

Теперь давайте напишем минимальный компонент и отрендерим его в DOM.
Сначала я покажу вам код, а потом объясню:

На данный момент мы игнорируем импорт и инициализацию функции patch. Это просто материал по умолчанию.

Первая интересная часть - это контейнерная переменная. Как и почти в каждой библиотеке, использующей виртуальную DOM, нам нужен корневой элемент в DOM. Здесь монтируются наши компоненты. Переменная container и есть этот корень.

Все элементы модели DOM в Snabbdom создаются с помощью функции под названием «h». Возможно, вы знаете эту функцию по Preact. Наш компонент состоит из двух элементов DOM. Для каждого из них мы вызываем функцию «h». Эта функция принимает следующие параметры:

  • Тег HTML или тег в сочетании с селектором CSS (с указанием класса или идентификатора для элемента)
  • Необязательно: объект, содержащий объекты, например события или встроенные стили.
  • Необязательно: массив дополнительных элементов DOM, каждый из которых представляет собой вызов функции «h».

Как видите, у нашего div есть дочерний элемент - абзац.

Чтобы смонтировать каждый компонент в DOM, нам нужно поместить его в функцию patch (все еще в примере кода выше).

Затем вы должны увидеть визуализированный компонент в DOM:

Теперь мы рассмотрели самые основы. Давайте подробнее

Обработка события

Организовать событие, которое нужно уволить, очень просто. Как я сказал ранее, события принадлежат объекту options нашего компонента Snabbdom. В этом объекте мы можем определить новый объект как дочерний для «on» - что означает, что мы хотим прослушивать действие над этим элементом:

Таким образом, всякий раз, когда нажимается эта кнопка, будет выполняться функция «clickHandler».

Иногда мы хотим передать аргументы в нашу функцию-обработчик событий. Тем не менее, click: clickHandler(argument) немедленно выполнит функцию. Вы могли знать эту «проблему» из React.

Что нам нужно сделать, это передать функцию:

Когда вы нажимаете кнопку, передача аргумента и запись в журнал будут работать нормально.

Обновление DOM

Теперь, когда мы только что узнали об обработке событий, мы можем использовать его для обновления нашей DOM. Как вы знаете из Vue, React или Angular, есть что-то, что мы называем состоянием. При изменении этого состояния (например, переменной счетчика) компоненты пользовательского интерфейса, в зависимости от этого, обновляются автоматически. Этого мы тоже хотим достичь.

Обновить некоторые элементы DOM просто - мы используем для этого функцию «patch».
Мы использовали эту функцию раньше. Пора понять, как это работает.

patch принимает два аргумента:

  • Первый - это узел VDOM, представляющий текущий вид.
  • Второй - это узел VDOM, представляющий обновленное представление.

Помните, как мы визуализировали div в DOM через Snabbdom и проверяли, как он выглядит в браузере?

Исходный div-контейнер, жестко закодированный в нашем HTML-файле, исчез:

<div id="container"></div>

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

Итак, если мы хотим обновить элемент DOM, значение которого изменилось, мы заменяем текущий на patch. Чтобы сгенерировать обновленный компонент, мы можем использовать функцию - она ​​возвращает наш узел VDOM. Вот код:

Наша функция «component» генерирует div, оборачивающий кнопку, и p-тег, отображающий переменную «counter». Когда мы нажимаем на кнопку, счетчик увеличивается. Затем новое представление создается и сохраняется в переменной newVnode. Чтобы обновить видимую модель DOM, мы перезаписываем существующий контейнер и исправляем его новым представлением компонентов.

Обновление с использованием значений событий

Теперь, когда мы только что узнали об обработке событий, мы можем использовать его для обновления нашей DOM - используя целевое значение события. Это отлично работает для обновления текста.
Помимо реакции на события щелчка в узле DOM, мы также можем обрабатывать ввод данных пользователем - по крайней мере, в таких элементах, как <input />.

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

Это должно работать нормально, когда вы откроете его в браузере. И если вы откроете инспектор элементов в инструментах разработчика вашего браузера, вы увидите кое-что интересное. Каждый раз, когда вы вводите что-то в поле ввода, не выполняется повторная визуализация всего компонента. Только необходимая часть, в нашем случае абзац, есть.

Удаление нашего элемента из DOM

Так же, как и монтирование, размонтирование работает с использованием функции исправления.
Давайте применим его к нашему существующему компоненту в DOM.

Чтобы увидеть действие по его удалению из DOM, я поместил код для размонтирования в таймаут, который занимает 3 секунды:

Вот и все. Мы исправляем наш существующий компонент в DOM с помощью «!» что дает Snabbdom понять, что мы хотим размонтировать наш элемент.

Крючки

Как и в React, если вы их знаете, хуки подключаются к некоторому компонентному процессу. Примеры: установка, обновление или размонтирование.

В Snabbdom пока доступно десять крючков. Поскольку все они работают почти одинаково, мы сосредоточимся на одном из них: ловушке обновления.

Ловушка обновления запускается всякий раз, когда обновляется наш компонент. Обновления, как мы знаем, совершаются с помощью функции patch. Чтобы реализовать ловушку, мы повторно используем наш пример с полем ввода. Все, что нам нужно добавить, это объект hook в опции нашего компонента:

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

Поскольку мы подключились к процессу обновления, при каждом изменении ввода в текстовое поле будет запускаться console.log.

Спасибо за чтение!