一、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'
- 创建
RichTextEditor
富文本编辑组件,定义初始化的 state
,editorState
为创建一个没有内容的编辑对象,默认为 EditorState.createEmpty()
,代码如下所示:
state = {
editorState: EditorState.createEmpty(),
}
- 在
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)
})
}
)
}
- 在
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 } },
}}
/>
)
}
- 在
addUpdate
组件中去使用富文本编辑组件 RichTextEditor
,会涉及到组件传值。子组件调用父组件的方法是将父组件的方法以函数属性的形式传递给子组件, 子组件就可以调用。父组件调用子组件的方法是在父组件中通过 ref
得到子组件标签对象(也就是组件对象), 调用其方法。所以,我们就可以通过 ref
去实现组件传值。首先,创建 ref
容器,在 constructor
中,通过 React.createRef()
进行创建用来保存 ref
标识的标签对象的容器,代码如下所示:
constructor (props) {
super(props)
this.pw = React.createRef()
this.editor = React.createRef()
}
- 然后,在
addUpdate
组件中,将 ref
容器交给需要获取的标签元素,进行使用,代码如下所示:
<Item label="商品详情" labelCol={{span: 2}} wrapperCol={{span: 20}}>
<RichTextEditor ref={this.editor} detail={detail}></RichTextEditor>
</Item>
- 最后,通过
ref
容器读取标签元素。在表单提交的时候,去进行读取,代码如下所示:
const detail = this.editor.current.getDetail()
- 在
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 实现富文本编辑的实现
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 } },
}}
/>
)
}
}