0

我使用了 draft-js-export-html npm 并将 html 保存到我的数据库中,如下所述。

我点击了这个链接并使用 npm draft-js-import将 html 导入到带有 draftjs 的编辑器内容。如果我的 html 不包含任何图像,我可以使用 html 初始化内容,但如果它包含<img>标签,我将无法导入 html。

import React, { Component } from 'react';
import Relay from 'react-relay';
import {Editor, EditorState, RichUtils,DefaultDraftBlockRenderMap,convertToRaw,convertFromRaw} from 'draft-js';
import CreatePostMutation from "../mutations/CreatePostMutation";
import { disconnectAccount, connectAccount, postUpload } from '../serverRequests';
import {stateToHTML} from 'draft-js-export-html';
//text editor's code start
// Custom overrides for "code" style.
const styleMap = {
  CODE: {
    backgroundColor: 'rgba(0, 0, 0, 0.05)',
    fontFamily: '"Inconsolata", "Menlo", "Consolas", monospace',
    fontSize: 16,
    padding: 2,
  },
};

function getBlockStyle(block) {
  switch (block.getType()) {
    case 'blockquote': return 'RichEditor-blockquote';
    default: return null;
  }
}

class StyleButton extends React.Component {
  constructor() {
    super();
    this.onToggle = (e) => {
      e.preventDefault();
      this.props.onToggle(this.props.style);
    };
  }

  render() {
    let className = 'RichEditor-styleButton';
    if (this.props.active) {
      className += ' RichEditor-activeButton';
    }

    return (
      <span className={className} onMouseDown={this.onToggle}>
        {this.props.label}
      </span>
    );
  }
}

const BLOCK_TYPES = [
  {label: 'H1', style: 'header-one'},
  {label: 'H2', style: 'header-two'},
  {label: 'H3', style: 'header-three'},
  {label: 'H4', style: 'header-four'},
  {label: 'H5', style: 'header-five'},
  {label: 'H6', style: 'header-six'},
  {label: 'Blockquote', style: 'blockquote'},
  {label: 'UL', style: 'unordered-list-item'},
  {label: 'OL', style: 'ordered-list-item'},
  {label: 'Code Block', style: 'code-block'},
];

const BlockStyleControls = (props) => {
  const {editorState} = props;
  const selection = editorState.getSelection();
  const blockType = editorState
    .getCurrentContent()
    .getBlockForKey(selection.getStartKey())
    .getType();

  return (
    <div className="RichEditor-controls">
      {BLOCK_TYPES.map((type) =>
        <StyleButton
          key={type.label}
          active={type.style === blockType}
          label={type.label}
          onToggle={props.onToggle}
          style={type.style}
        />
      )}
    </div>
  );
};

var INLINE_STYLES = [
  {label: 'Bold', style: 'BOLD'},
  {label: 'Italic', style: 'ITALIC'},
  {label: 'Underline', style: 'UNDERLINE'},
  {label: 'Monospace', style: 'CODE'},
];

const InlineStyleControls = (props) => {
  var currentStyle = props.editorState.getCurrentInlineStyle();
  return (
    <div className="RichEditor-controls">
      {INLINE_STYLES.map(type =>
        <StyleButton
          key={type.label}
          active={currentStyle.has(type.style)}
          label={type.label}
          onToggle={props.onToggle}
          style={type.style}
        />
      )}
    </div>
  );
};
//text editor's code ends

class BlogForm extends Component {
  constructor(props) {
    super(props);

    let contentState = stateFromHTML(props.post.content);
     this.state = {
       editorState: EditorState.createWithContent(contentState),
     };
    this.focus = () => this.refs.editor.focus();
    this.onChange = (editorState) => this.setState({editorState});
    console.log(editorState)
    this.handleKeyCommand = (command) => this._handleKeyCommand(command);
    this.toggleBlockType = (type) => this._toggleBlockType(type);
    this.toggleInlineStyle = (style) => this._toggleInlineStyle(style);
  }

  _handleKeyCommand(command) {
    const {editorState} = this.state;
    const newState = RichUtils.handleKeyCommand(editorState, command);
    if (newState) {
      this.onChange(newState);
      return true;
    }
    return false;
  }

  _toggleBlockType(blockType) {
    this.onChange(
      RichUtils.toggleBlockType(
        this.state.editorState,
        blockType
      )
    );
  }

  _toggleInlineStyle(inlineStyle) {
    this.onChange(
      RichUtils.toggleInlineStyle(
        this.state.editorState,
        inlineStyle
      )
    );
  }
  handleSubmit = (e) => {
    let html = stateToHTML(this.state.editorState.getCurrentContent());
    e.preventDefault();
    console.dir(this.state.editorState)
    Relay.Store.update(
      new CreatePostMutation({
        title: this.refs.newTitle.value,
        content: html,
        userid: this.props.user.userid
      }),
    );
    this.refs.newTitle.value = "";
  }
  render() {
    const {editorState} = this.state;
    console.log(editorState)
    // If the user changes block type before entering any text, we can
    // either style the placeholder or hide it. Let's just hide it now.
    let className = 'RichEditor-editor';
    var contentState = editorState.getCurrentContent();
    if (!contentState.hasText()) {
      if (contentState.getBlockMap().first().getType() !== 'unstyled') {
        className += ' RichEditor-hidePlaceholder';
      }
    }
    return (
      <div className="col-md-8 col-sm-8 col-xs-12">
        <form onSubmit={this.handleSubmit} className="postForm">
          <div className="form-group">
            <input className="form-control" type="text" required placeholder="Title" ref="newTitle" />
          </div>
          <div className="form-group">

            <div className="RichEditor-root">
              <BlockStyleControls
                editorState={editorState}
                onToggle={this.toggleBlockType}
                />
              <InlineStyleControls
                editorState={editorState}
                onToggle={this.toggleInlineStyle}
                />
              <div className={className} onClick={this.focus}>
                <Editor
                  blockStyleFn={getBlockStyle}
                  customStyleMap={styleMap}
                  editorState={editorState}
                  handleKeyCommand={this.handleKeyCommand}
                  onChange={this.onChange}
                  placeholder="Enter Content..."
                  ref="editor"
                  spellCheck={true}
                  />
              </div>
            </div>
          </div>
          <div className="form-group"> 
            <input type="file" name="avatar" ref="avatar" onChange={(e)=>this.handleImageSelect(e)} className="form-control padding upload-input" placeholder="Change image" />
          </div>
          <button className="btn btn-primary allbtn-btn" type="submit">Submit</button>
        </form>
      </div>
    )
  }
}
export default BlogForm

因为它正在产生错误

Uncaught Invariant Violation: Component(...): A valid React element (or null) must be returned. You may have returned undefined, an array or some other invalid object.

我也尝试了这个链接,也使用了 convertFromHtml但仍然无法用<img>标签初始化编辑器

提前致谢

4

2 回答 2

2

您不需要使用外部插件将 Draftjs 内容转换为 HTML,因为 Draft.js 提供了一个名为convertToRaw(用于导出数据)和convertFromRaw(用于导入数据)的函数。

于 2016-08-18T15:37:06.853 回答
1

您需要一个 blockRenderMap 和 blockRenderFn 来支持图像,因为 Draft-JS 不捆绑支持这些图像。查看draft-js-plugins,因为有一个(目前,2016 年 10 月 31 日,损坏的)图像插件,以及Draft-js-base-plugin上的我的图像插件示例。

于 2016-08-31T05:23:27.897 回答