Всё является блоком: модель данных Blok
У Blok одна основная идея. Поймите её — и остальной API сложится сам собой.
В Blok любая часть контента — это блок. Рядом с блоками не существует отдельной модели документа: блок — это универсальный примитив. Абзац — блок. Заголовок — блок. Целая база данных и каждая строка в ней — тоже блоки. Как только это укладывается в голове, API перестаёт выглядеть списком возможностей и начинает читаться как одно цельное дерево.
Форма блока
Каждый блок — какого бы он ни был типа — это один и тот же небольшой объект. type указывает инструмент, который его отображает, data хранит содержимое этого инструмента, а tunes — необязательные настройки уровня блока.
// 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. Блок с потомками по сути является страницей — открыть его значит перейти к его потомкам.
// 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 для точной формы сохранённого блока.