PlateController
是一个可选的 provider 组件,用于从各自的 Plate
组件外部访问特定的 Plate Stores。
PlateController Store
PlateController Store 包含基于 id
获取 Plate Store 以及确定当前活动 id
所需的信息。
使用模式
通过 ID 访问特定编辑器
PlateController
可用于使用其 id
访问特定编辑器的 store。请注意,如果找不到匹配的编辑器,将返回一个不可变的回退编辑器。
const App = withHoc(PlateController, () => {
const mainEditor = useEditorRef('main');
useEffect(() => {
if (!mainEditor.isFallback) {
console.info('Editor mounted', mainEditor);
}
}, [mainEditor]);
return (
<>
<Plate editor={createPlateEditor({ id: 'main' })}>
<PlateContent />
</Plate>
<Plate editor={createPlateEditor({ id: 'secondary' })}>
<PlateContent />
</Plate>
</>
);
});
活动编辑器
如果在 PlateController
内部使用 useEditorRef
等钩子时没有显式指定 id
,它们将解析为当前活动的编辑器。
活动编辑器的确定方式如下:
- 如果某个编辑器已获得焦点,则返回最后一个这样的编辑器。
- 如果某个编辑器是主要编辑器,则返回第一个挂载的这样的编辑器。
- 否则,返回一个不可变的回退编辑器。
const App = withHoc(PlateController, () => {
const activeEditorId = useEditorId();
const isFallback = !useEditorMounted();
const message = isFallback
? '请聚焦一个编辑器'
: `活动编辑器:${activeEditorId}`;
return (
<main>
<p>{message}</p>
<Plate editor={createPlateEditor({ id: 'main', primary: false })}>
<PlateContent />
</Plate>
<Plate editor={createPlateEditor({ id: 'secondary', primary: false })}>
<PlateContent />
</Plate>
</main>
);
});
处理回退编辑器
当在 PlateController
内部调用的钩子无法找到匹配的 Plate Store 时,它将使用 Plate Store 的默认值。editor
的默认值是 createPlateFallbackEditor()
。回退编辑器就像一个没有插件的空 Plate 编辑器,但如果它收到 Slate 操作,则会抛出运行时错误(即它是不可变的,不能用于转换)。
这样做的原因是确保查询编辑器的代码(例如确定工具栏按钮是否处于活动状态)在出现问题时静默失败并返回合理的默认值,而转换编辑器的代码(例如按下工具栏按钮)则大声失败并显示错误。
有两种方法可以确定您是否正在使用回退编辑器或真实编辑器:
useEditorMounted
如果无法解析到已挂载的编辑器,则返回false
editor.meta.isFallback
对于回退编辑器为true
在 PlateController
内部使用 useEditorRef
等钩子时,您应该编写防御性代码,以确保在出现回退编辑器时能够适当处理。例如,如果 useEditorMounted
返回 false
,您可以禁用工具栏按钮,或者如果 editor.meta.isFallback
为 true
,则可以忽略事件。
import { KEYS } from 'platejs';
const App = withHoc(PlateController, () => {
const activeEditor = useEditorRef();
const toggleBold = () => {
if (activeEditor.isFallback) return;
activeEditor.tf.toggleMark(KEYS.bold);
};
return (
<main>
<button type="button" onClick={toggleBold}>
Bold
</button>
<Plate editor={createPlateEditor({ id: 'main', primary: false })}>
<PlateContent />
</Plate>
<Plate editor={createPlateEditor({ id: 'secondary', primary: false })}>
<PlateContent />
</Plate>
</main>
);
});
const App = withHoc(PlateController, () => {
const activeEditor = useEditorRef();
const isFallback = !useEditorMounted();
const toggleBold = () => {
activeEditor.tf.toggleMark(KEYS.bold);
};
return (
<main>
<button
type="button"
onClick={toggleBold}
disabled={isFallback}
>
Bold
</button>
<Plate editor={createPlateEditor({ id: 'main', primary: false })}>
<PlateContent />
</Plate>
<Plate editor={createPlateEditor({ id: 'secondary', primary: false })}>
<PlateContent />
</Plate>
</main>
);
});