道招

改造富文本编辑器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);

file

具体使用细节可以参照我前几天写的《Did you mean to use React.forwardRef()?搞懂react的createRef和forwardRef》

用法二:让我们在父组件里面能通过ref拿到函数式子组件需要通过useImperativeHandle暴露的方法

file

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 对象的 ref createHandle:一个函数,返回值是一个对象,即这个 ref 的current [deps]:即依赖列表,当监听的依赖发生变化,useImperativeHandle 才会重新将子组件的实例属性输出到父组件ref 的 current 属性上,如果为空数组,则不会重新输出。

现在我们就可以通过this.richEditorRef.current.getContent()获取到富文本里面的内容了,快去试试吧。

更新时间:
上一篇:转译:使用react hooks优化回调函数在组件间的传递,useState,useReducer?下一篇:web前端开源流程图组件库调研记录

相关文章

转译:使用react hooks优化回调函数在组件间的传递,useState,useReducer?

我们先看一下使用 useState hooks写的todoList组件,里面我们需要层层传递回调函数。 import React, { useState } from &quot;react& 阅读更多…

Did you mean to use React.forwardRef()?搞懂react的createRef和forwardRef

最近在使用react过程中发现在使用ref时的一些场景,自己初步感觉react的ref没有vue那么强大。 现在我就简单看下怎么使用ref? createRef 我们直接看源码 / 阅读更多…

Did you mean to use React.forwardRef()?搞懂react的createRef和forwardRef

最近在使用react过程中发现在使用ref时的一些场景,自己初步感觉react的ref没有vue那么强大。 现在我就简单看下怎么使用ref? createRef 我们直接看源码 / 阅读更多…

WordPress博客项目改用react前端展示

之前自己的主打技术栈是vue全家桶,所以将自己的wordpress博客改成了vue版本服务端渲染,现在因为公司需要将我的项目从vue转到react,本人后面可能也就要主打eact技术栈了。 我记 阅读更多…

关注道招网公众帐号
道招开发者二群