目錄
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;