自定义Block渲染
这篇文章讨论怎么定制Draft的block渲染。Block渲染用于定义支持的block类型和它们的渲染器,以及将解析之后的的内容转换为已知的Draft block类型。
当解析内容或者使用convertFromHTML
时,Draft会将标签和Draft block进行匹配,将解析后的内容转化为已知的block渲染类型。
默认的block渲染表
HTML标签 | Draft block类型 |
---|---|
\ | header-one |
\ | header-two |
\ | header-three |
\ | header-four |
\ | header-five |
\ | header-six |
\ | blockquote |
\ | code-block |
\ |
atomic |
\ | unordered-list-item,ordered-list-item ** |
\ | unstyled * |
** - 这个Block类型建立在父级元素为\
- 和\
- 的基础上
* - 任何不在上边列表的block类型都会被当做unstyled
配置block渲染列表
Draft默认的block渲染可以通过给Editor
组件传入类型为Immutable Map的blockRender
prop来重写。
例如改写默认的block渲染。
// 下边的例子中,只允许「heading-two」作为唯一有效的block类型
// 并且将unstyled元素也更新为「h2」
const blockRenderMap = Immutable.Map({
'header-two': {
element: 'h2'
},
'unstyled': {
element: 'h2'
}
});
class RichEditor extends React.Component {
render() {
return (
<Editor
...
blockRenderMap={blockRenderMap}
/>
);
}
}
除了重写block类型,我们还能够添加自定义的block类型。通过DefaultDraftBlockRenderMap来新建一个blockRenderMap。
扩展默认的block render map。
const blockRenderMap = Immutable.Map({
'section': {
element: 'section'
}
});
// 将'section' 作为可用的block类型,并更新unstyled元素
// 同时保持其它的block类型
const extendedBlockRenderMap = Draft.DefaultDraftBlockRenderMap.merge(blockRenderMap);
class RichEditor extends React.Component {
render() {
return (
<Editor
...
blockRenderMap={extendedBlockRenderMap}
/>
);
}
}
当Draft解析一个已经被解析的html,它将html元素转化为Draft block类型。如果你想让其它的标签也能转化为指定的block类型,你可以在block config中添加aliasedElements
。
unstyled block类型别名的使用:
'unstyled': {
element: 'div',
aliasedElements: ['p'],
}
自定义 block wrappers
默认的情况下,html标签被用来包裹block类型。通过blockRenderMap,React组件也能够用来包裹EditorBlock。
在解析或者使用convertFromHTML
时html会被扫描,来匹配特定的标签。一个wrapper会用来承载特定的block类型。例如:
Draft 使用\
- 或 \
- 的wrapper。wrapper可以在其它类型的block上使用。
- 作为\
在自定义block类型上使用React组件作为wrapper的例子:
class MyCustomBlock extends React.Component {
constructor(props) {
super(props);
}
render() {
return (
<div className='MyCustomBlock'>
{/* 这里this.props.children 包含<section>,因为section匹配上了这个组件 */}
{this.props.children}
</div>
);
}
}
const blockRenderMap = Immutable.Map({
'MyCustomBlock': {
// 在解析过程中使用的html标签,用来对应我们的组件;
// 它也会被保留,不会被替换。
element: 'section',
wrapper: MyCustomBlock,
}
});
// 在支持原有block类型的基础上添加我们的myCustomBlock类型
const extendedBlockRenderMap = Draft.DefaultDraftBlockRenderMap.merge(blockRenderMap);
class RichEditor extends React.Component {
...
render() {
return (
<Editor
...
blockRenderMap={extendedBlockRenderMap}
/>
);
}
}