大家好,很高兴又见面了,我是"高级前端?进阶?",由我带着大家一起关注前端前沿、深入前端底层技术,大家一起进步,也欢迎大家关注、点赞、收藏、转发!
今天给大家介绍的主题是 facebook 开源的富文本编辑器 Lexical。话不多说,直接进入正题!
1.什么是 Lexical
Lexical 是一个可扩展的 JavaScript Web 文本编辑器框架,强调可靠性、可访问性和性能。 Lexical 旨在提供一流的开发人员体验,以便开发者可以轻松进行原型设计并快速构建功能。 结合高度可扩展的架构,Lexical 允许开发人员创建可扩展大小和功能的独特文本编辑体验。
Lexical 的原理是将自身附加到 contentEditable 元素,开发者可以使用 Lexical 的声明性 API 而无需担心 DOM 周围的特定边缘情况。 事实上,在大多数情况下,开发者很少需要与 DOM 交互(除非构建自己的自定义节点)。
Lexical 的核心包文件大小仅为 22kb (min+gzip),非常轻量。 此外,在支持延迟加载的框架中,开发者还可以推迟 Lexical 插件,直到用户实际与编辑器本身交互。Lexical 的典型特征包括以下几点:
- 可靠:Lexical 由编辑器实例组成,每个实例附加到单个内容可编辑元素。 一组编辑器状态表示编辑器在任何给定时间的当前状态和待处理状态
- 无障碍:Lexical 是为每个人设计的,遵循 WCAG 中建立的最佳实践,并与屏幕阅读器和其他辅助技术兼容
- 快速:不直接涉及 UI 组件、工具栏或富文本功能和 Markdown,这些功能的逻辑可以通过插件接口包含在内
- 跨平台:Lexical 可作为在 Web 浏览器中使用的 JavaScript 框架,以及用于本机 iOS 开发的 Swift 框架
Lexical 的使用场景也非常广泛:
- 简单的纯文本编辑器,比 <textarea> 更强大,例如:需要 mention、自定义表情符号、链接和主题标签等功能
- 更复杂的富文本编辑器,可用于在博客、社交媒体、消息应用程序上发布内容
- 成熟的所见即所得编辑器,可在 CMS 或富内容编辑器中使用
- 结合了上述许多要点的实时协作文本编辑体验
开发者甚至可以将 Lexical 视为文本编辑器 UI 框架。虽然 Lexical 目前只能在 Web 上使用,但该团队还在尝试为其他平台构建 Lexical 的本机版本。 在 Meta,Lexical 每天为 Facebook、Workplace、Messenger、WhatsApp 和 Instagram 上的数亿用户提供网络文本编辑体验。
目前 Lexical 在 Github 通过 MIT 协议开源,有超过 16.6k 的 star、1.4k 的 fork、8k 的项目依赖量、代码贡献者 400+、妥妥的前端优质开源项目。
2.快速使用 Lexical
Vanilla JS 使用 Lexical
当使用 Lexical 时,通常使用单个编辑器实例,而编辑器实例可以被认为是负责将 EditorState 与 DOM 连接起来的实例,同时编辑器也可以注册自定义节点、添加侦听器和转换。
可以从词法包创建编辑器实例,并接受允许主题和其他选项的可选配置对象:
import {createEditor} from 'lexical';
const config = {
namespace: 'MyEditor',
theme: {
...
},
onError: console.error
};
const editor = createEditor(config);
拥有编辑器实例后,就可以将编辑器实例与文档中的内容可编辑 <div> 元素相关联:
const contentEditableElement = document.getElementById('editor');
editor.setRootElement(contentEditableElement);
如果要从元素中清除编辑器实例,可以传递 null。或者,如果需要,还可以切换到另一个元素,只需将替代元素引用传递给 setRootElement() 即可。
Lexical 维护并与编辑器实例关联的底层状态模型,开发者可以通过调用 editor.getEditorState() 从编辑器获取最新的编辑器状态。
const stringifiedEditorState = JSON.stringify(editor.getEditorState().toJSON());
const newEditorState = editor.parseEditorState(stringifiedEditorState);
React 中使用 Lexical
首先需要安装相应的依赖:
npm install --save lexical @lexical/react
下面是使用 lexical 和 @lexical/react 的基本纯文本编辑器的示例:
import {$getRoot, $getSelection} from 'lexical';
import {useEffect} from 'react';
import {LexicalComposer} from '@lexical/react/LexicalComposer';
import {PlainTextPlugin} from '@lexical/react/LexicalPlainTextPlugin';
import {ContentEditable} from '@lexical/react/LexicalContentEditable';
import {HistoryPlugin} from '@lexical/react/LexicalHistoryPlugin';
import {OnChangePlugin} from '@lexical/react/LexicalOnChangePlugin';
import {useLexicalComposerContext} from '@lexical/react/LexicalComposerContext';
import LexicalErrorBoundary from '@lexical/react/LexicalErrorBoundary';
const theme = {
}
function MyCustomAutoFocusPlugin() {
const [editor] = useLexicalComposerContext();
useEffect(() => {
editor.focus();
}, [editor]);
return null;
}
function onError(error) {
console.error(error);
}
function Editor() {
const initialConfig = {
namespace: 'MyEditor',
theme,
onError,
};
return (
<LexicalComposer initialConfig={initialConfig}>
<PlainTextPlugin
contentEditable={<ContentEditable />}
placeholder={<div>Enter some text...</div>}
ErrorBoundary={LexicalErrorBoundary}
/>
<HistoryPlugin />
<MyCustomAutoFocusPlugin />
</LexicalComposer>
);
}
现在在 React 中有了一个简单的编辑器,接下来要做的就是访问编辑器的内容,例如:将其保存在数据库中。 可以通过更新侦听器来完成此操作,该侦听器将在每次编辑器状态更改时执行并提供最新状态。 在 React 中,通常使用插件系统来设置这样的侦听器,因为它使开发者可以通过 React 上下文轻松访问 LexicalEditor 实例。
function MyOnChangePlugin({onChange}) {
const [editor] = useLexicalComposerContext();
useEffect(() => {
return editor.registerUpdateListener(({editorState}) => {
onChange(editorState);
});
}, [editor, onChange]);
return null;
}
现在可以在编辑器中实现,并将 EditorState 保存在 React 状态变量中:
function MyOnChangePlugin({ onChange }) {
const [editor] = useLexicalComposerContext();
useEffect(() => {
return editor.registerUpdateListener(({editorState}) => {
onChange(editorState);
});
}, [editor, onChange]);
return null;
}
function Editor() {
const [editorState, setEditorState] = useState();
function onChange(editorState) {
setEditorState(editorState);
}
return (
<LexicalComposer initialConfig={initialConfig}>
<PlainTextPlugin
contentEditable={<ContentEditable />}
placeholder={<div>Enter some text...</div>}
ErrorBoundary={LexicalErrorBoundary}
/>
<HistoryPlugin />
<MyCustomAutoFocusPlugin />
<MyOnChangePlugin onChange={onChange}/>
</LexicalComposer>
);
}
3.本文总结
本文主要和大家介绍 Lexical,其是一个可扩展的 JavaScript Web 文本编辑器框架,强调可靠性、可访问性和性能。 Lexical 旨在提供一流的开发人员体验,以便开发者可以轻松进行原型设计并快速构建功能。因为篇幅问题,关于 Lexical 主题只是做了一个简短的介绍,但是文末的参考资料提供了大量优秀文档以供学习,如果有兴趣可以自行阅读。如果大家有什么疑问欢迎在评论区留言。
参考资料
https://github.com/facebook/lexical
https://lexical.dev/docs/intro
https://lexical.dev/docs/getting-started/quick-start
https://lexical.dev/docs/getting-started/react
https://forums.envato.com/t/wysiwyg-editor-pro-version-now-at-review-queue-any-ideas-welcome/74503
https://www.youtube.com/watch?v=dx7HSB4Q-I8
https://ijs.to/p/is-lexcial-the-new-rich-editor-standard-for-react (封面图引用)
本文暂时没有评论,来添加一个吧(●'◡'●)