改造富文本编辑器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前端
相关文章
React router用hooks读取routeName、根据routeName跳转
在迁移Vue至React的过程中遇到了一些路由相关的问题,在Vue项目中经常会使用routeName,毕竟使用path太长了,也记不住,我自己看了看React router也没有发现routeNam 阅读更多…
使用next.js服务端渲染经历
上周末的时候打算把自己的网站从vue的ssr转换为react的ssr,鉴于之前在vue中是用的原生的ssr,这次想在react中试试框架,所以首选的就是next.js。 第一次用next.js,根据 阅读更多…
WordPress博客项目改用react前端展示
之前自己的主打技术栈是vue全家桶,所以将自己的wordpress博客改成了vue版本服务端渲染,现在因为公司需要将我的项目从vue转到react,本人后面可能也就要主打eact技术栈了。 我记 阅读更多…
对React Hooks的Capture value特性的理解
之前我的项目里面很多功能都是用的事件驱动,所以下面的实例也会更多地使用监听事件的回调函数。 我们先看下测试代码 const {useEffect ,useState, useRef, us 阅读更多…
项目Vue转成React hooks可能存在的问题--急需类似setState回调
假设在Vue中有如下三个方法,并且初始时 this.a = ‘a’; this.b = ‘b’; funA() { this.a = '1221 阅读更多…
转译:使用react hooks优化回调函数在组件间的传递,useState,useReducer?
我们先看一下使用 useState hooks写的todoList组件,里面我们需要层层传递回调函数。 import React, { useState } from "react& 阅读更多…