温馨提示:本文需要您对slatejs有一定了解,文中代码均为伪代码,主要讲思路
书接上回,我们已经实现了一个插件管理器,接下来,可以开始实现一些基础的插件了
Tag标签的具体表现
- 被识别为整块
- 光标无法插入到元素内
- 删除时为整块删除
设计与实现
- slatejs提供了
isVoid用来判定元素是否为空元素,即Tag类型,我们已经在上一篇文章中实现了editor.isVoid方法,优先获取插件内的isVoid属性进行判定 - Tag实际显示的内容在不能放在
children中,需要另一个属性存储 - 我们之前的插件管理器实现了
renderElement,这里只需要实现插件自己的renderElement去渲染一个Tag标签即可 useSelected()和useFocused()是slate-react提供的hooks,用于获取当前选中的和focus的元素
接下来事情就变得非常简单了,直接上手撸代码
const PLUGIN_TYPE_TAG = 'tag'
type TagElement = {
type: PLUGIN_TYPE_TAG;
character: string;
children: {text: string}[];
};
interface TagProps extends RenderElementProps {
element: TagElement;
}
const Tag: React.FC<TagProps> = ({ attributes, element, children }) => {
const selected = useSelected();
const focused = useFocused();
const selectedClass =
selected && focused ? `editor_tag--selected` : '';
return (
<span {...attributes} contentEditable={false}>
<span className={`editor_tag ${selectedClass}`}>
{element.character}
{children}
</span>
</span>
);
};
export default class TagPlugin implements BasePlugin {
editor = null;
isVoid = true;
isInline = true;
pluginType = PLUGIN_TYPE_TAG;
renderElement(props: RenderElementProps) {
const { attributes, children } = props;
const element = props.element as TagElement;
return (
<Tag
attributes={attributes}
element={element}
children={children}
/>
);
}
}
- 样式这里就不多贴了,可根据个人需求,调整
editor_tag和editor_tag--selected这两个类 - Tag插件实现完成,只需要在使用的时候初始化Tag插件,伪代码如下:
const plugins = [new Plugin()];
const [value, setValue] = useState([{
type: 'tag',
character: 'Tag标签的内容',
children: [{text: ''}]
}])
<MyEditor plugins={plugins} value={value} onChange={(value) => setValue(value)}/>
至此,Tag插件实现完成。
往期文章链接:富文本编辑器踩坑——(一)slatejs插件管理系统