draftjs 如何启动带有内容的编辑器
draftjs how to initiate an editor with content
Facebook 偶然发现了这个很酷的文本编辑器,draft.js。
我尝试按照 Github 中的示例进行操作,但我想创建一个包含内容的编辑器而不是一个空的编辑器。
var EditorState = Draft.EditorState;
var RichEditor = React.createClass({
getInitialState(){
return {editorState: EditorState.createWithContent("Hello")}
//the example use this code to createEmpty editor
// return ({editorState: EditorState.createEmpty()})
}
});
当我 运行 它时,它会抛出错误消息“Uncaught TypeError: contentState.getBlockMap is not a function”。
EditorState.createWithContent is a ContentState
, not a string. You need to import ContentState
的第一个参数
var EditorState = Draft.EditorState;
var ContentState = Draft.ContentState;
使用ContentState.createFromText And pass the result to EditorState.createWithContent.
return {
editorState: EditorState.createWithContent(ContentState.createFromText('Hello'))
};
我已经为 DraftJS 创建了一组包来帮助导入和导出内容 (HTML/Markdown)。我在 npm 上的项目 react-rte. The one you're probably looking for is: draft-js-import-html 中使用这些。
npm install draft-js-import-html
您可以如何使用它的示例:
var stateFromHTML = require('draft-js-import-html').stateFromHTML;
var EditorState = Draft.EditorState;
var RichEditor = React.createClass({
getInitialState() {
let contentState = stateFromHTML('<p>Hello</p>');
return {
editorState: EditorState.createWithContent(contentState)
};
}
});
我发布的模块有:
我发现这是一种简洁的处理方式,具有丰富的功能。您可以在未来添加更多插件,将您的内容导出为 .md
等,而无需过多更改组件的结构。
import Draft from 'draft-js';
import DraftPasteProcessor from 'draft-js/lib/DraftPasteProcessor';
const { EditorState, ContentState } = Draft;
import Editor from 'draft-js-plugins-editor';
import createRichButtonsPlugin from 'draft-js-richbuttons-plugin';
const richButtonsPlugin = createRichButtonsPlugin();
class DescriptionForm extends React.Component {
state = {
editorState: this._getPlaceholder(),
}
_getPlaceholder() {
const placeholder = 'Write something here';
const contentHTML = DraftPasteProcessor.processHTML(placeholder);
const state = ContentState.createFromBlockArray(contentHTML);
return Draft.EditorState.createWithContent(state);
}
_onChange(editorState) {
this.setState({
editorState,
});
}
render () {
let { editorState } = this.state;
return (
<div>
<Editor
editorState={editorState}
onChange={this._onChange.bind(this)}
spellCheck={false}
plugins={[richButtonsPlugin, videoPlugin]}
/>
</div>
);
}
}
您可以使用 convertFromHTML
导入 html 和 createWithContent
import { convertFromHTML, ContentState } from 'draft-js'
const html = '<div><p>hello</p></div>'
const blocksFromHTML = convertFromHTML(html)
const content = ContentState.createFromBlockArray(blocksFromHTML)
this.state = {
editorState: EditorState.createWithContent(content)
}
如草稿convertFromHtml example所示。请注意,0.9.1
版本无法导入图像,而 0.10.0
可以。
在 0.10.0
createFromBlockArray
更改为:
const content = ContentState.createFromBlockArray(
blocksFromHTML.contentBlocks,
blocksFromHTML.entityMap
)
有一些 API 变化,为清楚起见,这些示例使用最新的 API,即 v0.10.0.
有很多方法,但基本上您有三种选择,具体取决于您是要对内容资源使用纯文本、样式文本还是 html 标记。
纯文本很明显,但对于样式文本,您需要使用序列化的 javasript 对象或 html 标记。
让我们从纯文本示例开始:
import {Editor, EditorState} from 'draft-js';
class MyEditor extends Component{
constructor(props) {
super(props);
const plainText = 'Lorem ipsum dolor sit amet, consectetuer adipiscing elit.';
const content = ContentState.createFromText(plainText);
this.state = { editorState: EditorState.createWithContent(content)};
this.onChange = (editorState) => {
this.setState({editorState});
}
}
render(){
return(
<Editor
editorState={this.state.editorState}
onChange={this.onChange}
/>
)
}
}
用于导入样式化内容Draft.js 提供convertFromRaw and convertFromHTML 实用函数。
convertFromRaw 函数将原始 javascript 对象作为参数。在这里,我们使用 JSON 字符串化 javascript 对象作为内容源:
class MyEditor extends Component{
constructor(props) {
super(props);
const rawJsText = `{
"entityMap": {},
"blocks": [
{
"key": "e4brl",
"text": "Lorem ipsum dolor sit amet, consectetuer adipiscing elit.",
"type": "unstyled",
"depth": 0,
"inlineStyleRanges": [
{
"offset": 0,
"length": 11,
"style": "BOLD"
},
{
"offset": 28,
"length": 29,
"style": "BOLD"
},
{
"offset": 12,
"length": 15,
"style": "ITALIC"
},
{
"offset": 28,
"length": 28,
"style": "ITALIC"
}
],
"entityRanges": [],
"data": {}
},
{
"key": "3bflg",
"text": "Aenean commodo ligula eget dolor.",
"type": "unstyled",
"depth": 0,
"inlineStyleRanges": [],
"entityRanges": [],
"data": {}
}
]
}`;
const content = convertFromRaw(JSON.parse(rawJsText));
this.state = { editorState: EditorState.createWithContent(content)};
this.onChange = (editorState) => {
this.setState({editorState});
}
}
render(){
return(
<Editor
editorState={this.state.editorState}
onChange={this.onChange}
/>
)
}
}
Draft.js 提供 convertToRaw 函数,以便您可以将编辑器的状态转换为原始 javascript 对象以进行长期存储。
最后,这里是如何使用 html 标记:
class MyEditor extends Component{
constructor(props) {
super(props);
const html = `<p>Lorem ipsum <b>dolor</b> sit amet, <i>consectetuer adipiscing elit.</i></p>
<p>Aenean commodo ligula eget dolor. <b><i>Aenean massa.</i></b></p>`;
const blocksFromHTML = convertFromHTML(html);
const content = ContentState.createFromBlockArray(
blocksFromHTML.contentBlocks,
blocksFromHTML.entityMap
);
this.state = { editorState: EditorState.createWithContent(content)};
this.onChange = (editorState) => {
this.setState({editorState});
}
}
render(){
return(
<Editor
editorState={this.state.editorState}
onChange={this.onChange}
/>
)
}
}
当您需要使用纯文本启动编辑器时。
使用EditorState.createWithContent
and ContentState.createFromText
methods. Working example - https://jsfiddle.net/levsha/3m5780jc/
constructor(props) {
super(props);
const initialContent = 'Some text';
const editorState = EditorState.createWithContent(ContentState.createFromText(initialContent));
this.state = {
editorState
};
}
当您需要使用 html 标记字符串中的内容启动编辑器时。
使用convertFromHTML
and ContentState.createFromBlockArray
. Working example - https://jsfiddle.net/levsha/8aj4hjwh/
constructor(props) {
super(props);
const sampleMarkup = `
<div>
<h2>Title</h2>
<i>some text</i>
</div>
`;
const blocksFromHTML = convertFromHTML(sampleMarkup);
const state = ContentState.createFromBlockArray(
blocksFromHTML.contentBlocks,
blocksFromHTML.entityMap
);
this.state = {
editorState: EditorState.createWithContent(state),
};
}
当你有一个字符串数组并且你想用一些默认的 draft.js 块类型启动一个编辑器时。
您可以创建 ContentBlocks
s with constructor new ContentBlock(...)
, and pass it to ContentState.createFromBlockArray
method. Working example with unordered-list-item
- https://jsfiddle.net/levsha/uy04se6r/
的数组
constructor(props) {
super(props);
const input = ['foo', 'bar', 'baz'];
const contentBlocksArray = input.map(word => {
return new ContentBlock({
key: genKey(),
type: 'unordered-list-item',
characterList: new List(Repeat(CharacterMetadata.create(), word.length)),
text: word
});
});
this.state = {
editorState: EditorState.createWithContent(ContentState.createFromBlockArray(contentBlocksArray))
};
}
当您需要使用来自 ContentState
原始 JS 结构的内容启动编辑器时。
如果您之前使用 convertToRaw
(read for details). You can initiate an editor with convertFromRaw
method. Working example - https://jsfiddle.net/levsha/tutc419a/
将内容状态保存到原始 JS 结构
constructor(props) {
super(props);
this.state = {
editorState: EditorState.createWithContent(convertFromRaw(JSON.parse(editorStateAsJSON)))
};
}
如果您想使用 HTML 格式
设置,只需添加以下代码即可将初始值设置为您的 edtitorState
this.state = {
editorState: EditorState.createWithContent(
ContentState.createFromBlockArray(
convertFromHTML('<p>My initial content.</p>')
)
),
}
在 simple 中,您可以从初始阶段或随时使用 setState
将原始 HTML 内容设置为编辑器,如下所示。
editorState: EditorState.createWithContent(ContentState.createFromBlockArray(convertFromHTML('<b>Program</b>')))
导入必要的组件。
import { EditorState, ContentState, convertFromHTML } from 'draft-js'
对于 Nextjs
import React, { Component } from 'react';
import { EditorState, convertToRaw, ContentState, convertFromHTML } from 'draft-
js';
import draftToHtml from 'draftjs-to-html';
import dynamic from 'next/dynamic';
import "react-draft-wysiwyg/dist/react-draft-wysiwyg.css";
const Editor = dynamic(
() => import('react-draft-wysiwyg').then(mod => mod.Editor),
{ ssr: false }
)
let htmlToDraft = null;
if (typeof window === 'object') {
htmlToDraft = require('html-to-draftjs').default;
}
export default class EditorConvertToHTML extends Component {
constructor(props) {
super(props);
this.state = {
editorState: EditorState.createEmpty(),
contentState: ""
}
}
componentDidMount() {
const html = '<p>Hey this <strong>editor</strong> rocks d</p>';
const contentBlock = htmlToDraft(html);
console.log(contentBlock)
if (contentBlock) {
const contentState =
ContentState.createFromBlockArray(contentBlock.contentBlocks);
const editorState = EditorState.createWithContent(contentState);
console.log(editorState)
this.setState(
{
editorState: EditorState.createWithContent(
ContentState.createFromBlockArray(
convertFromHTML(html)
)
)
}
)
}
}
onEditorStateChange = (editorState) => {
this.setState({
editorState,
});
};
render() {
const { editorState } = this.state;
console.log(this.state.editorState.getCurrentContent())
return (
<div>
<Editor
editorState={editorState}
wrapperClassName="demo-wrapper"
editorClassName="demo-editor"
onEditorStateChange={this.onEditorStateChange}
/>
<textarea
disabled
value=
{draftToHtml(convertToRaw(editorState.getCurrentContent()))}
/>
</div>
);
}
}
Facebook 偶然发现了这个很酷的文本编辑器,draft.js。 我尝试按照 Github 中的示例进行操作,但我想创建一个包含内容的编辑器而不是一个空的编辑器。
var EditorState = Draft.EditorState;
var RichEditor = React.createClass({
getInitialState(){
return {editorState: EditorState.createWithContent("Hello")}
//the example use this code to createEmpty editor
// return ({editorState: EditorState.createEmpty()})
}
});
当我 运行 它时,它会抛出错误消息“Uncaught TypeError: contentState.getBlockMap is not a function”。
EditorState.createWithContent is a ContentState
, not a string. You need to import ContentState
var EditorState = Draft.EditorState;
var ContentState = Draft.ContentState;
使用ContentState.createFromText And pass the result to EditorState.createWithContent.
return {
editorState: EditorState.createWithContent(ContentState.createFromText('Hello'))
};
我已经为 DraftJS 创建了一组包来帮助导入和导出内容 (HTML/Markdown)。我在 npm 上的项目 react-rte. The one you're probably looking for is: draft-js-import-html 中使用这些。
npm install draft-js-import-html
您可以如何使用它的示例:
var stateFromHTML = require('draft-js-import-html').stateFromHTML;
var EditorState = Draft.EditorState;
var RichEditor = React.createClass({
getInitialState() {
let contentState = stateFromHTML('<p>Hello</p>');
return {
editorState: EditorState.createWithContent(contentState)
};
}
});
我发布的模块有:
我发现这是一种简洁的处理方式,具有丰富的功能。您可以在未来添加更多插件,将您的内容导出为 .md
等,而无需过多更改组件的结构。
import Draft from 'draft-js';
import DraftPasteProcessor from 'draft-js/lib/DraftPasteProcessor';
const { EditorState, ContentState } = Draft;
import Editor from 'draft-js-plugins-editor';
import createRichButtonsPlugin from 'draft-js-richbuttons-plugin';
const richButtonsPlugin = createRichButtonsPlugin();
class DescriptionForm extends React.Component {
state = {
editorState: this._getPlaceholder(),
}
_getPlaceholder() {
const placeholder = 'Write something here';
const contentHTML = DraftPasteProcessor.processHTML(placeholder);
const state = ContentState.createFromBlockArray(contentHTML);
return Draft.EditorState.createWithContent(state);
}
_onChange(editorState) {
this.setState({
editorState,
});
}
render () {
let { editorState } = this.state;
return (
<div>
<Editor
editorState={editorState}
onChange={this._onChange.bind(this)}
spellCheck={false}
plugins={[richButtonsPlugin, videoPlugin]}
/>
</div>
);
}
}
您可以使用 convertFromHTML
导入 html 和 createWithContent
import { convertFromHTML, ContentState } from 'draft-js'
const html = '<div><p>hello</p></div>'
const blocksFromHTML = convertFromHTML(html)
const content = ContentState.createFromBlockArray(blocksFromHTML)
this.state = {
editorState: EditorState.createWithContent(content)
}
如草稿convertFromHtml example所示。请注意,0.9.1
版本无法导入图像,而 0.10.0
可以。
在 0.10.0
createFromBlockArray
更改为:
const content = ContentState.createFromBlockArray(
blocksFromHTML.contentBlocks,
blocksFromHTML.entityMap
)
有一些 API 变化,为清楚起见,这些示例使用最新的 API,即 v0.10.0.
有很多方法,但基本上您有三种选择,具体取决于您是要对内容资源使用纯文本、样式文本还是 html 标记。
纯文本很明显,但对于样式文本,您需要使用序列化的 javasript 对象或 html 标记。
让我们从纯文本示例开始:
import {Editor, EditorState} from 'draft-js';
class MyEditor extends Component{
constructor(props) {
super(props);
const plainText = 'Lorem ipsum dolor sit amet, consectetuer adipiscing elit.';
const content = ContentState.createFromText(plainText);
this.state = { editorState: EditorState.createWithContent(content)};
this.onChange = (editorState) => {
this.setState({editorState});
}
}
render(){
return(
<Editor
editorState={this.state.editorState}
onChange={this.onChange}
/>
)
}
}
用于导入样式化内容Draft.js 提供convertFromRaw and convertFromHTML 实用函数。
convertFromRaw 函数将原始 javascript 对象作为参数。在这里,我们使用 JSON 字符串化 javascript 对象作为内容源:
class MyEditor extends Component{
constructor(props) {
super(props);
const rawJsText = `{
"entityMap": {},
"blocks": [
{
"key": "e4brl",
"text": "Lorem ipsum dolor sit amet, consectetuer adipiscing elit.",
"type": "unstyled",
"depth": 0,
"inlineStyleRanges": [
{
"offset": 0,
"length": 11,
"style": "BOLD"
},
{
"offset": 28,
"length": 29,
"style": "BOLD"
},
{
"offset": 12,
"length": 15,
"style": "ITALIC"
},
{
"offset": 28,
"length": 28,
"style": "ITALIC"
}
],
"entityRanges": [],
"data": {}
},
{
"key": "3bflg",
"text": "Aenean commodo ligula eget dolor.",
"type": "unstyled",
"depth": 0,
"inlineStyleRanges": [],
"entityRanges": [],
"data": {}
}
]
}`;
const content = convertFromRaw(JSON.parse(rawJsText));
this.state = { editorState: EditorState.createWithContent(content)};
this.onChange = (editorState) => {
this.setState({editorState});
}
}
render(){
return(
<Editor
editorState={this.state.editorState}
onChange={this.onChange}
/>
)
}
}
Draft.js 提供 convertToRaw 函数,以便您可以将编辑器的状态转换为原始 javascript 对象以进行长期存储。
最后,这里是如何使用 html 标记:
class MyEditor extends Component{
constructor(props) {
super(props);
const html = `<p>Lorem ipsum <b>dolor</b> sit amet, <i>consectetuer adipiscing elit.</i></p>
<p>Aenean commodo ligula eget dolor. <b><i>Aenean massa.</i></b></p>`;
const blocksFromHTML = convertFromHTML(html);
const content = ContentState.createFromBlockArray(
blocksFromHTML.contentBlocks,
blocksFromHTML.entityMap
);
this.state = { editorState: EditorState.createWithContent(content)};
this.onChange = (editorState) => {
this.setState({editorState});
}
}
render(){
return(
<Editor
editorState={this.state.editorState}
onChange={this.onChange}
/>
)
}
}
当您需要使用纯文本启动编辑器时。
使用EditorState.createWithContent
and ContentState.createFromText
methods. Working example - https://jsfiddle.net/levsha/3m5780jc/
constructor(props) {
super(props);
const initialContent = 'Some text';
const editorState = EditorState.createWithContent(ContentState.createFromText(initialContent));
this.state = {
editorState
};
}
当您需要使用 html 标记字符串中的内容启动编辑器时。
使用convertFromHTML
and ContentState.createFromBlockArray
. Working example - https://jsfiddle.net/levsha/8aj4hjwh/
constructor(props) {
super(props);
const sampleMarkup = `
<div>
<h2>Title</h2>
<i>some text</i>
</div>
`;
const blocksFromHTML = convertFromHTML(sampleMarkup);
const state = ContentState.createFromBlockArray(
blocksFromHTML.contentBlocks,
blocksFromHTML.entityMap
);
this.state = {
editorState: EditorState.createWithContent(state),
};
}
当你有一个字符串数组并且你想用一些默认的 draft.js 块类型启动一个编辑器时。
您可以创建 ContentBlocks
s with constructor new ContentBlock(...)
, and pass it to ContentState.createFromBlockArray
method. Working example with unordered-list-item
- https://jsfiddle.net/levsha/uy04se6r/
constructor(props) {
super(props);
const input = ['foo', 'bar', 'baz'];
const contentBlocksArray = input.map(word => {
return new ContentBlock({
key: genKey(),
type: 'unordered-list-item',
characterList: new List(Repeat(CharacterMetadata.create(), word.length)),
text: word
});
});
this.state = {
editorState: EditorState.createWithContent(ContentState.createFromBlockArray(contentBlocksArray))
};
}
当您需要使用来自 ContentState
原始 JS 结构的内容启动编辑器时。
如果您之前使用 convertToRaw
(read convertFromRaw
method. Working example - https://jsfiddle.net/levsha/tutc419a/
constructor(props) {
super(props);
this.state = {
editorState: EditorState.createWithContent(convertFromRaw(JSON.parse(editorStateAsJSON)))
};
}
如果您想使用 HTML 格式
设置,只需添加以下代码即可将初始值设置为您的 edtitorStatethis.state = {
editorState: EditorState.createWithContent(
ContentState.createFromBlockArray(
convertFromHTML('<p>My initial content.</p>')
)
),
}
在 simple 中,您可以从初始阶段或随时使用 setState
将原始 HTML 内容设置为编辑器,如下所示。
editorState: EditorState.createWithContent(ContentState.createFromBlockArray(convertFromHTML('<b>Program</b>')))
导入必要的组件。
import { EditorState, ContentState, convertFromHTML } from 'draft-js'
对于 Nextjs
import React, { Component } from 'react';
import { EditorState, convertToRaw, ContentState, convertFromHTML } from 'draft-
js';
import draftToHtml from 'draftjs-to-html';
import dynamic from 'next/dynamic';
import "react-draft-wysiwyg/dist/react-draft-wysiwyg.css";
const Editor = dynamic(
() => import('react-draft-wysiwyg').then(mod => mod.Editor),
{ ssr: false }
)
let htmlToDraft = null;
if (typeof window === 'object') {
htmlToDraft = require('html-to-draftjs').default;
}
export default class EditorConvertToHTML extends Component {
constructor(props) {
super(props);
this.state = {
editorState: EditorState.createEmpty(),
contentState: ""
}
}
componentDidMount() {
const html = '<p>Hey this <strong>editor</strong> rocks d</p>';
const contentBlock = htmlToDraft(html);
console.log(contentBlock)
if (contentBlock) {
const contentState =
ContentState.createFromBlockArray(contentBlock.contentBlocks);
const editorState = EditorState.createWithContent(contentState);
console.log(editorState)
this.setState(
{
editorState: EditorState.createWithContent(
ContentState.createFromBlockArray(
convertFromHTML(html)
)
)
}
)
}
}
onEditorStateChange = (editorState) => {
this.setState({
editorState,
});
};
render() {
const { editorState } = this.state;
console.log(this.state.editorState.getCurrentContent())
return (
<div>
<Editor
editorState={editorState}
wrapperClassName="demo-wrapper"
editorClassName="demo-editor"
onEditorStateChange={this.onEditorStateChange}
/>
<textarea
disabled
value=
{draftToHtml(convertToRaw(editorState.getCurrentContent()))}
/>
</div>
);
}
}