slate.js 🔗
v0.47
slate是开源社区最新出的一个比较火的可定制化的富文本编辑器
https://github.com/ianstormtaylor/slate
slate 是一个底层核心库,如果要使用,还需要配合slate-react等进行UI部分展示
安装 🔗
yarn add slate slate-react
使用 🔗
slate使用的是基于js对象,通过slate内核进行转换后,用slate-react最终映射到真实dom上
slate传入的初始化的值格式为
1
2
3
4
5
6
| [
{
type: string,
children: []
}
]
|
最顶层的type就是paragraph, 表示段落
段落的子元素又是一个个对象,可以用不同的type进行区分,其中children中也可以写入一个text对象,表示当前就是文本节点
基础渲染 🔗
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
| import React, { useMemo, useCallback } from 'react'
import { Editor, BaseEditor } from "slate";
import {
Slate,
Editable,
withReact,
ReactEditor
} from "slate-react";
const initialValue: Descendant[] = [
{
type: "paragraph",
children: [
{
text: "With Slate you can build complex block types that have their own embedded content and behaviors, like rendering checkboxes inside check list items!",
},
],
},
];
export const App = ({ p }: any) => {
const editor: ReactEditor = useMemo(
() => withHistory(withReact(createEditor())),
[]
);
return (
<Slate editor={editor} value={initialValue}>
<Editable
placeholder="Get to work…"
/>
</Slate>
);
};
|
添加监听事件 🔗
slate-react
封装的Editable
组件就是类似于contenteditable, 其中暴露了一系列的监听事件可以对外使用
1
2
3
4
5
6
7
8
9
| <Editable
onKeyDown={event => {
if (event.key === '&') {
// 可以监听到对应的值
event.preventDefault()
editor.insertText('and')
}
}}
/>
|
自定义渲染元素 🔗
https://docs.slatejs.org/walkthroughs/03-defining-custom-elements
实际在使用过程中富文本编辑器中需要渲染其他效果,比如说高亮,文字加颜色等
Editable组件留下了一个渲染入口,可以根据不同的type去渲染不同的组件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
| const renderElement = useCallback((props: any) => <Element {...props} />, []);
const Element = (
props: JSX.IntrinsicAttributes & {
attributes: any;
children: any;
element: any;
}
) => {
const { attributes, children, element } = props;
// 根据不同的type类型渲染不同的元素
switch (element.type) {
case "check-list-item":
return <CheckListItemElement {...props} />;
case "pinyin":
return <RenderHanzi {...props} />;
default:
return <DefaultElement {...attributes}>{children}</DefaultElement>;
}
};
|
最后在Editable上使用
1
2
3
4
| <Editable
// ....
renderElement={renderElement}
/>
|