在区块中按下回车键时会发生一些非常酷的事情
当你在编辑器中编写列表时,按下回车键,就会自动得到另一个项目符号!
你是否曾想过这是如何发生的?你是否希望让你自己的区块也能实现类似的功能,而不仅仅是列表项?
这正是本文要帮助你的地方。如果你之前写过一些区块,可能会更容易理解。
通常会发生三件事。
当你在编辑一个 Gutenberg 区块时,按下回车键通常会发生以下三件事之一:
- 创建一个与你刚刚编写的区块相匹配的新区块。
- 添加一个换行符。
- 或者添加一个新段落,因为段落是默认区块。
当你通过按回车键来获得一个新区块时,你正在使用 Gutenberg 的 RichText 组件。文档以及撰写 WordPress 相关内容的人将这种行为称为拆分。在区块末尾按回车键会添加一个新区块,而在区块中间按回车键会将其一分为二。
你需要使用两个函数来实现拆分,但还有第三个函数可以让用户撤销拆分,这非常方便。这被称为合并。
- onSplit – 用于创建新区块(必需)
- onReplace – 用于添加新区块 – (必需)。区块通常应该已经将此作为 prop 接收,通常提供此默认值就足够了。
- onMerge – 用于将区块粘合在一起(可选)。区块通常应该已经接收一个
mergeBlocksprop,可以使用它。
你可以将这些函数作为props传递给 RichText 组件。
onSplit
onSplit 接收被拆分的值部分,以及该部分是否位于原始区块之后(即,用户是否要在内容开头按回车键)。它应该返回一个新区块,该函数将被调用两次,每次针对拆分后的一个部分。
给定一个字符串 “Test”:
- 在开头按回车键意味着 onSplit 将在第一次调用时产生
''和false,然后在第二次调用时产生"Test"和true。 - 在中间按回车键意味着 onSplit 将在第一次调用时获得
'Te'和true,然后在第二次调用时获得'st'和false。 - 在末尾按回车键意味着 onSplit 将在第一次调用时获得
'Test'和true,然后在第二次调用时获得''和false。
在所有情况下,给定的值都应该返回一个区块。因此,一个典型的实现将位于区块编辑组件内部,看起来像这样:
<RichText
onSplit={ ( value, isAfterOriginal ) =>
createBlock( 'block/name', { ...attributes, text: value } );
}
/>
attributes 是传入编辑组件的 attributes prop。
onReplace
onReplace 接收一个数组,该数组包含从 onSplit 返回的区块。它还接收要选择的索引和初始位置。
它不应该返回任何内容;它应该将区块添加到编辑器中。一个简单的实现将位于区块编辑组件内部,看起来像这样:
<RichText
onReplace={ ( blocks, indexToSelect, initialPosition ) =>
replaceBlocks( clientId, blocks, indexToSelect, initialPosition );
}
/>
其中 replaceBlocks 来自 block-editor store,clientId 是当前区块的 clientId。
默认的 onReplace prop 的功能与上述类似。除非你需要完全不同的东西,否则不妨将其设置为 RichText prop,而无需重新发明轮子。
onMerge
onMerge 捕获合并的方向。与 onReplace 一样,它也不应该返回任何内容。相反,它应该只是在编辑器中找到你想要合并的区块——然后将它们合并。
你的区块应该已经接收一个 mergeBlocks prop。你当然可以使用它。但请注意,你最终会调用区块的 merge 函数,该函数将传递你想要合并的两个区块的属性。因此,你需要在区块的 index.js 文件中分配区块的 merge 函数。这通常如下所示:
( firstAttribs, secondAttribs ) => { ...firstAttribs, text: firstAttribs.text + secondAttribs.text }
扩展阅读
- 我在研究这个问题时发现两个有用的区块:list-item 区块和 button 区块。它们为我提供了在现实世界中使用所有三个函数的可靠示例。
- 你可能想看看
onSplit和onReplace在上下文中是如何被调用的。查看 rich-text/split-value.js 如何调用 `onSplit`,以及 rich-text/index.js 如何调用onMerge。 - 你会发现,传递给区块的默认
onMergeprop 的大部分逻辑都位于 mergeBlocks 内部。