介绍
这个编辑器组件功能很多,支持大纲、数学公式、流程图等,基本上能想到的都包含了,开箱即用。编辑体验良好,移动设备使用体验也不错。
这是个中文项目,已持续多年迭代,社区稳定,文档易懂,Demo 多样,使用 TS 开发,类型友好。
https://github.com/Vanessa219/vditor
安装使用
npm install vditor --save
使用:
- 如何在 React 中使用: https://b3log.org/vditor/demo/react.html
- 如何在 Vue 中使用: https://b3log.org/vditor/demo/vue.html
React 包装组件
在官网 React 示例的基础上,我进行了以下封装:
- 支持传入参数,不做过多定制化,由外部控制
- 模仿
tui.editor
的用法,支持通过 ref 来获取 vditor 实例,方便外部操作
export interface IVditorEditorProps {
options: IOptions;
}
export interface IVditorEditorRef {
getInstance: () => Vditor | null;
}
const VditorEditor: ForwardRefRenderFunction<IVditorEditorRef, IVditorEditorProps> = (
{ options },
ref,
) => {
const domRef = useRef<HTMLDivElement>(null);
const vditorRef = useRef<Vditor | null>(null);
const optionsRef = useRef(options);
useEffect(() => {
if (domRef.current) {
vditorRef.current = new Vditor(domRef.current, optionsRef.current);
}
return () => {
if (vditorRef.current) {
vditorRef.current.destroy();
}
};
}, []);
function getInstance() {
return vditorRef.current;
}
useImperativeHandle(ref, () => {
return { getInstance };
});
return <div ref={domRef}></div>;
};
export default forwardRef(VditorEditor);
编辑器设置记录
以下内容都在编辑器初始化时传入的 options 参数声明。
配置 tab 使得可以方便地编辑代码,不然点击 tab 后可能会出现不符合预期的效果。
tab: ' '
历史记录间隔,默认是 800 毫秒,缩短间隔时间可避免一次性回退过多内容。
undoDelay: 400
初始化后,赋予默认值:
after: () => {
if (value) {
instance.setValue(value);
}
}
内容更新回调:
input(value: string) {
onChange(value);
}
自定义单图片上传:
upload: {
accept: 'image/*',
multiple: false,
async handler(files) {
let file = files[0];
let url = await uploadFunc(file);
let name = file.name;
let code = `\n![${name}](${url})`;
instance.insertValue(code);
return null
},
},
由于按需加载的机制,vditor 使用了 cdn,但可能不太稳定,可进行自建 cdn,将 dist 目录放到自定义的一个目录下,需包含 dist 本身:
cdn: cdnPath,
theme: {
path: `${cdnPath}/dist/css/content-theme`,
current: 'light',
},
模式切换与表格编辑
可选模式有:sv 分屏预览, ir 即时渲染, wysiwyg 所见即所得;
- 即时渲染、所见即所得模式,有大纲,可快速定位到某个小节进行修改。
- 表格编辑适合到所见即所得模式下进行编辑,有上、下、左、右插入行列的选项
- sv 模式下问题相对较多,vditor 官方对 sv 模式也不太维护,使用体验一般。
所以使用模式为:默认使用 ir 即时渲染模式,表格编辑时使用 wysiwyg 所见即所得模式,查看 markdown 源代码时使用 sv 分屏预览模式。
一些使用笔记
移动端窗口小,可切换为全屏后,使用即时渲染模式,也有很好的编辑体验,大纲在移动端会自动隐藏。
复制代码片段、链接时编辑器会进行处理,如代码片段会自动加 ···
,即使已经在代码片段内,这样就会导致错乱。此时使用 shift + ctrl + v 粘贴进来即可,不会特殊处理。
在 ir 即时渲染模式中,代码块后如果是标题,标题前无法插入内容。可在下一行标题前点击回车,然后输入内容,即可继续编写本节内容。全文最后段代码,在代码最后一行按方向键下即可进入新的一行。
markdown 文本渲染
组件还提供了一些静态方法,如对页面中的 Markdown 进行渲染时可直接调用 preview
方法。
基于这个方法,可再封装一个 React 渲染组件,支持 value 改变后重新渲染:
export interface IVditorPreviewProps {
value: string | undefined;
}
const VditorPreview: FC<IVditorPreviewProps> = ({ value }) => {
const domRef = useRef<HTMLDivElement>(null);
useEffect(() => {
if (domRef.current && value) {
Vditor.preview(domRef.current, value);
}
}, [value]);
return <div ref={domRef}></div>;
};