Инструкция для Web
DivKit для Web — это npm-пакет @divkitframework/divkit. Он отрисовывает JSON-верстку в DOM-элемент в браузере или в HTML-строку на сервере. Чтобы посмотреть, как выглядит верстка, без интеграции в проект, используйте DivKit Web Playground.
Подключение библиотеки и отрисовка первой карточки
Установка пакета
Установите пакет из npm:
npm i @divkitframework/divkit --save
В пакете несколько модулей, и каждый экспортирует функцию render. Выберите модуль в зависимости от того, где отрисовывается верстка:
| Модуль | Назначение |
|---|---|
@divkitframework/divkit/client |
Отрисовка только в браузере. |
@divkitframework/divkit/client-hydratable |
Отрисовка в браузере с гидратацией HTML, полученного с сервера. Размер модуля немного больше, чем у client. |
@divkitframework/divkit/server |
Отрисовка в HTML-строку на сервере. |
Модули поставляются в форматах ES-модулей и CommonJS: Node.js и сборщики сами выбирают подходящий. Описания типов TypeScript входят в пакет.
Подключение стилей
При любом способе подключения нужен файл стилей dist/client.css. Подключить его можно любым способом. Например, импортируйте файл как модуль, если ваш сборщик обрабатывает CSS:
import '@divkitframework/divkit/dist/client.css';
Или добавьте ссылку на файл в HTML-страницу:
<link rel="stylesheet" href="node_modules/@divkitframework/divkit/dist/client.css">
Отрисовка на клиенте
Добавьте на страницу элемент, в который будет отрисована карточка:
<div id="root"></div>
Вызовите функцию render из модуля client. Передайте в нее идентификатор блока, целевой элемент и JSON с версткой. Для примера выведем на экран небольшой текст:
import { render } from '@divkitframework/divkit/client';
import '@divkitframework/divkit/dist/client.css';
const json = {
card: {
log_id: 'text',
states: [
{
state_id: 0,
div: {
type: 'text',
text: 'Hello, DivKit!'
}
}
]
}
};
const instance = render({
id: 'hello',
target: document.querySelector('#root'),
json,
onError(details) {
console.error(details.error);
}
});
Если все сделано без ошибок, на странице появится надпись «Hello, DivKit!». Функция возвращает экземпляр карточки, с помощью которого ее можно обновить или удалить.
Серверная отрисовка и гидратация
На сервере используйте модуль server. Его функция render не принимает параметр target и возвращает HTML-строку:
import { render } from '@divkitframework/divkit/server';
const html = render({
id: 'hello',
json,
onError(details) {
console.error(details.error);
}
});
Вставьте полученную строку в элемент-контейнер и подключите к странице файл dist/client.css. Чтобы карточка стала интерактивной, в браузере вызовите render из модуля client-hydratable с параметром hydrate: true:
import { render } from '@divkitframework/divkit/client-hydratable';
render({
id: 'hello',
target: document.querySelector('#root'),
hydrate: true,
json,
onError(details) {
console.error(details.error);
}
});
Примечание
Передавайте на сервере и на клиенте одинаковые id и json. По значению id генерируются идентификаторы и классы в разметке.
Готовый пример серверной отрисовки с гидратацией доступен на GitHub.
Подключение без сборки
Библиотеку можно подключить в браузере и без сборщика, но для рабочих проектов рекомендуется сборка.
Импортируйте функцию render из файла dist/esm/client.mjs:
<link rel="stylesheet" href="./node_modules/@divkitframework/divkit/dist/client.css">
<div id="root"></div>
<script type="module">
import { render } from './node_modules/@divkitframework/divkit/dist/esm/client.mjs';
render({
id: 'hello',
target: document.querySelector('#root'),
json: {
card: {
log_id: 'text',
states: [
{
state_id: 0,
div: {
type: 'text',
text: 'Hello, DivKit!'
}
}
]
}
}
});
</script>
Скрипт dist/browser/client.js добавляет функцию render в глобальный объект window.Ya.DivKit:
<link rel="stylesheet" href="./node_modules/@divkitframework/divkit/dist/client.css">
<div id="root"></div>
<script src="./node_modules/@divkitframework/divkit/dist/browser/client.js"></script>
<script>
window.Ya.DivKit.render({
id: 'hello',
target: document.querySelector('#root'),
json: {
card: {
log_id: 'text',
states: [
{
state_id: 0,
div: {
type: 'text',
text: 'Hello, DivKit!'
}
}
]
}
}
});
</script>
Написание Ya.Divkit считается устаревшим — используйте Ya.DivKit.
React
Для React есть отдельный пакет @divkitframework/react. Его компонент DivKit принимает параметры функции render в виде пропсов.
Параметры функции render
Параметры id и json обязательны во всех модулях, параметр target — в модулях client и client-hydratable. Остальные параметры необязательны. В таблице перечислены основные параметры, а полный список с описаниями приведен в README пакета.
| Параметр | Модули | Описание |
|---|---|---|
id |
Все | string. Уникальный идентификатор блока. Используется для генерации идентификаторов и классов, поэтому на странице не должно быть двух блоков с одинаковым id. |
json |
Все | object. JSON с версткой: объект card и необязательный объект templates. |
target |
client, client-hydratable |
HTMLElement. Элемент, в который отрисовывается карточка. |
hydrate |
client-hydratable |
boolean. Укажите true, чтобы гидратировать HTML, который уже находится в target. |
onError |
Все | function. Обработчик ошибок и предупреждений. См. раздел Ошибки. |
onStat |
client, client-hydratable |
function. Обработчик для логирования нажатий и показов. См. раздел Статистика. |
onCustomAction |
client, client-hydratable |
function. Обработчик действий, которые DivKit не выполняет сам. См. раздел Кастомные действия. |
builtinProtocols |
Все | string[]. Значение по умолчанию: ['http', 'https', 'tel', 'mailto', 'intent']. Элементы с действием, протокол которого есть в списке, отрисовываются как ссылки <a>, и нажатия на них обрабатывает браузер. |
platform |
Все | string. Возможные значения: desktop, touch, auto. Значение по умолчанию: auto. Настраивает обработку событий мыши или касаний. |
direction |
Все | string. Возможные значения: ltr, rtl. Значение по умолчанию: ltr. Направление текста и верстки. |
theme |
Все | string. Возможные значения: system, light, dark. Значение по умолчанию: system. См. раздел Тематизация. |
themeVariableName |
Все | string. Имя переменной, в которой хранится текущая тема. См. раздел Тематизация. |
globalVariablesController |
client, client-hydratable |
object. Контроллер внешних переменных. См. раздел Переменные. |
typefaceProvider |
Все | function. Возвращает значение CSS-свойства font-family для шрифта из верстки. См. раздел Шрифты. |
customComponents |
Все | Map. Описания кастомных компонентов. См. раздел Кастомные компоненты. |
extensions |
client, client-hydratable |
Map. Расширения, которые подключаются в верстке по идентификатору. См. раздел Расширения. |
extensionsForAllComponents |
client, client-hydratable |
array. Расширения, которые применяются ко всем элементам. См. раздел Расширения. |
fetchInit |
client, client-hydratable |
object или function. Второй аргумент функции fetch для запросов, которые отправляют действия download и submit. |
tooltipRoot |
client, client-hydratable |
HTMLElement. Элемент, в который добавляются тултипы и меню вместо target. Помогает избежать обрезания. |
store |
Все | object. Внешнее хранилище для хранимых значений. Хранилище реализует методы get и set; метод get должен быть синхронным. |
videoPlayerProvider |
Все | object. Провайдер собственного видеоплеера. На сервере содержит свойство template — строку или функцию, которая возвращает разметку плеера; на клиенте — функцию instance, которая создает экземпляр плеера. |
mix |
Все | string. Дополнительный CSS-класс корневого элемента. |
customization |
Все | object. CSS-классы для кнопок скролла в gallery и pager на десктопе, а также для всплывающего меню и его пунктов. |
Обработка действий, статистики и ошибок
Кастомные действия
Чтобы сделать интерфейс интерактивным, добавьте обработку действий. Действия с протоколом div-action DivKit выполняет сам, а ссылки с протоколами из списка builtinProtocols открывает браузер. Остальные действия передаются в обработчик onCustomAction: это ссылки с другими протоколами и действия с "typed": {"type": "custom"}.
Для примера превратим текст в кнопку, при нажатии на которую появится уведомление. Добавьте элементу действие:
"actions": [
{
"log_id": "button_pressed",
"url": "notification://show-toast?text=Hello%2C%20DivKit%21"
}
]
Обработайте это действие в onCustomAction:
render({
id: 'hello',
target: document.querySelector('#root'),
json,
onCustomAction(action) {
const [address, query = ''] = (action.url || '').split('?');
if (address === 'notification://show-toast') {
alert(new URLSearchParams(query).get('text'));
}
}
});
Так можно повлиять из JSON-верстки не только на состояние самой карточки, но и на все приложение. Данные действия с "typed": {"type": "custom"} передаются в поле action.payload. Подробнее — в разделе Кастомные действия.
Статистика
Обработчик onStat предназначен для логирования нажатий и показов. В поле details.action передается действие, а поле details.type принимает одно из значений:
click— нажатие на элемент с действием, а также любое действие, у которого нет собственного типа;visible— показ элемента, для которого заданыvisibility_actions;disappear— исчезновение элемента, для которого заданыdisappear_actions;trigger— срабатывание триггера.
render({
id: 'hello',
target: document.querySelector('#root'),
json,
onStat(details) {
console.log(details.type, details.action.log_id);
}
});
Ошибки
В обработчик onError передаются ошибки и предупреждения, которые возникают при разборе и отрисовке верстки. У объекта details.error есть поле level со значением error или warn и необязательное поле additional с дополнительными данными. Если обработчик не задан, DivKit выводит сообщения в консоль.
render({
id: 'hello',
target: document.querySelector('#root'),
json,
onError(details) {
const { level, message, additional } = details.error;
console.log(level, message, additional);
}
});
Тематизация
Параметр theme задает тему карточки: light, dark или system. Со значением system, которое используется по умолчанию, тема определяется по настройкам системы пользователя (медиавыражение prefers-color-scheme) и меняется вместе с ними. На сервере настройки системы недоступны, поэтому со значением system верстка отрисовывается в светлой теме.
Чтобы использовать текущую тему в верстке, укажите в параметре themeVariableName имя переменной. DivKit создаст строковую переменную с этим именем и будет записывать в нее значение light или dark. Используйте переменную в выражениях: при смене темы зависящие от нее свойства обновятся без перезагрузки страницы.
Примечание
Если параметр themeVariableName не передан, переменная не создается. Имя переменной не должно совпадать с именами переменных карточки и внешних переменных, иначе DivKit сообщит об ошибке Duplicate variable.
render({
id: 'themed',
target: document.querySelector('#root'),
json,
theme: 'system',
themeVariableName: 'theme'
});
Посмотреть пример верстки
{
"card": {
"log_id": "themed_card",
"states": [
{
"state_id": 0,
"div": {
"type": "text",
"text": "Hello, DivKit!",
"text_color": "@{theme == 'dark' ? '#ffffff' : '#000000'}",
"background": [
{
"type": "solid",
"color": "@{theme == 'dark' ? '#000000' : '#ffffff'}"
}
]
}
}
]
}
}
Тему уже отрисованной карточки меняет метод экземпляра setTheme, например instance.setTheme('dark'). В описаниях типов пакета этот метод помечен как устаревший.
Переменные
Модули client и client-hydratable экспортируют функции для работы с внешними переменными. Функция createVariable создает переменную, а createGlobalVariablesController — контроллер, через который переменные становятся доступны в карточке. Чтобы несколько карточек использовали общие переменные, передайте один и тот же контроллер в каждый вызов render.
import {
render,
createVariable,
createGlobalVariablesController
} from '@divkitframework/divkit/client';
const userName = createVariable('user_name', 'string', 'Guest');
const controller = createGlobalVariablesController();
controller.setVariable(userName);
render({
id: 'hello',
target: document.querySelector('#root'),
json,
globalVariablesController: controller
});
const unsubscribe = userName.subscribe(value => {
console.log(value);
});
userName.setValue('Alice');
В верстке переменная доступна по имени, например @{user_name}. Методы переменной:
subscribe— вызывает обработчик с текущим значением и затем при каждом его изменении. Возвращает функцию для отписки.setValue— записывает новое значение.getValue— возвращает текущее значение.
Имена переменных в одном контроллере должны быть уникальными: при добавлении второй переменной с тем же именем метод setVariable выбрасывает исключение.
Расширение возможностей
Кастомные компоненты
Элемент custom отрисовывается с помощью пользовательских элементов HTML (Custom Elements). Передайте в параметре customComponents объект Map, в котором ключ — значение custom_type из верстки, а значение — описание компонента с именем тега в поле element:
import { render } from '@divkitframework/divkit/client';
class CustomCard extends HTMLElement {
connectedCallback() {
this.textContent = `Start: ${this.getAttribute('start')}`;
}
}
customElements.define('custom-card', CustomCard);
render({
id: 'custom',
target: document.querySelector('#root'),
json: {
card: {
log_id: 'custom_card',
states: [
{
state_id: 0,
div: {
type: 'custom',
custom_type: 'custom_card',
custom_props: {
start: 15
}
}
}
]
}
},
customComponents: new Map([
['custom_card', { element: 'custom-card' }]
])
});
Свойства из custom_props передаются компоненту в виде HTML-атрибутов. Кастомные компоненты поддерживаются и при серверной отрисовке: разметку компонента для сервера можно передать в поле template описания.
Примеры на GitHub:
Расширения
По умолчанию ни одно расширение не подключено. Чтобы включить расширение, передайте в параметре extensions объект Map: ключ — идентификатор расширения из поля extensions элемента, значение — класс расширения. Модули client и client-hydratable экспортируют готовые расширения SizeProvider и Gesture, а также функции lottieExtensionBuilder и markdownExtensionBuilder, которые создают расширения для Lottie и Markdown.
import { render, SizeProvider } from '@divkitframework/divkit/client';
render({
id: 'hello',
target: document.querySelector('#root'),
json,
extensions: new Map([
['size_provider', SizeProvider]
])
});
Расширения работают только на клиенте. Если страница отрисована на сервере, а расширение меняет внешний вид элемента, пользователь может заметить это изменение при загрузке страницы.
Подробнее о расширениях и параметре extensionsForAllComponents — в разделе Подключение.
Шрифты
Шрифты подключаются на странице средствами CSS. Чтобы сопоставить имя шрифта из параметра font_family с CSS-шрифтом, передайте функцию typefaceProvider. Она получает имя шрифта и необязательный объект с насыщенностью fontWeight и возвращает значение CSS-свойства font-family:
render({
id: 'hello',
target: document.querySelector('#root'),
json,
typefaceProvider(fontFamily, opts) {
if (fontFamily === 'display') {
return '"My Display Font", sans-serif';
}
return '';
}
});
Подробнее — в разделе Шрифты.
Обновление и удаление карточки
Функция render из модулей client и client-hydratable возвращает экземпляр карточки. Его методы:
| Метод | Описание |
|---|---|
execAction(action) |
Выполняет действие в карточке. |
applyPatch(patch) |
Применяет патч. Возвращает true, если патч применен. |
setData(json) |
Перерисовывает карточку по новому JSON. Метод экспериментальный: его логика и API могут измениться. |
$destroy() |
Уничтожает экземпляр и удаляет карточку со страницы. |
instance.execAction({
log_id: 'reset_counter',
url: 'div-action://set_variable?name=counter&value=0'
});
instance.$destroy();
Метод setData старается сохранить состояние карточки, например значения в полях ввода. Он не меняет существующие переменные и триггеры, а только создает новые переменные.
Требования к окружению
Поддерживаемые браузеры:
chrome >= 67
safari >= 14
firefox >= 68
Для отдельных возможностей нужны более новые браузеры. Например, параметр aspect элемента container требует поддержки CSS-свойства aspect-ratio.
Для серверной отрисовки:
Node.js >= 14
Целые числа DivKit хранит в типе BigInt, если платформа его поддерживает. Учитывайте, что JSON.parse и метод json() ответа fetch возвращают большие целые числа как number, поэтому значения больше 2^53 могут потерять точность еще до передачи в DivKit.
Примеры проектов
Готовые к запуску примеры доступны на GitHub:
- js и ts — подключение со сборкой;
- globals и globals-esm — подключение без сборки;
- ssr и node-esm — серверная отрисовка;
- divkit-react — React с серверной отрисовкой.
Узнать больше
Вы можете обсуждать интересующие вас темы в сообществе пользователей DivKit в Telegram: https://t.me/divkit_community_ru.