vant850

工作中遇到了一个需要做图文详情 的富文本编辑的需求, 于是基于 React-draft-wysiwyg 实现了一个 纯组件, 目前支持 常规文本输入 外部链接图片 以即本地上传图片, 由于是纯组件, 可直接放在react 项目中引入使用, 就不废话了 直接上代码

import React, { Component } from 'react';
import { Editor } from 'react-draft-wysiwyg';
import { EditorState, convertToRaw, ContentState } from 'draft-js';
import draftToHtml from 'draftjs-to-html';
import htmlToDraft from 'html-to-draftjs';
import 'react-draft-wysiwyg/dist/react-draft-wysiwyg.css';

//  这里的 UploadBase64 是我的图片上传接口
import { UploadBase64 } from '@/services/common_services';
// 这里的 IMG_URL 图片的 Host, 因为上面的接口上传成功返回的是一个相对路径 页面展示时需要自行拼接 Host。 这两处, 大家可根据实际情况自行修改
import { IMG_URL } from '@/utils';

const transformDraftStateToHtml = (editorState) => {
  if (!editorState.getCurrentContent) {
    return '';
  }
  return draftToHtml(convertToRaw(editorState.getCurrentContent()));
};

const transformHtmlToDraftState = (html = '') => {
  const blocksFromHtml = htmlToDraft(html);
  const { contentBlocks, entityMap } = blocksFromHtml;
  const contentState = ContentState.createFromBlockArray(contentBlocks, entityMap);
  return EditorState.createWithContent(contentState);
}

class EditorVan extends Component {

  state = {
    editorState: ''
  }

  onEditorStateChange = (editorState) => {
    this.setState({
      editorState
    })
    this.props.transformHTML( transformDraftStateToHtml(editorState) )
  };

  componentDidMount() {
    this.setState({
      editorState: transformHtmlToDraftState(this.props.editorState)
    })
  };

  uploadImageCallBack = (file) => {
    return new Promise((resolve, reject) => {
      (async() => {
        const base64 = await getBase64(file);
        const data = {
            base64: base64.split(',')[1],
            fileName: file.name,
            fileCode: 'material',
        }
        const res = await UploadBase64(data);
        if(res && res.data) {
          resolve({
            data: {
              link: `${IMG_URL}${res.data}`,
            },
          });
        } else {
          reject();
        }
      })();
    })
  }

  render() {
    return (
      <Editor
        editorState={this.state.editorState}
        onEditorStateChange={this.onEditorStateChange} 
        toolbar={{
          image: {
            uploadCallback: this.uploadImageCallBack,
            alt: { present: true, previewImage: true },
            previewImage: true,
          },
        }}
      />
    )
  }
};

export default EditorVan;

function getBase64(img, callback) {
  return new Promise((res, rej) => {
      const reader = new FileReader();
      reader.addEventListener('load', () => res(reader.result));
      reader.readAsDataURL(img);
  })
}

  该组件使用也十分方便,代码如下

<EditorVan editorState={this.state.editorState} transformHTML={(editorState) => this.setState({ editorState })} />

  

相关文章: