Custom Block Components

自定义块级组件

Draft is designed to solve problems for straightforward rich text interfaces like comments and chat messages, but it also powers richer editor experiences like Facebook Notes.

Draft 旨在解决简单的富文本接口的问题,像是评论和聊天信息,但它也赋予了更丰富的编辑器体验,像是 Facebook 笔记

Users can embed images within their Notes, either loading from their existing Facebook photos or by uploading new images from the desktop. To that end, the Draft framework supports custom rendering at the block level, to render content like rich media in place of plain text.

用户可以在他们的笔记中嵌入图片,无论是从他们已经存在的 Facebook 照片中读取还是从桌面上传新图片。为此,Draft 框架支持 block 级别的自定义渲染,来渲染富媒体内容,替代了纯文本。

The TeX editor in the Draft repository provides a live example of custom block rendering, with TeX syntax translated on the fly into editable embedded formula rendering via the KaTeX library.

在 Draft 仓库里的 TeX 编辑器 提供了一个自定义块级渲染的在线示例。通过 KaTeX library ,TeX 语法被动态的编译成渲染的可编辑的嵌入公式。

A media example is also available, which showcases custom block rendering of audio, image, and video.

也提供了一个 多媒体示例 ,它展示了音频,图片和视频的自定义块级渲染。

By using a custom block renderer, it is possible to introduce complex rich interactions within the frame of your editor.

通过使用一个自定义的block渲染器,在你的编辑器里引入复杂的富文本接口成为可能。

Custom Block Components

自定义块级组件

Within the Editor component, one may specify the blockRendererFn prop. This prop function allows a higher-level component to define custom React rendering for ContentBlock objects, based on block type, text, or other criteria.

Editor 组件中,可以指定 blockRendererFn 属性。这个属性方法允许一个更高级别的组件指定自定义的,以 block 类型,文字或其他标准为基础的,对 ContentBlock 对象的 React 渲染。

For instance, we may wish to render ContentBlock objects of type 'atomic' using a custom MediaComponent.

比如,我们也许希望以 “atomic” 类型,使用自定义的 MediaComponent 渲染 ContentBlock 对象。

function myBlockRenderer(contentBlock) {
  const type = contentBlock.getType();
  if (type === 'atomic') {
    return {
      component: MediaComponent,
      editable: false,
      props: {
        foo: 'bar',
      },
    };
  }
}

// Then...
import {Editor} from 'draft-js';
class EditorWithMedia extends React.Component {
  ...
  render() {
    return <Editor ... blockRendererFn={myBlockRenderer} />;
  }
}

If no custom renderer object is returned by the blockRendererFn function, Editor will render the default DraftEditorBlock text block component.

如果没有自定义的渲染器对象被 blockRendererFn方法返回,Editor 会渲染默认的 DraftEditorBlock 文本块级组件。

The component property defines the component to be used, while the optional props object includes props that will be passed through to the rendered custom component via the props.blockProps sub property object. In addition, the optional editable property determines whether the custom component is contentEditable.

这个 component 的属性决定了组件何时被使用,同时这个可选的 props 对象包含了,通过 props.blockProps 子属性对象进入被渲染的自定义组件的属性。此外,这个可选的 editable 属性决定了自定义组件是否是 contentEditable

It is strongly recommended that you use editable: false if your custom component will not contain text.

如果你的自定义组件不包含文本,强烈建议您使用 editable:false

If your component contains text as provided by your ContentState, your custom component should compose a DraftEditorBlock component. This will allow the Draft framework to properly maintain cursor behavior within your contents.

如果你的组件包含被你的 ContentState 提供的文本,你的自定义组件应该构成一个 DraftEditorBlock 组件。这会要求 Draft 框架在你的内容里适当的调整光标行为。

By defining this function within the context of a higher-level component, the props for this custom component may be bound to that component, allowing instance methods for custom component props.

通过在一个高级组件的上下文中定义方法,这个自定义组件的属性可以被绑定到其他组件,允许它使用自定义组件属性的实例方法。

Defining custom block components

定义自定义块级组件

Within MediaComponent, the most likely use case is that you will want to retrieve entity metadata to render your custom block. You may apply an entity key to the text within a 'atomic' block during EditorState management, then retrieve the metadata for that key in your custom component render() code.

MediaComponent 中,最常用的例子是你想要检索检索实体元数据以渲染你的自定义 block 。在 EditorState 的管理中,你也许会应用一个实体 key 到一个 'atomic' 的 block 的文本上,然后在你的自定义组件的 render() 代码中检索那个 key 的元数据。

class MediaComponent extends React.Component {
  render() {
    const {block, contentState} = this.props;
    const {foo} = this.props.blockProps;
    const data = contentState.getEntity(block.getEntityAt(0)).getData();
    // Return a <figure> or some other content using this data.
    // 返回一个 <figure> 或其他使用这个数据的内容
  }
}

The ContentBlock object and the ContentState record are made available within the custom component, along with the props defined at the top level. By extracting entity information from the ContentBlock and the Entity map, you can obtain the metadata required to render your custom component.

这个 ContentBlock 对象和 ContentState 记录可以在自定义组件中获取,通过定义好的顶级属性。通过从 ContentBlockEntity 的遍历提取实体信息,你可以获取所需的元数据,从而渲染到你的自定义组件上。

Retrieving the entity from the block is admittedly a bit of an awkward API, and is worth revisiting.

从 block 上检索实体的 API 不可否认的有点笨拙,但这是值得的。

Recommendations and other notes

建议和其他注意点

If your custom block renderer requires mouse interaction, it is often wise to temporarily set your Editor to readOnly={true} during this interaction. In this way, the user does not trigger any selection changes within the editor while interacting with the custom block. This should not be a problem with respect to editor behavior, since interacting with your custom block component is most likely mutually exclusive from text changes within the editor.

如果你的自定义 block 渲染器需要鼠标交互,在交互中临时设置你的 EditorreadOnly = { true } 是明智的。这样,用户不会在编辑器中触发自定义 block 的交互。这不应该是编辑行为方面的问题,因为你的自定义 block 组件的交互和编辑器中文字的变化很可能是互斥的。

The recommendation above is especially important for custom block renderers that involve text input, like the TeX editor example.

上述的建议对于包含文字输入的自定义 block 渲染特别重要,例如 TeX 编辑器示例。

It is also worth noting that within the Facebook Notes editor, we have not tried to perform any special SelectionState rendering or management on embedded media, such as rendering a highlight on an embedded photo when selecting it. This is in part because of the rich interaction provided on the media itself, with resize handles and other controls exposed to mouse behavior.

值得一提的是,在 Facebook 的笔记编辑器中,我们没有尝试执行任何特殊的 SelectionState 渲染或管理到嵌入的多媒体中,比如渲染一个高亮到选择的嵌入照片上。这在一定程度上是因为多媒体本身提供的富文本交互,比如缩放的处理和其他暴露到鼠标行为上的控制。

Since an engineer using Draft has full awareness of the selection state of the editor and full control over native Selection APIs, it would be possible to build selection behavior on static embedded media if desired. So far, though, we have not tried to solve this at Facebook, so we have not packaged solutions for this use case into the Draft project at this time.

因为一个使用 Draft 的工程师有着对于编辑器的选择状态的完整认识,以及对于原生 Selection APIs 的完整控制,所以如果需要,在内嵌多媒体上构建静态的选择行为是可能的。到目前为止,在 Facebook ,我们还没有尝试解决这一点,所以在 Draft 项目中,我们还没有这个示例的完整的解决方案。

results matching ""

    No results matching ""