改造wangEditor成react组件

栏目: IT技术 · 发布时间: 3年前

内容简介:我们知道wangEditor常用的功能是editor实例的我们怎么把这种传统模式书写的第三方库引入到react项目中,并且方便其它同事使用呢?我们需要做一个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);

改造wangEditor成react组件

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

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

改造wangEditor成react组件

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() 获取到富文本里面的内容了。


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Linux内核设计与实现(原书第3版)

Linux内核设计与实现(原书第3版)

Robert Love / 陈莉君、康华 / 机械工业出版社华章公司 / 2011-4-30 / 69.00元

《Linux内核设计与实现(原书第3版)》详细描述了Linux内核的设计与实现。内核代码的编写者、开发者以及程序开发人员都可以通过阅读本书受益,他们可以更好理解操作系统原理,并将其应用在自己的编码中以提高效率和生产率。 《Linux内核设计与实现(原书第3版)》详细描述了Linux内核的主要子系统和特点,包括Linux内核的设计、实现和接口。从理论到实践涵盖了Linux内核的方方面面,可以满......一起来看看 《Linux内核设计与实现(原书第3版)》 这本书的介绍吧!

CSS 压缩/解压工具
CSS 压缩/解压工具

在线压缩/解压 CSS 代码

JSON 在线解析
JSON 在线解析

在线 JSON 格式化工具

HTML 编码/解码
HTML 编码/解码

HTML 编码/解码