Draftjs 如何使用内容启动编辑器

IT技术 reactjs draftjs
2021-04-08 05:09:54

偶然发现了 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()})
   }
});

当我运行它时,它会引发错误并显示以下消息“未捕获的类型错误:contentState.getBlockMap 不是函数”。

6个回答

EditorState.createWithContent的第一个参数是一个ContentState,而不是一个字符串。您需要导入ContentState

var EditorState = Draft.EditorState;
var ContentState = Draft.ContentState;

使用ContentState.createFromText并将结果传递给EditorState.createWithContent

return {
  editorState: EditorState.createWithContent(ContentState.createFromText('Hello'))
};

我为 DraftJS 创建了一组包来帮助导入和导出内容 (HTML/Markdown)。我在我的项目react-rte 中使用这些您可能正在寻找的是:npm 上的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)
    };
  }
});

我发布的module是:

太好了。docs/repo 页面中未提及使用 createWithContent 初始化编辑器
2021-06-04 05:09:54
stateFromHTML() 非常棒,因为它可以处理像 <p> 和 <strong> 这样的 html 标签,但是,如果我将带有 <sub> 或 <sup> 标签的字符串传递给它,它会丢弃它们。任何解决方法?
2021-06-11 05:09:54
很抱歉,我没有很好的解决方法,除非重写解析器以处理更多情况。老实说,我创建的整套工具(上面列出了)已经非常过时了,并且不再真正维护了。
2021-06-17 05:09:54

您可以使用convertFromHTML导入 htmlcreateWithContent

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)
}

如 Draft 的convertFromHtml 示例所示请注意,该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 提供了convertFromRawconvertFromHTML实用功能。

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}
      />
    )
  }
}
稍微说一下 - 我很困惑在使用 convertFromRaw() 导入时如何使用 data {} 对象 - 有没有用例的例子?
2021-05-25 05:09:54

当您需要使用纯文本启动编辑器时。

用途EditorState.createWithContentContentState.createFromText方法。工作示例 - https://jsfiddle.net/levsha/3m5780jc/

constructor(props) {
  super(props);

  const initialContent = 'Some text';
  const editorState = EditorState.createWithContent(ContentState.createFromText(initialContent));

  this.state = {
    editorState
  };
}

当您需要使用 html 标记字符串中的内容启动编辑器时。

使用convertFromHTMLContentState.createFromBlockArray工作示例 - 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数组new ContentBlock(...),并将其传递给ContentState.createFromBlockArray方法。工作示例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 结构的内容启动编辑器时

如果您之前将内容状态保存为原始 JS 结构convertToRaw(阅读此答案了解详细信息)。您可以使用convertFromRaw方法启动编辑器工作示例 - https://jsfiddle.net/levsha/tutc419a/

constructor(props) {
  super(props);

  this.state = {
    editorState: EditorState.createWithContent(convertFromRaw(JSON.parse(editorStateAsJSON)))
  };
}