本文将介绍笔者在React的项目中使用百度的富文本编辑器Ueditor的过程。注意本文不提供一条龙式的使用方法,只是将使用过程中的一些实现思路进行总结,供以参考。react项目中导入ueditor,会存在各种不正交的问题,需要注意。
引入
首先在ueditor官网下载最新安装包,然后在项目入口的html中导入(导入方式不一,可以采用import的方式,需要自行度娘。但是无论哪种引入方式,只要想自定义功能,不正交问题就难以避免QAQ)。不管三七二十一先跑起来再说。。
<!DOCTYPE HTML> <html lang="en-US"> <head> <meta charset="UTF-8"> <title>ueditor demo</title> </head> <body> <!-- 配置文件 --> <script type="text/javascript" src="https://www.jb51.net/path/ueditor.config.js"></script> <!-- 编辑器源码文件 --> <script type="text/javascript" src="https://www.jb51.net/path/ueditor.all.js"></script> ······ </body> </html>
在React项目中使用ueditor要注意
导入的路径,笔者使用的是项目经webpack打包之后的相对路径。
导入顺序,配置文件要先于源码。
笔者这种引入方式存在缓存问题,所以修改ueditor.all.js后需要及时清理缓存,测试新的代码。
封装
/** * 封装UEditor */ import React from 'react'; import './index.less'; class UEditor extends React.Component { constructor(props) { super(props); this.editor = {}; this.id = ''; } ······ componentDidMount() { let UE = window.UE; let id = this.id; if (id) { try { /* 加载之前先执行删除操作,否则如果存在页面切换, 再切回带编辑器页面重新加载时不刷新无法渲染出编辑器 */ UE.delEditor(id); } catch (e) {} let ueditor = UE.getEditor(id, { toolbars: [ ['bold', 'italic', 'underline', 'kityformula', 'diyimg'] ], initialContent: '', autoHeightEnabled: false, autoFloatEnabled: false, elementPathEnabled: false, wordCount: false, enableAutoSave: false, initialFrameWidth: this.props.width, initialFrameHeight: this.props.height }); } } render() { this.id = this.props.id; return <div styleName="content" id={this.id} />; } } export default UEditor;
笔者在项目中使用了加粗,斜体,下划线,插入图片,公式等功能,想要自定义配置均可参照ueditor.config.js修改。具体的将一一介绍,最后实现效果如下:
问题总结:
1. 禁止自动增高,改用滚动条
autoHeightEnabled: false initialFrameWidth:this.props.width initialFrameHeight:this.props.height
autoHeightEnabled可以阻止自动增高,然后再自定义容器宽度和高度。
2. 自定义全局样式,如容器的padding,p标签的line-height等
解决方法:ueditor.all.js的第6800多行的render方法,在其中可以自定义全局样式。
3. 导航条切换后,无法再次渲染
解决方法:在每次ueditor实例化之前,先删除对应的id
UE.delEditor(id);
原因分析:
从实例化和卸载实例的源码来看:
getEditor:
UE.getEditor = function (id, opt) { var editor = instances[id]; if (!editor) { editor = instances[id] = new UE.ui.Editor(opt); editor.render(id);//渲染编辑器 } return editor; };
delEditor:
UE.delEditor = function (id) { var editor; if (editor = instances[id]) { editor.key && editor.destroy(); delete instances[id] } };
UE在全局管理了一个实例池,每次实例化都会根据id检索,然后生成实例。从getEditor的源码中可以看出,ueditor的一个实例在第一次初始化时存在一个editor.render(),这是将此id的实例渲染到对应的id容器上。然而,当用户tab切换编辑器再切回来时,此时由于该实例已在实例池中存在,于是直接执行return editor,所以少了editor.render()这一步,于是不能重新渲染。所以,在Ueditor组件每次实例化之前,先进行delEditor卸载。这里需要注意,从delEditor中可以看出ueditor卸载实例时调用了实例的destroy方法。从destroy的注释来看:销毁编辑器实例,使用textarea代替 ,这解释了为什么在切换编辑器或者卸载编辑器时,会出现编辑器变为textarea的情况,如图所示:
4. 模拟placeholder实现预置文案
解决方法:在UE的实例中自定义方法,实现填充文字模拟placeholder的效果,代码如下: