在DraftJS中设置自定义类型

时间:2016-09-02 14:16:13

标签: javascript reactjs draftjs

我很好奇我们是否可以定义自己的块类型,而不是使用DRAFTBLOCKTYPE中的块类型。

目前,我正在使用名为draft-wysiwyg的插件draft-image-plugin。问题是,我已将block-image作为块的类型而不是atomic传递,以使插件正常工作。

实际上,我曾尝试使用this中的解决方案,其中我将插件的类型覆盖为atomic。但是它会影响应用程序中atomic类型的其他块,因为我不能创建自己的blockRendererFn,因为blockRenderer被吞下了'通过该插件的blockRenderer。

要将块类型设置为atomic,我可以通过以下方式轻松实现:

AtomicBlockUtils.insertAtomicBlock(
  editorState,
  entityKey,
  ' '
)

如何将块类型设置为任何自定义类型,例如block-imageblock-table?这甚至可能吗?

1 个答案:

答案 0 :(得分:3)

是的,这是可能的,你有几个不同的选择。以下是我所知道的一些:

  1. 如果您可以控制呈现类型atomic的块的组件,那么将新类型作为实体添加到这些块可能是最简单的。

  2. 如果这不是一个选项,那就会变得更加麻烦。 AtomicBlockUtils实际上只是一个模块,用于帮助人们更轻松地创建媒体(原子)块(即使将来可能会添加更多实用功能)。如果您想要完全相同的行为,但使用不同的类型,则可以复制that module,只需与其他内容交换'atomic'(例如'block-image'或变量,以使其更具通用性/可恢复性)。

    他们使用的技术基本上是创建一个空块的选择,然后使用Modifier.setBlockType()函数为它提供一个新的块类型:

  3. const asAtomicBlock = DraftModifier.setBlockType(
        afterSplit, // ContentState
        insertionTarget, // SelectionState
        'atomic' // your custom type
    );
    
    1. this example中,作者创建了自己的版本,名为addNewBlock()(它的工作方式与AtomicBlockUtils中的完全不同):
    2. /*
      Adds a new block (currently replaces an empty block) at the current cursor position
      of the given `newType`.
      */
      const addNewBlock = (editorState, newType = Block.UNSTYLED, initialData = {}) => {
        const selectionState = editorState.getSelection();
        if (!selectionState.isCollapsed()) {
          return editorState;
        }
        const contentState = editorState.getCurrentContent();
        const key = selectionState.getStartKey();
        const blockMap = contentState.getBlockMap();
        const currentBlock = getCurrentBlock(editorState);
        if (!currentBlock) {
          return editorState;
        }
        if (currentBlock.getLength() === 0) {
          if (currentBlock.getType() === newType) {
            return editorState;
          }
          const newBlock = currentBlock.merge({
            type: newType,
            data: getDefaultBlockData(newType, initialData),
          });
          const newContentState = contentState.merge({
            blockMap: blockMap.set(key, newBlock),
            selectionAfter: selectionState,
          });
          return EditorState.push(editorState, newContentState, 'change-block-type');
        }
        return editorState;
      };
      

      所以如果你想要,例如创建一个类型为block-image'的块,带有src属性,你可以像这样使用这个函数:

      const newEditorState = addNewBlock(this.state.editorState, 'block-image', { src: 'https://...' })    
      this.setState({ editorState: newEditorState })
      

      <强>更新 如果添加新类型,还需要将其添加到编辑器的blockRenderMap中:

      import { Map } from 'immutable'
      
      <Editor 
        // editor props
        blockRenderMap={Map({
          ['unstyled']: {
            element: 'div'
          },
          ['block-image']: {
            element: 'div' // or whatever element you want as a wrapper
          },
          // all your other block types
        })}
      />