对于 React 结合 Antd 实现富文本编辑功能

一、React 结合 Antd 实现富文本编辑
  1. 引入所需相关的组件和文件,代码如下所示:
import React, { Component } from 'react'
import PropTypes from 'prop-types'
import {EditorState, convertToRaw, ContentState} from 'draft-js'
import {Editor} from 'react-draft-wysiwyg'
import draftToHtml from 'draftjs-to-html'
import htmlToDraft from 'html-to-draftjs'
import 'react-draft-wysiwyg/dist/react-draft-wysiwyg.css'
  1. 创建 RichTextEditor 富文本编辑组件,定义初始化的 stateeditorState 为创建一个没有内容的编辑对象,默认为 EditorState.createEmpty(),代码如下所示:
state = {
    editorState: EditorState.createEmpty(), 
 }
  1. RichTextEditor 组件中,创建三个方法,onEditorStateChange 是输入过程中实时的回调,通过 setState 设置 editorState,当前富文本编辑的对象。getDetail 是返回输入数据对应的 html 格式的文本。uploadImageCallBack 是点击上传图片,代码如下所示:
  onEditorStateChange = (editorState) => {
    this.setState({ editorState })
  }

  getDetail = () => {
    return draftToHtml(convertToRaw(this.state.editorState.getCurrentContent()))
  }

  uploadImageCallBack = (file) => {
    return new Promise(
      (resolve, reject) => {
        const xhr = new XMLHttpRequest()
        xhr.open('POST', '/manage/img/upload')
        const data = new FormData()
        data.append('image', file)
        xhr.send(data)
        xhr.addEventListener('load', () => {
          const response = JSON.parse(xhr.responseText)
          const url = response.data.url 
          resolve({data: {link: url}})
        })
        xhr.addEventListener('error', () => {
          const error = JSON.parse(xhr.responseText)
          reject(error)
        })
      }
    )
  }
  1. render 中,通过 this.state 获取 editorState 编辑对象。通过使用 Editor 去实现富文本编辑的显示,代码如下所示:
render () {
    const { editorState } = this.state
    return (
      <Editor
        editorState={editorState}
        editorStyle={{border: '1px solid black', minHeight: 200, paddingLeft: 10}}
        onEditorStateChange={this.onEditorStateChange}
        toolbar={{
          image: { uploadCallback: this.uploadImageCallBack, alt: { present: true, mandatory: true } },
        }}
      />
    )
  }
  1. addUpdate 组件中去使用富文本编辑组件 RichTextEditor,会涉及到组件传值。子组件调用父组件的方法是将父组件的方法以函数属性的形式传递给子组件, 子组件就可以调用。父组件调用子组件的方法是在父组件中通过 ref 得到子组件标签对象(也就是组件对象), 调用其方法。所以,我们就可以通过 ref 去实现组件传值。首先,创建 ref 容器,在 constructor 中,通过 React.createRef() 进行创建用来保存 ref 标识的标签对象的容器,代码如下所示:
constructor (props) {
    super(props)
    this.pw = React.createRef()
    this.editor = React.createRef()
 }
  1. 然后,在 addUpdate 组件中,将 ref 容器交给需要获取的标签元素,进行使用,代码如下所示:
<Item label="商品详情" labelCol={{span: 2}} wrapperCol={{span: 20}}>
    <RichTextEditor ref={this.editor} detail={detail}></RichTextEditor>
</Item>
  1. 最后,通过 ref 容器读取标签元素。在表单提交的时候,去进行读取,代码如下所示:
 const detail = this.editor.current.getDetail()
  1. RichTextEditor 组件中,通过 prop-types 中的 PropTypes 进行检测由父组件传入的 detail 的数据,由 PropTypes.string 判断传入 detail 必须字符串类型。在 constructor 中,通过 this.props 获取传入的 detail 数据。如果有值, 根据 html格式字符串创建一个对应的编辑对象。反之,则创建一个没有内容的编辑对象,代码如下所示:
static propTypes = {
    detail: PropTypes.string
 }
 
 constructor (props) {
    super(props)
    const html = this.props.detail
    if (html) {
      const contentBlock = htmlToDraft(html)
      const contentState = ContentState.createFromBlockArray(contentBlock.contentBlocks)
      const editorState = EditorState.createWithContent(contentState)
      this.state = {
        editorState,
      }
    } else {
      this.state = {
        editorState: EditorState.createEmpty()
      }
    }
  }
二、React 结合 Antd 实现富文本编辑的实现
  1. React 结合 Antd 实现富文本编辑的实现,完整代码如下所示:
import React, { Component } from 'react'
import PropTypes from 'prop-types'
import {EditorState, convertToRaw, ContentState} from 'draft-js'
import {Editor} from 'react-draft-wysiwyg'
import draftToHtml from 'draftjs-to-html'
import htmlToDraft from 'html-to-draftjs'
import 'react-draft-wysiwyg/dist/react-draft-wysiwyg.css'

export default class RichTextEditor extends Component {

  static propTypes = {
    detail: PropTypes.string
  }

  state = {
    editorState: EditorState.createEmpty(), 
  }

  constructor (props) {
    super(props)
    const html = this.props.detail
    if (html) {
      const contentBlock = htmlToDraft(html)
      const contentState = ContentState.createFromBlockArray(contentBlock.contentBlocks)
      const editorState = EditorState.createWithContent(contentState)
      this.state = {
        editorState,
      }
    } else {
      this.state = {
        editorState: EditorState.createEmpty()
      }
    }
  }

  onEditorStateChange = (editorState) => {
    this.setState({ editorState })
  }

  getDetail = () => {
    return draftToHtml(convertToRaw(this.state.editorState.getCurrentContent()))
  }

  uploadImageCallBack = (file) => {
    return new Promise(
      (resolve, reject) => {
        const xhr = new XMLHttpRequest()
        xhr.open('POST', '/manage/img/upload')
        const data = new FormData()
        data.append('image', file)
        xhr.send(data)
        xhr.addEventListener('load', () => {
          const response = JSON.parse(xhr.responseText)
          const url = response.data.url 
          resolve({data: {link: url}})
        })
        xhr.addEventListener('error', () => {
          const error = JSON.parse(xhr.responseText)
          reject(error)
        })
      }
    )
  }

  render () {
    const { editorState } = this.state
    return (
      <Editor
        editorState={editorState}
        editorStyle={{border: '1px solid black', minHeight: 200, paddingLeft: 10}}
        onEditorStateChange={this.onEditorStateChange}
        toolbar={{
          image: { uploadCallback: this.uploadImageCallBack, alt: { present: true, mandatory: true } },
        }}
      />
    )
  }
}

你可能感兴趣的:(React,React,Antd,实现富文本编辑功能)