前言
本文将介绍在React项目中使用百度富文本编辑器Ueditor的过程。注意,本文并没有提供一站式的使用方法,只是总结了使用过程中的一些实现思路,以供参考。在react项目中导入ueditor存在各种非正交问题,需要引起重视。
介绍
首先在ueditor官网下载最新的安装包,然后在项目入口的html中导入(导入方式不同,可以使用导入方式,需要自己做决定。但是无论是哪种介绍方式,想要定制功能都很难避免QAQ。不管怎样,先跑。
!DOCTYPE html html lang=' en-US ' head meta charset=' UTF-8 ' title ueditor demo/title/head body!-配置文件-脚本类型=' text/JavaScript ' src=' http : path/ueditor . config . js '/脚本!-编辑器源代码文件-脚本类型=' text/JavaScript ' src=' http : path/ueditor . all . js '/脚本./body/html在React项目中使用ueditor,注意它
导入路径,作者在项目被webpack打包后使用相对路径。导入顺序,配置文件应该在源代码之前。这种方式存在缓存问题,需要在修改ueditor.all.js封装后及时清除缓存并测试新代码
/* * *包UEditor */从“React”导入React;“进口”。/index . less ';类UEditor扩展了React。组件{构造器(道具){ super(道具);this . editor={ };this.id=} componentDidMount() {让UE=window。用户设备;let id=this.id如果(id){加载前尝试{/*删除,否则有页面切换,用编辑器切回页面重新加载不刷新,编辑器无法渲染*/UE . deleditor(id);} catch(e){ } let ueditor=UE . geteditor(id,{ toolbars: [ ['bold ',' italic ','下划线',' kityformula ',' diyimg'],initialContent: ' ',autoHeightEnabled: false,elementPathEnabled: false,wordCount: false,enableAutoSave: false,initial framewidth 3360 this . props . width,initialFrameHeight:} } render(){ this . id=this . props . id;返回div style name=' content ' id={ this . id }/;} }导出默认的UEditor我在项目中使用了粗体、斜体、下划线、插入图片、公式等功能。如果要自定义配置,可以参考ueditor.config.js进行修改。具体情况将逐一介绍,最终结果如下:
问题总结:
1.禁止自动增加,改用滚动条
auto height abled : false initial frame length:这个。props . width initialialframeheight:这个。props . height auto height abled可以防止自动增加,然后自定义容器的宽度和高度。
2.自定义全局样式,如容器的填充、P标签的行高等
解决方法:ueditor.all.js第6800行的render方法,您可以在其中自定义全局样式。
3.导航栏切换后,不能再次呈现
解决方法:在每次实例化ueditor之前删除相应的id
UE . deleditor(id);原因分析:
从实例化和卸载实例的源代码中:
getEditor:
UE.getEditor=function (id,opt){ var editor=instance[id];if(!编辑器){ editor=instances[id]=new UE . ui . editor(opt);editor . render(id);//渲染编辑器}返回编辑器;};删除者:
UE . deleditor=function(id){ var editor;if(editor=instance[id]){ editor . key editor . destroy();删除实例[id]} };UE全局管理一个实例池,每个实例化都会根据id进行检索,然后生成一个实例。从getEditor的源代码可以看出,ueditor的一个实例在第一次初始化的时候有一个editor.render(),就是把这个id的实例渲染到对应的id容器中。但是,当用户选项卡切换回编辑器时,实例已经存在于实例池中,因此直接执行返回编辑器,因此缺少editor.render()的步骤,因此无法重新呈现。因此,在Ueditor组件的每次实例化之前,卸载delEditor。这里需要注意的是,从delEditor可以看出,当ueditor卸载实例时,会调用实例的destroy方法。根据destroy的注释:销毁编辑器实例,替换为textarea,这就解释了为什么在切换编辑器或卸载编辑器时,编辑器会变成textarea,如图所示:
4.模拟占位符实现预置复制
解决方案:在UE实例中自定义方法,实现填充文本模拟占位符的效果。代码如下:
//模拟占位符和控件工具栏显示隐藏UE . editor . prototype . initdiy=function(占位符){ var _ editor=this//get focus _ editor . addlistener(' focus ',function(){ UE . iseditor=true;var Text=` p style=' color : # CDCDCD ' $ { placeholder }/p ` var localHtml=_ editor . getcontent();if(LocalHTML===Text){ _ editor . setContent(');//单击时为empty _ editor . focus(true);}//将其他工具栏的显示设置为none var list=document . queryselectorall('。edui-编辑器-工具栏框’);list . foreach((ele)={ ele . style . display=' none ';});var toolbar=find key(_ editor . key);toolbar . style . display=' block ';});//插入图片时出现问题//_ editor.addlistener ('blur ',function(){//var local html=_ editor . getcontent();//if(LocalHTML==' '){//_ editor . setContent(` p style=' color : # CDCDCD ' $ { placeholder }/p `);//}////window . activeeditor=_ editor . key;//});_ editor . ready(function(){//_ editor . FireEvent(' blur '));_ editor . setcontent(` p style=' color : # CDCDCD ' $ { placeholder }/p `);//填写预设副本});}//查找工具栏功能查找键(key){ let ele=document . queryselector(`# $ { key } `);let toolbar=ele.querySelector('。edui-editor-toolbarbox’);返回工具栏;}原来作者达到的效果是点击时清空,失去焦点时恢复。但是自定义工具栏的时候有一个bug(我会在5中详细说明),所以我采用了另外一个方案:初始设置预置副本,用户对焦时清除预置,用户失焦后不恢复预置副本。也就是说,模糊事件被注释。
5.工具栏显示在编辑器的顶部,显示悬浮效果,默认情况下隐藏,聚焦时显示
实现思路:添加主题/默认/css/ueditor.css到:默认。edui-editor-toolbarbox { position : absolute;top :-36px;}首先实现头部偏移,然后通过控制工具栏对应的dom元素的显示来隐藏工具栏。效果如下:
我们来解释一下为什么编辑器失焦时预设副本不恢复。从4中的代码中,我们可以看到,我们通过分别触发Focus和blur事件来清空和填充编辑器的内容。但是当我们点击工具栏时,编辑器会触发模糊事件!然后各种bug就会出现。以百度官网的ueditor为例,控制台输入:
为编辑器注册点击事件。单击粗体按钮时,控制台输出:
为了避免在点击工具栏时触发模糊事件,作者标注了所有定制的模糊事件。
6.自定义按钮,上传齐牛云的图片
首先在ueditor.config.js中找到toolbars数组,添加一个diymg字符串,然后在zh-cn.js中找到labelMap数组,最后添加' diyimg ' : ' insert picture '。最后,在ueditor.all.js中找到btnCmds数组,并添加第一个字符串。当这个字符串用于初始化时,工具栏上会显示一个按钮,但是我们发现它显示的内容如下:
那是因为ueditor默认使用粗体图标作为自定义按钮的默认图标,所以为了使用默认图标插入图片,我们需要在最后一行添加themes/default/css/ueditor.css:
/*自定义图片上传按钮*/。edui-default . edui-toolbar . edui-for-DIY mg . edui-icon { background-position :-380 px;//这个位置是“插入图片”的图标,其他图标可以自行调整。}添加后,显示效果如下:
图标正常显示后,需要为图标添加对应的点击事件,并在ueditor.all.js中添加:
//图片上传UE.commands[' DIY mg ']={ exec command : function(){ const upload=async(e)=}.//完成图片上传的代码} const file input=document . getelementbyid(' DIY mg ');//获取隐藏在dom fileInput.onchange=upload上的输入标记;file InPut . click();//触发输入标签实现文件上传返回真;},query commandstate : function(){ } };这里不重复上传图片的代码。有很多图片。我将简单谈谈实现思路:
首先实现一个按钮来插入图片,然后为按钮注册相应的事件di vig,然后给页面添加一个输入文件标签并隐藏。di vig事件会触发标签的点击事件,弹出上传文件的弹出窗口。此时,单击所选文件将触发onchange事件并执行相应的图像上传代码。成功上传到服务器后,服务器会返回图片对应的url。此时,获取url并填写相应的编辑器实例,执行插入图片的编辑器代码:
这个。execcommand ('insertimage ',{src:res.data.downloadurl,//URL宽度3360' 60'/高度: ' 45 ' });7.在编辑器中为标签(如img)添加内嵌样式
默认情况下,ueditor中存在Xss筛选!以img标签为例,添加style="vertical-top "。
首先,找到ueditor.config.js,在其中搜索xss,第403行周围有代码:
Img: [src ',' alt ',' title ',' width ',' height ',' id ',' _ src ',' loading class ',' class ',' data-latest'],将样式字符串添加到数组中,然后在ueditor.all.js中搜索UE.comm
有人吐槽:
1.在react项目中引入脚本感觉不合适
2.为了实现占位,事件之间存在非正交现象。例如单击按钮,会触发编辑器的失焦事件
3.使用自定义字数限制功能时,作者使用ueditor的contentChange来检测内容字数,但contentChange事件是定时的,因此在计算字数时会出现问题。
实施中存在的问题及解决办法
1.上传图片时出现跨域问题
源代码中有标题[' x _ request _ with ']=' xmlhttprequest ';
需要为后端配置标头(“访问控制-允许-标头”、“访问令牌、内容类型、weborigin、x-requested-with、x _ requested _ with”)。
2.进入文本编辑界面的编辑器未加载。
可能的原因:放置了编辑器的容器id,并且容器下的编辑器已经存在
代码中显示了解决方案
this.editor.ready(函数(ueditor) {if(!Ueditor) {//如果初始化后Ueditor不存在,删除后再次调用UE . deleditor(self . props . id);self . initeditor();}})3.注意这两个参数的配置
ueditor _ home _ URL ' : '/react/dist/Ueditor/',//editor实例路径,即放置u editor包的位置
serverurl 3360 window . API _ host '/inner message/uploadimage ',//后端提供了一个加载图片的接口,这是一个常见的接口。后端配置的config.json文件在url中传递操作。
要区分的不同值(config|uploaimage等。)
以上就是本文的全部内容。希望对大家的学习有帮助,支持我们。