Перейти к содержимому
ФреймворкJavaScript

Всё является блоком: модель данных Blok

У Blok одна основная идея. Поймите её, и остальной API сложится сам собой.

Обновлено 5 окт. 2026 г.Редактировать на GitHub

В Blok каждая часть контента является блоком. Отдельной модели документа рядом с блоками нет.

Блок является универсальным примитивом.

  • Абзац является блоком.
  • Заголовок является блоком.
  • Целая база данных является блоком, как и каждая строка в ней.

Как только это укладывается в голове, API перестаёт выглядеть списком возможностей и начинает читаться как одно цельное дерево.

Форма блока

Каждый блок любого типа является одним и тем же небольшим объектом. type указывает инструмент, который его отображает. data хранит содержимое этого инструмента. tunes хранит необязательные настройки уровня блока.

TypeScript
// Every block — whatever its type — is the same small object
{
  id: 'block-a1b2c3',              // unique, auto-generated
  type: 'paragraph',              // which tool renders it
  data: { text: 'Hello, world' }, // the tool's content
  tunes: {},                      // block-level settings (optional)
}

Блоки образуют дерево

Блоки не плоский список. Любой блок может содержать другие блоки через contentIds, а каждый потомок ссылается обратно через parentId. Блок с потомками по сути является страницей. Открыть его значит перейти к его потомкам.

TypeScript
// A database block holds its rows as children.
// In saved JSON the hierarchy fields are named `content` and `parent`;
// on live Block objects (and the React BlockNode) the same links are
// exposed as `contentIds` and `parentId`.
{
  id: 'db-1',
  type: 'database',
  data: { schema: [/* columns */], views: [/* configs */] },
  content: ['row-1', 'row-2'], // its children
}

// A row is a block that points back to its parent
{
  id: 'row-1',
  type: 'database-row',
  parent: 'db-1',
  data: { properties: { status: 'Done', priority: 'High' } },
}

Та же идея на всех уровнях

То, что выглядит как отдельные системы, на самом деле блоки, расставленные в дереве:

Это……является блоком, потому что
АбзацВ его data хранится текст и строчное форматирование.
База данныхВ её data хранятся схема и конфигурации представлений, а не отдельная таблица.
Строка базы данныхЭто потомок блока базы данных. Её значения лежат в data.properties.
СтраницаЛюбой блок с потомками. Открытие переходит к его contentIds.

Что не является блоком

Структурированные значения свойств не являются блоками. Статус, приоритет или срок у строки хранятся как метаданные в data блока-владельца. Правило простое: если у сущности есть идентичность, она хранит содержимое и её можно вкладывать, то это блок. Если это типизированное значение, принадлежащее блоку, то оно живёт в data этого блока.

Почему это важно для вас

Поскольку всё является блоком, вы осваиваете один набор приёмов, и он работает везде:

Один API для всего

insert, move и delete работают с любым блоком одними и теми же вызовами: с абзацем, со строкой или с целой базой данных.

Один формат сохранения

editor.save() обходит одно и то же дерево для любого контента, поэтому сохранение и отрисовка не требуют особых случаев.

Одна модель вложенности

parentId и contentIds описывают вложенность везде, поэтому строка внутри базы данных и абзац внутри сворачиваемого списка ведут себя одинаково.

Расширяете Blok? Задайте один вопрос

Прежде чем проектировать новую возможность, спросите: «Это блок?» Если она представляет контент, данные или контейнер, ответ почти всегда да. Реализуйте её как блок, а не придумывайте параллельную модель данных.

  • Представление-календарь → конфигурация представления на блоке базы данных. Строки остаются блоками-строками.
  • Тред комментариев → блок.
  • Оглавление → блок, который читает соседние блоки.
  • Встраивание → блок.

Готовы работать с деревом напрямую? Смотрите Blocks API для вставки и перемещения блоков и BlockData для точной формы сохранённого блока.