BlockNote Docs参考事件

事件

BlockNote 提供了多个事件回调,允许您响应编辑器中的变化。这些事件对于构建响应式应用和跟踪用户交互至关重要。

概述

编辑器会触发以下事件:

  • 编辑器生命周期 - 编辑器创建、挂载、卸载等时触发
  • 内容变化 - 插入、更新或删除区块时触发
  • 选择变化 - 光标位置或选择范围发生变化时触发
  • 焦点变化 - 焦点进入或离开编辑器时触发

onMount

当编辑器被挂载时,会调用 onMount 回调。

editor.onMount(() => {
  console.log("编辑器已挂载");
});

onUnmount

当编辑器被卸载时,会调用 onUnmount 回调。

editor.onUnmount(() => {
  console.log("编辑器已卸载");
});

onSelectionChange

每当编辑器的选择范围发生变化(包括光标移动和文本选择)时,会调用 onSelectionChange 回调。

editor.onSelectionChange((editor) => {
  console.log("选择范围已改变");

  // 获取当前的选择信息
  const selection = editor.getSelection();
  const textCursorPosition = editor.getTextCursorPosition();

  console.log("当前选择:", selection);
  console.log("文本光标位置:", textCursorPosition);
});

onFocusChange

The onFocusChange callback receives the editor and a context containing focused (a boolean) and event (the triggering DOM FocusEvent). By default, it reports focus entering or leaving the content area.

Pass includeEditorUI: true to count focus within the editor's toolbars, menus, and popovers too. In this mode, the callback runs only when that combined state changes, allowing focus to settle so moving from the content area into a popover input does not report a blur.

const unsubscribe = editor.onFocusChange(
  (editor, { focused }) => {
    console.log("Interacting with editor:", focused);
  },
  { includeEditorUI: true },
);

// When you no longer need the listener:
unsubscribe();

For the current focus state, use editor.isFocused(). In React, use useEditorFocus when focus determines what to render.

onChange

每当编辑器的内容发生变化时,会调用 onChange 回调。这是追踪文档修改的主要方式。

editor.onChange((editor, { getChanges }) => {
  console.log("编辑器内容已改变");

  // 获取详细的变更信息
  const changes = getChanges();
  console.log("变更内容:", changes);

  // 保存内容,更新 UI 等
});

有关 getChanges 函数的更多信息,请参见理解变更。

onBeforeChange

在任何变更应用到编辑器之前,会调用 onBeforeChange 回调,允许您取消此次变更。

editor.onBeforeChange(({ getChanges, tr }) => {
  if (
    // 取消插入新区块
    getChanges().some((change) => change.type === "insert")
  ) {
    // 返回 `false` 将取消此次变更,不会应用到编辑器
    return false;
  }
});

有关 getChanges 函数的更多信息,请参见理解变更。

理解变更

getChanges() 函数返回关于哪些区块受到影响的详细信息。它包括三种变更类型:

  • 插入 - 插入了新的区块
  • 删除 - 删除了区块
  • 更新 - 区块内容发生了变化
  • 移动 - 区块被移动到新的位置(这也可能会更新区块的内容)
/**
 * 编辑器中发生的变更。
 */
type BlocksChanged = Array<
  | {
      type: "insert" | "delete";
      // 受影响的区块(插入时为新插入的区块,删除时为被删除的区块)
      block: Block;
      // 变更来源
      source: BlockChangeSource;
      // 插入和删除变更没有先前区块
      prevBlock: undefined;
    }
  | {
      type: "update";
      // 受影响的区块
      block: Block;
      // 变更来源
      source: BlockChangeSource;
      // 更新前的区块
      prevBlock: Block;
    }
  | {
      type: "move";
      // 变更来源
      source: BlockChangeSource;
      // 受影响的区块
      block: Block;
      // 移动前的区块(因为移动也可能会更新区块内容)
      prevBlock: Block;
      /**
       * 移动前的父区块(如果存在)。
       */
      prevParent?: Block;
      /**
       * 当前位置的父区块(如果存在)。
       */
      currentParent?: Block;
    }
>;

变更来源

每个变更都包含一个来源,用于指示触发此次修改的原因:

type BlockChangeSource = {
  type:
    | "local" // 本地用户触发(默认)
    | "paste" // 来自粘贴操作
    | "drop" // 来自拖放操作
    | "undo" // 来自撤销操作(仅本地)
    | "redo" // 来自重做操作(仅本地)
    | "undo-redo" // 来自撤销/重做操作(协作环境)
    | "yjs-remote"; // 来自远程用户(协作环境)
};

事件清理

所有事件回调都会返回清理函数,调用该函数即可移除事件监听器:

// 设置事件监听器
const cleanupOnChange = editor.onChange((editor, { getChanges }) => {
  console.log("内容已改变");
});

const cleanupOnSelection = editor.onSelectionChange((editor) => {
  console.log("选择范围已改变");
});

// 之后,清理事件监听器
cleanupOnChange();
cleanupOnSelection();