改造富文本编辑器wangEditor成react组件
改造富文本编辑器wangEditor成react组件
我们知道wangEditor常用的功能是editor实例的txt.html()
和txt.text()
方法,尤其是txt.html()
方法,这是一个类似与jQuery常用的那种get和set一体的方法。
我们怎么把这种传统模式书写的第三方库引入到react项目中,并且方便其它同事使用呢?我们需要做一个react组件,让它来完成wangEditor的“react化”。
对于编辑器这种,我们不太在乎它的生命周期,我们更适合将它封装成函数式组件。
我们在项目使用是只有使用ref拿到这个组件并且调用对应的方法来取到(设置)富文本里面的内容。
<WangEditor
ref={this.richEditorRef}
content={this.state.editShortcutReply.content}/>
这样在使用时就很方便啊,那我们的WangEditor组件怎么实现呢?
import React, { useEffect, forwardRef, useImperativeHandle } from 'react';
import toaster from 'viewsUI/toaster';
import WangEditor from 'viewsUI/wangeditor/wangEditorForSetting'
import wangEditorI18nLang from './i18nLang';
let richEditor = null;
/*eslint-disable*/
const wangEditor = (props, ref) => {
let unique = Math.random().toString(36).substr(2);
useEffect(() => {
console.log('wangEditor useEffect -> ');
loadEditor();
if (props.visible) {
setContent(props.content || '');
}
}, []);
function getContent() {
return richEditor.txt.html();
}
function getText() {
return richEditor.txt.text();
}
function setContent (content) {
richEditor.txt.html(content);
initFocus();
}
function initFocus() {
const $textElem = richEditor.$textElem;
const $children = $textElem.children();
if ($children.length) {
const $first = $children.first();
richEditor.selection.createRangeByElem($first, false, true);
richEditor.selection.restoreSelection();
}
}
useImperativeHandle(ref, () => ({
getContent,
getText,
setContent,
initFocus,
}));
function loadEditor() {
richEditor = new WangEditor('#toolbar' + unique, '#body' + unique);
richEditor.customConfig.uploadImgShowBase64 = false;
richEditor.customConfig.uploadImgMaxLength = 1
richEditor.customConfig.uploadImgParams = {
fileBytes: '',
maxBytes: 204800,
thumbHeight: 120,
thumbWidth: 120,
};
richEditor.customConfig.menus = [
'head', // 标题
'bold', // 粗体
'fontSize', // 字号
'fontName', // 字体
'italic', // 斜体
'underline', // 下划线
// 'strikeThrough', // 删除线
'foreColor', // 文字颜色
'backColor', // 背景颜色
'link', // 插入链接
'list', // 列表
'justify', // 对齐方式
'quote', // 引用
//'emoticon', // 表情
'image', // 插入图片
// 'table', // 表格
'htmlTable', // 粘贴表格
// 'video', // 插入视频
// 'code', // 插入代码
'undo', // 撤销
'redo' // 重复
];
richEditor.create();
}
return (
<div style={{display: 'flex','flexDirection': 'column',width: '100%', height: '100%', overflow: 'auto'}}>
<div id={'toolbar' + unique} style={{borderBottom: '1px solid #EBF2FA', fontSize: '14px', padding: '5px 10px', marginBottom: '5px', flex: 'none' }}/>
<div id={'body' + unique} style={{height: 'auto',wordBreak: 'break-all',whiteSpace: 'normal',flex: 'auto',display: 'flex',flexDirection: 'column', overflow: 'auto'}}/>
</div>
);
};
export default forwardRef(wangEditor);
为了给父组件暴露wangEditor组件的部分方法,我们需要使用useImperativeHandle
。
它可以让你在使用 ref 时自定义暴露给父组件的实例值。在大多数情况下,应当避免使用 ref 这样的命令式代码。
通常useImperativeHandle
应当与forwardRef
一起在函数式中使用。
forwardRef介绍
用法一:让我们在父组件里面能通过ref
拿到函数式子组件的某个node节点
const Menu = (props, ref) => {
return (<aside ref={ref} id="menu" className={props.show ? 'show' : ''}>
<div className="inner flex-row-vertical">
<Profile avatarUrl="/owner.jpg"/>
<div className="scroll-wrap flex-col">
<MenuList asides={props.asides}/>
<ArchiveList />
</div>
</div>
</aside>);
};
export default forwardRef(Menu);
具体使用细节可以参照我前几天写的《Did you mean to use React.forwardRef()?搞懂react的createRef和forwardRef》
用法二:让我们在父组件里面能通过ref
拿到函数式子组件需要通过useImperativeHandle
暴露的方法
const Menu = (props, ref) => {
function log(...rest) {
console.log(...rest);
}
useImperativeHandle(ref, () => ({
log
}));
return (<aside ref={ref} id="menu" className={props.show ? 'show' : ''}>
<div className="inner flex-row-vertical">
<Profile avatarUrl="/owner.jpg"/>
<div className="scroll-wrap flex-col">
<MenuList asides={props.asides}/>
<ArchiveList />
</div>
</div>
</aside>);
};
export default forwardRef(Menu);
useImperativeHandle介绍
useImperativeHandle(ref, createHandle, [deps])
ref
:定义 current 对象的 refcreateHandle
:一个函数,返回值是一个对象,即这个 ref 的current[deps]
:即依赖列表,当监听的依赖发生变化,useImperativeHandle 才会重新将子组件的实例属性输出到父组件ref 的 current 属性上,如果为空数组,则不会重新输出。
现在我们就可以通过this.richEditorRef.current.getContent()
获取到富文本里面的内容了,快去试试吧。
- 分类:
- Web前端
相关文章
Did you mean to use React.forwardRef()?搞懂react的createRef和forwardRef
最近在使用react过程中发现在使用ref时的一些场景,自己初步感觉react的ref没有vue那么强大。 现在我就简单看下怎么使用ref? createRef 我们直接看源码 / 阅读更多…
深入学习React时间切片,任务调度scheduler
背景 最近想起月初看到的 魔术师卡颂 (微信号:kasong999)的一个公开直播—— 《手写React优先级调度算法》 ,虽然我更倾向于认为直播内容是演示如何利用React官方同款调度库手写代 阅读更多…
Vue和React hooks实现Select批量选择、选中条数、全选、反选实现对比
批量选择、全选、反选这些功能使用频率还是很高的,下面直接看看Vue和React分别怎么实现吧。 Vue 在使用Vue的时候是很容易实现的,我们以下列数据格式为例: const data 阅读更多…
项目Vue转成React hooks可能存在的问题--急需类似setState回调
假设在Vue中有如下三个方法,并且初始时 this.a = ‘a’; this.b = ‘b’; funA() { this.a = '1221 阅读更多…
Did you mean to use React.forwardRef()?搞懂react的createRef和forwardRef
最近在使用react过程中发现在使用ref时的一些场景,自己初步感觉react的ref没有vue那么强大。 现在我就简单看下怎么使用ref? createRef 我们直接看源码 / 阅读更多…
邮箱收件人组件成长历程(二)(React hooks升级版)
记得自己之前写过一篇 《邮箱收件人组件(vue版)成长历程(一)》 记得当时里面写到了自己使用的是可编辑div来进行输入的,同时提到 当时出于挑战自己和青铜的倔强,想试着换个方案,完全使用可编辑di 阅读更多…