富文本编辑器踩坑——(二)在slatejs中实现一个Tag插件

1,475 阅读1分钟

温馨提示:本文需要您对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_tageditor_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插件管理系统