react-draft-wysiwyg富文本组件
2018-09-03 本文已影响0人
Ann_l
目录
react-draft-wysiwyg富文本组件
组件使用背景
ant design 、react、dva、react-draft-wysiwyg
组件使用中遇到的问题
当嵌套组件中使用 react-draft-wysiwyg 的 editor 组件时,当我首次进入编辑页面,id=1的文章时,内容应该显示id=1的内容。返回列表页面,重新进入id=2的文章时,react-draft-wysiwyg 的 editor 组件会保留id=1的文章内容。当我返回列表页面,重新进入id=3的文章时,react-draft-wysiwyg 的 editor 组件会保留id=2的文章内容。
实现富文本组件合理使用有2个方案
1、将 react-draft-wysiwyg的editor直接使用,不要嵌套于其他组件内。
2、如果您将 react-draft-wysiwyg的editor 已经嵌套于其他组件,建议您自行实现该组件内容的实现双向绑定。
1、直接使用editor 范例
// 层级关系(我项目中实现是嵌套组件)
- EditBlogPage.jsx (当前编辑页)
- UpdateBlogForm
- EditorConvertToHTML
- Editor
render() {
const { blog } = this.props;
const itemBlog = blog.get('itemBlog').toJS();
const blogBodyEditor = blog.get('blogBodyEditor');
const contentBlock = htmlToDraft(itemBlog.body);
const contentState = ContentState.createFromBlockArray(contentBlock.contentBlocks);
const editorState = EditorState.createWithContent(contentState);
return (
<Layout>
<Layout.Content>
<Row>
<Card>
// 使用 UpdateBlogForm 组件
<UpdateBlogForm
optType="edit"
blogBodyEditor={blogBodyEditor}
itemBlog={itemBlog}
handleUpdate={this.handleUpdate} />
// 使用 EditorConvertToHTML 组件
<EditorConvertToHTML
body={itemBlog.body} />
// 直接使用 react-draft-wysiwyg 的 editor
<Editor
editorState={editorState}
toolbar={{
options: ['blockType'],
blockType: {
inDropdown: false,
className: 'bordered-option-classname',
options: ['Normal', 'H1', 'H2', 'H3', 'H4', 'H5'],
},
}} />
</Card>
</Row>
</Layout.Content>
</Layout>
);
}
组件使用对比图.png
从上图可以看出,当你直接使用editor 没毛病,完全可以实现您的需求。
2、嵌套组件内使用editor
思路:将传给editor的EditorState 存在state中,就像给input实现双向绑定。
// EditorConvertToHTML 组件
import React, { Component, PropTypes } from 'react';
import { Editor } from 'react-draft-wysiwyg';
import { EditorState, convertToRaw } from 'draft-js';
import draftToHtml from 'draftjs-to-html';
import './editor-to-html.scss';
class EditorConvertToHTML extends Component {
static propTypes = {
// 同时在将 EditorState 传入渲染使用
blogBodyEditor: PropTypes.instanceOf(EditorState),
changeBody: PropTypes.func,
}
constructor(props) {
super(props);
if (props.blogBodyEditor) {
this.state = {
editorState: props.blogBodyEditor,
};
} else {
this.state = {
editorState: EditorState.createEmpty(),
};
}
this.onEditorStateChange = this.onEditorStateChange.bind(this);
}
componentWillReceiveProps(nextProps) {
if (nextProps.blogBodyEditor) {
this.setState({
editorState: nextProps.blogBodyEditor,
});
}
}
onEditorStateChange(editorState) {
this.setState({
editorState,
});
// 关键代码:将更改的 editorState 存入state
this.props.changeBody(editorState, draftToHtml(convertToRaw(editorState.getCurrentContent())));
}
render() {
const { editorState } = this.state;
return (
<Editor
editorState={editorState}
onEditorStateChange={this.onEditorStateChange}
toolbar={{
options: ['blockType'],
blockType: {
inDropdown: false,
className: 'bordered-option-classname',
options: ['Normal', 'H1', 'H2', 'H3', 'H4', 'H5'],
},
}} />
);
}
}
export default EditorConvertToHTML;