react-rte/draft-js: blockRenderMap 不影响实际的编辑器状态

react-rte/draft-js: blockRenderMap not affecting the actual editor state

我正在使用 blockRenderMap 在编辑时提供小文本选项。默认 react-rte 不支持。这是执行此操作的代码:

import React, {Component} from 'react';
import RichTextEditor from 'react-rte';
import Immutable from 'immutable'
import Draft from 'draft-js'

const blockRenderMap = Immutable.Map({
    'small': {
      element: 'small'
    }
  });

// Include 'paragraph' as a valid block and updated the unstyled element but
// keep support for other draft default block types
const extendedBlockRenderMap = Draft.DefaultDraftBlockRenderMap.merge(blockRenderMap);

class MyStatefulEditor extends Component {

  state = {
    value: RichTextEditor.createEmptyValue()
  }

  onChange = (value) => {
    console.log(value.toString('html'))
    this.setState({value});
    if (this.props.onChange) {
      // Send the changes up to the parent component as an HTML string.
      // This is here to demonstrate using `.toString()` but in a real app it
      // would be better to avoid generating a string on each change.
      this.props.onChange(
        value.toString('html')
      );
    }
  };

  render () 
  { 
    const toolbarConfig = {
        // Optionally specify the groups to display (displayed in the order listed).
        display: ['INLINE_STYLE_BUTTONS', 'BLOCK_TYPE_BUTTONS', 'LINK_BUTTONS', 'BLOCK_TYPE_DROPDOWN', 'HISTORY_BUTTONS'],
        INLINE_STYLE_BUTTONS: [
          {label: 'Bold', style: 'BOLD', className: 'custom-css-class'},
          {label: 'Italic', style: 'ITALIC'},
          {label: 'Underline', style: 'UNDERLINE'}
        ],
        BLOCK_TYPE_DROPDOWN: [
          {label : 'Small', style: 'small'},
          {label: 'Normal', style: 'unstyled'},
          {label: 'Heading Large', style: 'header-one'},
          {label: 'Heading Medium', style: 'header-two'},
          {label: 'Heading Small', style: 'header-three'}
        ],
        BLOCK_TYPE_BUTTONS: [
          {label: 'UL', style: 'unordered-list-item'},
          {label: 'OL', style: 'ordered-list-item'}
        ]
      };
    return (  
      <RichTextEditor
        value={this.state.value}
        onChange={this.onChange}
        toolbarConfig={toolbarConfig}
        blockRenderMap={extendedBlockRenderMap}
      />
    );
  }

}

export default MyStatefulEditor;

使用编辑器时,效果很好

但是在 onChange 函数中,如果我打印包含 editorValue 的“value”变量,它显示如下:

<p>asdas</p>

而不是:

<small>asdas</small>

同时,如果我 select 默认支持的一种,比如大标题:

然后我在 onChange 中打印 value,我看到了这个:

<h1>asdas</h1>

为什么我的 blockRenderMap 不工作,而默认的工作?我怎样才能使 value 变量包含预期的 small 标签而不是 p 标签,对于它适用的情况?

这里有很多斗争

  1. react-rte不支持小字体,所以只好使用blockRenderMap指定新的映射,如Draft.js API (which react-rte allows to pass via props)
  2. 中所述
  3. blockRenderMap 还不够好。它仅在编辑模式下有效,因此该方法是解决方案的 50%(或 0,我不知道)。事实上 Draft.js(不要认为是 react-rte 这样做,但也找不到确切的草案代码)默认情况下将尚未映射的内容转换为 <p>。我真的希望 blockRenderMap 的扩展能够解决所有问题,但是没有。
  4. Draft.js 中定义的默认映射是限制性的:https://draftjs.org/docs/advanced-topics-custom-block-render-map/。一个古怪的想法是使用 <section> 作为样式,然后尝试对其应用 CSS class。但是默认情况下部分不可用。即使您将其指定为自定义 blockRenderMap,它也会将其转换为 value 变量中的 <p>。所以我最终修改了 <h4>.

解决方案是

编辑中:

  1. 指定自定义块样式:https://draftjs.org/docs/advanced-topics-block-styling/。在我的例子中,CSS class 用于小字体:
.rte-small-font {
  font-size: smaller;
  font-weight:normal;
  display:block;
  margin:0;
  padding:0;
}
  1. 决定我将使用哪一个受支持的 DraftJS 块:<h4>(因为我们无论如何都没有使用它)。 CSS class 基本上是将 <h4> 转换为 <small>
  2. BLOCK_TYPE_DROPDOWN 中添加此项:{label : 'Small', style: 'header-four'},

然后,当 onChange() 被调用时(基本上 'saving' 编辑的文本):

  1. 通过将 <h4> 替换为 <small>onChange() 中创建一个新字符串:let newString = value.toString('html').replace("<h4>", "<small>").replace("</h4>", "</small>");
  2. 将该字符串传递给我们拥有的另一个函数,该函数基本上是用该字符串填充 'webpart' 的内容。