摘要:前言本文将介绍笔者在的项目中使用百度的富文本编辑器的过程。以百度官网的为例,控制台输入为该编辑器注册点击事件,当点击加粗按钮时,控制台输出为了避免点击工具条时触发事件,笔者将自定义的事件全部注释了。
前言
本文将介绍笔者在React的项目中使用百度的富文本编辑器Ueditor的过程。注意本文不提供一条龙式的使用方法,只是将使用过程中的一些实现思路进行总结,供以参考。react项目中导入ueditor,会存在各种不正交的问题,需要注意。
引入首先在ueditor官网下载最新安装包,然后在项目入口的html中导入(导入方式不一,可以采用import的方式,需要自行度娘。但是无论哪种引入方式,只要想自定义功能,不正交问题就难以避免QAQ)。不管三七二十一先跑起来再说。。
ueditor demo
······
在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 ;
}
}
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的效果,代码如下:
//模拟placeholder和控制toolbar显示隐藏
UE.Editor.prototype.initDiy = function (placeholder) {
var _editor = this;
//获取焦点
_editor.addListener("focus", function () {
UE.isEditored = true;
var Text = `${placeholder}
`
var localHtml = _editor.getContent();
if (localHtml === Text) {
_editor.setContent("");//点击时清空
_editor.focus(true);
}
//使得其他工具条display置为none
var list = document.querySelectorAll(".edui-editor-toolbarbox");
list.forEach((ele) => {
ele.style.display = "none";
});
var toolbar = findKey(_editor.key);
toolbar.style.display = "block";
});
// 插入图片时存在问题
// _editor.addListener("blur", function () {
// var localHtml = _editor.getContent();
// if (localHtml === "") {
// _editor.setContent(`${placeholder}
`);
// }
// // window.activeEditor = _editor.key;
// });
_editor.ready(function () {
// _editor.fireEvent("blur");
_editor.setContent(`${placeholder}
`);//填充预置文案
});
}
//寻找工具条
function findKey(key) {
let ele = document.querySelector(`#${key}`);
let toolbar = ele.querySelector(".edui-editor-toolbarbox");
return toolbar;
}
原来,笔者实现的效果是点击时清空,失焦时还原。但是,在做自定义工具条时产生了bug(在5中我会细说),因此我采用了另一种方案:初始时设置预设文案,当用户聚焦时清空预设,用户失焦后不再恢复该预设文案。也就是将blur事件注释了。。。
5. 工具条显示在编辑器头部,显示为悬浮效果,默认隐藏,聚焦时出现实现思路:将themes/default/css/ueditor.css中加入:
.edui-default .edui-editor-toolbarbox {
position: absolute;
······
top: -36px;
}
首先实现头部偏移,然后通过控制toolbar对应dom元素的display来隐藏工具条。实现效果如下:
下面解释一下为什么编辑器失焦的时候不恢复预置文案:
从4中的代码可以看出,我们是通过触发focus和blur事件分别清空和填充编辑器的内容。但是当我们点击工具条时,编辑器就会触发blur事件!!于是就会出现各种bug。以百度官网的ueditor为例,控制台输入:
为该编辑器注册点击事件,当点击加粗按钮时,控制台输出:
为了避免点击工具条时触发blur事件,笔者将自定义的blur事件全部注释了。
6. 自定义按钮和七牛云图片上传首先,在ueditor.config.js中找到toolbars数组,增加一个diyimg字符串,然后在zh-cn.js找到labelMap数组,在末尾加上"diyimg": "插入图片" 。最后,在ueditor.all.js中找到btnCmds数组,加入diyimg字符串。初始化时使用这个字符串,工具条上就会显示一个按钮,但是我们发现他显示的是这样的:
这是因为ueditor默认使用加粗的icon作为自定义按钮的默认icon,所以为了使用默认的插入图片的图标,我们需要到themes/default/css/ueditor.css中,在最后一行加入:
/*自定义图片上传按钮 */
.edui-default .edui-toolbar .edui-for-diyimg .edui-icon {
background-position: -380px 0px;//这个位置是“插入图片”的icon,其他图标可自行调整
}
添加后,显示效果如下:
图标正常显示后,需要为该图标添加相应的点击事件,在ueditor.all.js中加入:
//图片上传
UE.commands["diyimg"] = {
execCommand : function(){
const upload = async(e) => {
······//完成图片上传的代码
}
const fileInput = document.getElementById("diyimg");//获取dom上隐藏的一个input标签
fileInput.onchange = upload;
fileInput.click();//触发input标签实现文件上传
return true;
},
queryCommandState:function(){
}
};
笔者这里不赘述图片上传的代码,度娘上很多,我简单说说实现的思路:
先实现一个插入图片的按钮,然后为该按钮注册相应的事件diyimg,然后在页面中添加一个input file标签并隐藏,diyimg事件会触发该标签的点击事件,弹出文件上传弹窗,此时选择文件点击后会触发onchange事件,执行相应的图片上传代码。上传成功到服务器后,服务器会返回图片对应的url,此时拿到该url填入对应编辑器实例,执行编辑器的插入图片的代码:
this.execCommand("insertimage", {
src: res.data.downloadUrl,//回调传来的url
width:"60"
// height:"45"
});
7. 给在编辑器内部的img等标签添加内联样式
ueditor默认存在xss过滤!!!这里以给img标签添加style=“vertical-top”为例。
首先要找到ueditor.config.js,在其中搜索xss,在第403行左右有代码:
img: [src", "alt", "title", "width", "height", "id", "_src", "loadingclass", "class", "data-latex"],
往数组里加入style字符串,然后在ueditor.all.js中搜索UE.commands["insertimage"] ,在第约11172行找到str,往里面加入内联样式即可。
一些吐槽: 1. 在react项目里使用script形式引入,感觉格格不入 2. 为了实现placeholder,各个事件之间存在不正交的现象。诸如点击按钮,却触发了编辑器的失焦事件 3. 在使用自定义的字数限制功能时,笔者使用ueditor的contentChange去检测内容字数,但是contentChange事件是定时的,所以计算字数会有问题。
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/52900.html
摘要:前言本文将介绍笔者在的项目中使用百度的富文本编辑器的过程。以百度官网的为例,控制台输入为该编辑器注册点击事件,当点击加粗按钮时,控制台输出为了避免点击工具条时触发事件,笔者将自定义的事件全部注释了。 前言 本文将介绍笔者在React的项目中使用百度的富文本编辑器Ueditor的过程。注意本文不提供一条龙式的使用方法,只是将使用过程中的一些实现思路进行总结,供以参考。react项目中导入...
VSCode使ReactVue代码调试变得更爽 在前段开发中,大家会遇见调试 Vue/React 代码,现在就给大家总结都有哪几种: 先找代码问题,在console.log 打印日志,用 Chrome Devtools 的 debugger 来调试,用 VSCode 的 debugger 来调试。 看到是不是不同,不仅效率大大提升就连体验也是超级帮的,这种体验让人超级爽到爆炸。 很多...
这是讲 ahooks 源码的第一篇文章,简要就是以下几点: 加深对 React hooks 的理解。 学习如何抽象自定义 hooks。构建属于自己的 React hooks 工具库。 培养阅读学习源码的习惯,工具库是一个对源码阅读不错的选择。 注:本系列对 ahooks 的源码解析是基于v3.3.13。自己 folk 了一份源码,主要是对源码做了一些解读,可见详情。 第一篇主要介绍 a...
在这里为大家介绍,实现多张图自动轮播可以用react-slick插件,下面一起看看: 一、进入官网查看文档(Docs) react-slick官网 二、安装插件(Quick Start) //npm安装 npminstallreact-slick--save //yarn安装 yarnaddreact-slick 三、范例使用(Examples) 在examples在扩...
用vite作为项目打包工具,这是为什么?其中最主要的原因是 ——vite在开发环境基于ESM规范实现的Nobundle模式,节省了代码打包的时间。 当前打包的需求任然有,且ESM规范兼容性越来越好,进入生产环境大面积可用的状态也不是不可能。 当生产环境打包将不再是刚需时。 另一方面,从HTTP协议的角度看,在HTTP/1.1时代,多个模块被打包成一个文件能减少浏览器并发请求数,达到优化目...
阅读 3236·2021-11-18 10:02
阅读 1103·2021-10-08 10:04
阅读 2710·2021-09-03 10:51
阅读 3931·2019-08-30 15:44
阅读 3180·2019-08-29 14:09
阅读 2784·2019-08-29 12:21
阅读 2320·2019-08-26 13:45
阅读 2114·2019-08-26 13:25