---
title: "Класс Blok — new Blok(), isReady, destroy"
description: "Создание, ожидание готовности и уничтожение экземпляра редактора, а также что безопасно вызывать до isReady."
source: https://blokeditor.com/ru/docs/core/
lastmod: 2026-09-07
---

Фреймворк JavaScript

Основное Класс Blok

На этой странице save()

# Класс Blok: создание и уничтожение редактора

Основной класс редактора, который инициализирует экземпляр редактора Blok и управляет им. Любое пространство имён, доступное инструменту через `api.*`, доступно и на самом экземпляре как `editor.*` — свойства ниже описывают ту же поверхность плюс пространства имён `width`, `placeholder`, `tokens` и `i18n`, которые класс объявляет сам.

Обновлено 30 июн. 2026 г. [Редактировать на GitHub](https://github.com/JackUait/blok/blob/main/docs/src/components/api/api-data.ts)

### Как получить экземпляр редактора

Методы ниже вызываются на редакторе, созданном через new Blok(). Они доступны после того, как разрешится editor.isReady.

TypeScript

```
// You already hold the instance returned by the constructor.
const editor = new Blok({ holder: 'editor' });
await editor.isReady;

// Call any API method on it.
editor.caret.setToLastBlock('end');
```

## Методы

### save()

Promise<OutputData>

Извлекает содержимое редактора в виде JSON-данных. Основной метод для сохранения контента.

Когда использовать

Вызывайте после `await editor.isReady`. Возвращённый JSON — ваш источник истины: сохраните его и передайте обратно в `render()`.

Ошибки

- Редактор находится в режиме только для чтения в момент вызова save(). Blok's content can not be saved in read-only mode Вызвать `readOnly.set(false)` перед сохранением либо сохранить данные из последнего вызова `onSave` / собственного зеркального состояния.

TypeScript

```
// Save editor content
const data = await editor.save();
console.log(data.blocks); // Array of block data
```

### render(data)

Promise<void>

Отображает содержимое редактора из ранее сохранённых JSON-данных. Принимает нестрогий формат (`LooseOutputData`) — значения `null` для `data`, `id` или `time` блока из backend-DTO нормализуются на границе.

Когда использовать

Загружает сохранённый контент и заменяет текущий документ. Чтобы добавить, а не заменить, используйте `blocks.insertMany()`.

TypeScript

```
// Load saved content
const savedData = {
  blocks: [
    { id: '1', type: 'paragraph', data: { text: 'Hello' } }
  ]
};
await editor.render(savedData);
```

### focus(atEnd?)

boolean

Устанавливает фокус на редактор. Опционально позиционирует курсор в конце содержимого.

Когда использовать

Передайте `true`, чтобы поставить курсор в самый конец. Для конкретного блока или смещения используйте API `caret`.

TypeScript

```
// Focus at start
editor.focus();

// Focus at end
editor.focus(true);
```

### clear()

Promise<void>

Удаляет всё содержимое редактора. Остаётся один пустой блок инструмента по умолчанию, поэтому редактор никогда не остаётся без блоков — при этом последующий save() всё равно вернёт `blocks: []`, так как пустой блок по умолчанию не проходит валидацию и отбрасывается из результата.

Когда использовать

Удаляет все блоки и оставляет один пустой параграф. Действие отменяемо — в отличие от `destroy()`, уничтожающего экземпляр.

TypeScript

```
// Clear all content
await editor.clear();
```

### destroy()

void

Уничтожает экземпляр редактора и удаляет все DOM-элементы и обработчики событий.

Когда использовать

Вызывайте из хука размонтирования вашего фреймворка, чтобы не утекли слушатели. После этого экземпляр непригоден — создайте новый `Blok`.

TypeScript

```
// Clean up on component unmount
editor.destroy();
```

### handlers.set(handlers)

void

Устанавливает, заменяет или удаляет живые колбэки редактора — `onChange`, `onSave`, `onEnter`, `onSubmit`, `onBeforeRender`, `onAfterRender` — на месте, поэтому курсор, выделение, прокрутка и история отмен сохраняются. Затрагиваются только переданные ключи; ключ со значением `undefined` СНИМАЕТ обработчик. Это важно, потому что само наличие колбэка и есть семантика: `onSubmit` превращает Enter в «сериализовать и отправить» вместо разбиения блока, а `onSave` включает конвейер отслеживания изменений. Используйте метод, чтобы сделать колбэк реактивным без пересоздания редактора — адаптеры React, Vue и Angular вызывают этот сеттер за вас, когда prop, слушатель или колбэк из `[config]` появляется или исчезает.

Когда использовать

Затрагиваются только переданные ключи — ключ со значением `undefined` снимает обработчик, именно так режим «Enter отправляет» выключается обратно.

Параметры

| Параметр | Тип | Обязательный | По умолчанию | Описание |
| --- | --- | --- | --- | --- |
| `handlers` | `LiveHandlers` | Обязательный | — | Частичная карта живых колбэков. Пропущенные ключи остаются как есть; ключ со значением `undefined` снимает обработчик. |

TypeScript

```
// "Enter sends" while composing, default Enter while editing a draft
editor.handlers.set({
  onSubmit: sendsOnEnter ? (data) => send(data) : undefined,
});

// Start mirroring content into your store, later stop again
editor.handlers.set({ onSave: (data) => store.set(data) });
editor.handlers.set({ onSave: undefined });
```

### whenAllReady(options?)

Promise<void>

Статический метод — резолвится, когда каждый экземпляр Blok в заданной области завершил загрузку (его `isReady` завершился; отклонения тоже считаются завершением). Коллективный сигнал готовности для страниц с несколькими экземплярами — заменяет ручную агрегацию колбэков `onReady` по каждому экземпляру. Передайте `within` (Element), чтобы учитывать только экземпляры внутри вашего поддерева: посторонний редактор на странице больше не сможет держать проверку закрытой. Передайте `settleOn: 'rendered'`, чтобы готовность означала не завершение конструктора, а наличие контента в DOM — это покрывает и повторные рендеры через `render(data)`. Пустая область резолвится сразу. Экземпляры, созданные пока промис в ожидании, продлевают ожидание; созданные после его резолва не учитываются — вызовите метод снова или используйте `subscribeReady()` для живого сигнала.

Когда использовать

Вызывайте как `Blok.whenAllReady()` на классе, а не на экземпляре. Экземпляр, который ещё загружается и чья обёртка не добавлена в документ, учитывается в любой области — лишнее ожидание безопасно, недостаточное является ошибкой.

TypeScript

```
// A comments list: N read-only bodies + a composer.
// Wait only for the editors inside this list.
await Blok.whenAllReady({
  within: listElement,
  settleOn: 'rendered',
});
composer.focus();
```

### readyState(options?)

{ total: number; pending: number; ready: boolean }

Статический метод — синхронный снимок готовности для области: сколько экземпляров попадает в `within`, сколько из них ещё не готовы на запрошенном уровне `settleOn` и готова ли область целиком. Пустая область возвращает `ready: true`, поэтому отдельная проверка «ждать нечего» не нужна.

Когда использовать

Достаточно дёшев, чтобы вызывать его на каждое уведомление из `subscribeReady()`: метод обходит зарегистрированные экземпляры и проверяет вложенность в DOM.

TypeScript

```
const { pending, ready } = Blok.readyState({ within: listElement });

if (!ready) {
  showSkeleton(pending);
}
```

### subscribeReady(listener)

() => void

Статический метод — подписка на изменения готовности всех экземпляров (создание, загрузка, смена состояния рендера, уничтожение); возвращает функцию отписки. Слушатель вызывается без аргументов: перечитайте `Blok.readyState(scope)`, когда он сработает. Подходит для `useSyncExternalStore` и других адаптеров хранилищ — живой сигнал вместо одноразовой защёлки.

Когда использовать

В фреймворках лучше использовать обёртки адаптеров: `useBlokReady()` в @bloklabs/react и @bloklabs/vue, `injectBlokReady()` в @bloklabs/angular — они оборачивают эту подписку и поиск области видимости.

TypeScript

```
const unsubscribe = Blok.subscribeReady(() => {
  setReady(Blok.readyState({ within: listElement }).ready);
});

// later
unsubscribe();
```

### createSelector(attr, value?)

string

Именованный экспорт корня пакета (не член класса Blok) — строит CSS-селектор по значению `DATA_ATTR`. Без `value` получается селектор по наличию атрибута, с ним — селектор по равенству значения. Используйте его вместе с `Blok.DATA_ATTR` вместо совпадения по внутренним именам классов Blok, которые не входят в публичную поверхность.

TypeScript

```
import { DATA_ATTR, createSelector } from '@bloklabs/core';

createSelector(DATA_ATTR.element); // '[data-blok-element]'
document.querySelectorAll(createSelector(DATA_ATTR.selected, true));
```

### icons

string

Именованные экспорты подпути `@bloklabs/core/icons` (не члены класса Blok) — собственные глифы Blok в виде SVG-строк, по одной константе `Icon*` на глиф (`IconBold`, `IconPlus`, `IconTrash`, `IconWarning`, …). Поскольку это обычные строки, они подставляются прямо туда, где инструмент обязан отдать разметку: в иконку `static get toolbox()` инструмента и в элементы, которые возвращает `renderSettings()`. Подпуть поставляется со сгенерированным самодостаточным файлом деклараций (`types/icons.d.ts`), где перечислены все константы, поэтому справочник по полному набору — автодополнение в редакторе кода.

TypeScript

```
import { IconBold, IconPlus } from '@bloklabs/core/icons';

class Callout {
  static get toolbox() {
    return { title: 'Callout', icon: IconPlus };
  }

  renderSettings() {
    return [{ icon: IconBold, title: 'Bold text', onActivate: () => this.toggleBold() }];
  }
}
```

## Свойства

| Свойство | Тип | Описание |
| --- | --- | --- |
| `DATA_ATTR` | `Record<DataAttrKey, DataAttrValue>` | Именованный экспорт корня пакета (`import { DATA_ATTR } from '@bloklabs/core'`), а не свойство экземпляра редактора — стабильные имена атрибутов `data-blok-*`, которые Blok пишет в своём DOM. Это поддерживаемый способ запрашивать DOM редактора и писать тесты на стороне хоста вместо совпадения по внутренним именам классов. Рядом с ним экспортируются типы `DataAttrKey` / `DataAttrValue` и хелпер `createSelector()`. |
| `BLOK_FONT_SIZE_TOKENS` | `BlokFontSizeTokens` | Именованный экспорт корня пакета (`import { BLOK_FONT_SIZE_TOKENS } from '@bloklabs/core'`), а не свойство экземпляра редактора — CSS-переменная, которую пишет каждый сценарий `style.fontSize`, в карте ровно той же формы, что и сама конфигурация (`BLOK_FONT_SIZE_TOKENS.paragraph`, `.heading[1]`, `.list.checklist`, `.bookmark.link`, …). Используйте её везде, где типографика задаётся не конфигурацией конструктора, а другим каналом — CSS-правилом для отдельной области или `editor.tokens.set({ [BLOK_FONT_SIZE_TOKENS.paragraph]: '18px' })` в рантайме, — чтобы имена CSS-переменных не приходилось копировать руками, а переименование становилось ошибкой компиляции, а не молча проходило впустую. |
| `version` | `string` | Именованный экспорт корня пакета (`import { version } from '@bloklabs/core'`), а не свойство экземпляра редактора — версия работающего редактора, то же значение, что попадает в `OutputData.version`. |
| `PendingBlok` | `{ isReady; isRendered; destroy(); theme; width; placeholder; tokens; i18n }` | Тип, экспортируемый из корня пакета (`import type { PendingBlok } from '@bloklabs/core'`), а не свойство экземпляра редактора — поверхность, которая гарантированно существует синхронно между `new Blok(config)` и разрешением `isReady`. Модульные API Blok (`blocks`, `caret`, `history`, `readOnly`, …) создаются асинхронно, поэтому чтение их раньше вернёт `undefined`. `PendingBlok` объявляет только восемь перечисленных здесь членов, что превращает это окно в ошибку компиляции вместо `undefined` в рантайме: `const pending: PendingBlok = new Blok(config); const editor = await pending.isReady;`. |
| `isReady` | `Promise<Blok>` | Promise, который разрешается готовым экземпляром редактора. Пространства имён API ниже (`blocks`, `caret`, `history`, `readOnly`, …) создаются асинхронно и равны `undefined`, пока он не разрешится — типизируйте ссылку, которой владеете в этот момент, как `PendingBlok`. |
| `isRendered` | `boolean` | Синхронный флаг готовности рендера — true, когда текущая партия рендера попала в DOM (отражает атрибут `data-blok-rendered` на обёртке); false до первого рендера и во время повторного. Дополняет асинхронные `isReady`/`onReady`: не нужны await или колбэк, состояние монтирования можно опрашивать синхронно. |
| `blocks` | `Blocks` | Модуль API для работы с блоками |
| `caret` | `Caret` | Модуль API для управления курсором |
| `history` | `History` | Модуль API истории |
| `saver` | `Saver` | Модуль API сохранения |
| `toolbar` | `Toolbar` | Модуль API панели инструментов |
| `inlineToolbar` | `InlineToolbar` | Модуль API строчной панели |
| `tools` | `Tools` | Модуль API инструментов |
| `uploader` | `Uploader` | Модуль API загрузчика — загрузка ассетов с маршрутизацией по виду ассета |
| `events` | `Events` | Модуль API событий |
| `listeners` | `Listeners` | Модуль API слушателей |
| `notifier` | `Notifier` | Модуль API уведомлений |
| `sanitizer` | `Sanitizer` | Модуль API очистки |
| `selection` | `Selection` | Модуль API выделения |
| `marks` | `Marks` | Модуль API меток — range-aware операции со строчными метками |
| `styles` | `Styles` | Модуль API стилей |
| `tooltip` | `Tooltip` | Модуль API подсказок |
| `readOnly` | `ReadOnly` | Модуль API режима только для чтения |
| `ui` | `Ui` | Модуль API интерфейса |
| `theme` | `Theme` | Модуль API темы |
| `width` | `Width` | Модуль API ширины |
| `placeholder` | `Placeholder` | Модуль API плейсхолдера |
| `tokens` | `Tokens` | Модуль API токенов темы в рантайме |
| `i18n` | `EditorI18n` | Модуль API i18n — всё, что инструмент получает через `api.i18n`, расширенное методом `update()` |
| `config` | `Readonly<Pick<BlokConfig, 'linkPaste' | 'link'>>` | Доступное только для чтения представление отдельных настроек редактора: опции `link` и `linkPaste`, с которыми был создан этот экземпляр. Собственный строчный инструмент или инструмент ссылок читает политику ссылок хоста отсюда (как `api.config`), а не выводит её заново. |
| `rectangleSelection` | `{ cancelActiveSelection(): void; isRectActivated(): boolean; clearSelection(): void; startSelection(pageX: number, pageY: number, shiftKey?: boolean): void; endSelection(): void }` | Управление выделением перетаскиванием (рамкой); доступно также внутри инструмента как `api.rectangleSelection`. `startSelection(pageX, pageY, shiftKey?)` начинает рамку от координат страницы; `endSelection()` сбрасывает состояние перетаскивания и прячет оверлей; `isRectActivated()` сообщает, активна ли рамка сейчас; `clearSelection()` снимает флаг активности; `cancelActiveSelection()` прерывает начатое выделение (clear + end) — это то, что вызывает другая система выделения, например выделение ячеек таблицы, когда она забирает приоритет. |
