Custom Block Rendering 自定义块级渲染
This article discusses how to customize Draft default block rendering. The block rendering is used to define supported block types and their respective renderers, as well as converting pasted content to known Draft block types.
本文讨论了如何定制 Draft 默认的 block 渲染。block 渲染被用于定义被支持的 block 类型和它们各自的渲染器,以及转换粘贴的内容到已知的 Draft block 类型上。
When pasting content or when using the convertFromHTML Draft will then convert the pasted content to the respective block rendering type by matching the Draft block render map with the matched tag.
当粘贴内容或使用 convertFromHTML 时,Draft 会通过 Draft block render map 找到匹配的标签,把粘贴内容转换成各自的block 渲染类型。
Draft default block render map
Draft 默认 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* |
** - Block type will be based on the parent <ul/> or <ol/>
*** - Any block that is not recognized by the block redering mapping will be treated as unstyled
** - block 类型会以父级的<ul/>或<ol/>为基础。
*** - 任何不被block render map 识别的 block 会被设置为 unstyled
Configuring block render map
配置 block render map
Draft default block render map can be overwritten, by passing an Immutable Map to the editor blockRender props.
通过传递一个 Immutable Map 给编辑器的 blockRender 属性,可以覆盖 Draft 的默认 block render map。
example of overwritting default block render map:
覆盖默认 block render map 的例子:
// The example below deliberatly only allows
// 'heading-two' as the only valid block type and
// updates the unstyled element to also become a h2.
// 这个下面的例子故意仅允许 “heading-two” 作为唯一允许的 block 类型,
// 并且也更新了unstrled元素成为一个h2
const blockRenderMap = Immutable.Map({
'header-two': {
element: 'h2'
},
'unstyled': {
element: 'h2'
}
});
class RichEditor extends React.Component {
render() {
return (
<Editor
...
blockRenderMap={blockRenderMap}
/>
);
}
}
There are cases where instead of overwriting the defaults we just want to add new block types; this can be done by using the DefaultDraftBlockRenderMap reference to create a new blockRenderMap
某些情况下相比起覆盖整个默认项,我们只是想增加新的block类型;这可以通过使用 DefaultDraftBlockRenderMap 的引用来创建一个新的 blockRenderMap 实现。
example of extending default block render map:
扩展默认 block render map 的例子:
const blockRenderMap = Immutable.Map({
'section': {
element: 'section'
}
});
// Include 'paragraph' as a valid block and updated the unstyled element but
// keep support for other draft default block types
// 引用”段落“作为一个有效的 block 并且更新 unstyled 的元素
// 但保持对其他 draft 默认 block 类型的支持
const extendedBlockRenderMap = Draft.DefaultDraftBlockRenderMap.merge(blockRenderMap);
class RichEditor extends React.Component {
render() {
return (
<Editor
...
blockRenderMap={extendedBlockRenderMap}
/>
);
}
}
When Draft parses pasted HTML, it maps from HTML elements back into Draft block types. If you want to specify other HTML elements that map to a particular block type, you can add an array
aliasedElements
to the block config.
当 Draft 粘贴 HTML 时,它会把 HTML 元素映射为 Draft 的 block 类型。如果你想要指定其他的 HTML 元素映射为一个特别的 block 类型,你可以在 block 配置中增加一个 aliasedElements
数组。
example of unstyled block type alias usage:
使用示例:给 unstyled block 类型添加别名:
'unstyled': {
element: 'div',
aliasedElements: ['p'],
}
Custom block wrappers
自定义块包装
By default the html element is used to wrap block types however a react component can also be provided to the blockRenderMap to wrap the EditorBlock.
默认情况下 html 元素被用来包装 block 类型,然而一个react组件也能被提供到 blockRenderMap 以包装编辑器的 block 。
During pasting or when using the convertFromHTML the html will be scanned for matching tag elements. A wrapper will be used when there is a definition for it on the blockRenderMap to wrap that particular block type. For example:
在粘贴或使用 convertFromHTML 时,html 会被扫描以匹配标签元素。一个包装器在 blockRenderMap 里有它的定义时,它会被用来包装那个特别的 block 类型。比如:
Draft uses wrappers to wrap <li/> inside either <ol/> or <ul/> but wrappers can also be used to wrap any other custom block type
Draft 使用包装器把 <li/> 包裹在 <ol/> 或 <ul/> 中,但是包装器也能被用来包装任意的自定义 block 类型。
example of extending default block render map to use a react component for a custom block:
用一个 react 组件作为自定义 block 扩展默认 block 渲染映射的例子:
class MyCustomBlock extends React.Component {
constructor(props) {
super(props);
}
render() {
return (
<div className='MyCustomBlock'>
{/* here, this.props.children contains a <section> container, as that was the matching element */}
{/* 这里,this.props.children 包含了一个 <section> 容器,也就是匹配的元素 */}
{this.props.children}
</div>
);
}
}
const blockRenderMap = Immutable.Map({
'MyCustomBlock': {
// element is used during paste or html conversion to auto match your component;
// it is also retained as part of this.props.children and not stripped out
// 元素被用来在粘贴或者 html 转换时自动匹配你的组件;
// 它也被作为 this.props.children 的一部分被保留而不会被剥离
element: 'section',
wrapper: <MyCustomBlock {...this.props} />
}
});
// keep support for other draft default block types and add our myCustomBlock type
// 保持支持其他的 draft 默认 block 类型,并且增加我们的 myCustomBlock 类型
const extendedBlockRenderMap = Draft.DefaultDraftBlockRenderMap.merge(blockRenderMap);
class RichEditor extends React.Component {
...
render() {
return (
<Editor
...
blockRenderMap={extendedBlockRenderMap}
/>
);
}
}