本文讨论如何自定义Draft默认Block Render。自定义块渲染 被用来 定义支持的块类型元素和它们各自的渲染器,还可以转换粘贴的内容成已知的Draft块类型。

当粘贴内容时或者当用convertFromHTML,Draft会转换粘贴的内容成相应的块渲染类型,方法是将Draft块渲染映射与对应匹配的标签进行匹配。

Draft default block render map

HTML element Draft block type
<h1/> header-one
<h2/> header-two
<h3/> header-three
<h4/> header-four
<h5/> header-five
<h6/> header-six
<blockquote/> blockquote
<pre/> code-block
<figure/> atomic
<li/> unordered-list-item,ordered-list-item**
<div/> unstyled*

** -块类型会基于父元素<ul/> 或者 <ol/>

* - 任何一个不会被识别的区块会被认为是unstyled

Configuring block render map(定义块渲染的映射)

默认的块渲染可以通过传递Immutable Map给编辑器blockRenderMap函数来覆盖掉默认的blockRenderMap。

覆盖默认块_BlockRenderMap_的例子:

  1. // The example below deliberatly only allows
  2. // 'heading-two' as the only valid block type and
  3. // updates the unstyled element to also become a h2.
  4. // 下面这个例子只允许'head -two'作为唯一有效的块类型
  5. // 并且更新所有的unstyled块类型元素都转化成h2
  6. const blockRenderMap = Immutable.Map({
  7. 'header-two': {
  8. element: 'h2'
  9. },
  10. 'unstyled': {
  11. element: 'h2'
  12. }
  13. });
  14. class RichEditor extends React.Component {
  15. render() {
  16. return (
  17. <Editor
  18. ...
  19. blockRenderMap={blockRenderMap}
  20. />
  21. );
  22. }
  23. }

下面一个例子,与重写默认的不同,我们仅仅是想添加一个新的块类型。我们可以使用DefaultDraftBlockRenderMap创建一个新的blockRenderMap。

扩展默认_blockRenderMap_的例子:

  1. const blockRenderMap = Immutable.Map({
  2. 'section': {
  3. element: 'section'
  4. }
  5. });
  6. // Include 'paragraph' as a valid block and updated the unstyled element but
  7. // keep support for other draft default block types
  8. // 段落 会被作为一个有效的区块,并且其他的默认块类型依然会被支持
  9. const extendedBlockRenderMap = Draft.DefaultDraftBlockRenderMap.merge(blockRenderMap);
  10. class RichEditor extends React.Component {
  11. render() {
  12. return (
  13. <Editor
  14. ...
  15. blockRenderMap={extendedBlockRenderMap}
  16. />
  17. );
  18. }
  19. }

当Draft解析粘贴的HTML时,它将HTML元素映射回Draft块类型。如果你想指定其他的HTMl元素变成一个特有的块类型,你可以在块配置中加一个数据aliasedElements

unstyled 块类型alias用法:

  1. 'unstyled': {
  2. element: 'div',
  3. aliasedElements: ['p'],
  4. }

Custom block wrappers(自定义块包装)

默认情况下,html元素用于包装块类型。但是,也可以向blockRenderMap提供react组件来包装EditorBlock。

在粘贴过程中,或者在调用convertFromHTML时,html将被扫描以查找匹配的标记元素。当在blockRenderMap上有定义时,将使用定义的包装器 来包装 特定的块类型。例如:

Draft使用包装器将<li/>包装在<ul/><ol/>中,但是包装器也可以用于包装任何其他自定义块类型。

用一个针对自定义块的React组件拓展默认的块渲染映射的例子:
_

  1. class MyCustomBlock extends React.Component {
  2. constructor(props) {
  3. super(props);
  4. }
  5. render() {
  6. return (
  7. <div className='MyCustomBlock'>
  8. {/* here, this.props.children contains a <section> container, as that was the matching element */}
  9. {this.props.children}
  10. </div>
  11. );
  12. }
  13. }
  14. const blockRenderMap = Immutable.Map({
  15. 'MyCustomBlock': {
  16. // element is used during paste or html conversion to auto match your component;
  17. // it is also retained as part of this.props.children and not stripped out
  18. element: 'section',
  19. wrapper: <MyCustomBlock />,
  20. }
  21. });
  22. // keep support for other draft default block types and add our myCustomBlock type
  23. const extendedBlockRenderMap = Draft.DefaultDraftBlockRenderMap.merge(blockRenderMap);
  24. class RichEditor extends React.Component {
  25. ...
  26. render() {
  27. return (
  28. <Editor
  29. ...
  30. blockRenderMap={extendedBlockRenderMap}
  31. />
  32. );
  33. }
  34. }