本文是《WordPress Gutenberg Block API》专题的第 4 篇,共 6 篇:
- WordPress Gutenberg Block API:简介
- WordPress Gutenberg Block API:块外观
- WordPress Gutenberg Block API:创建自定义块
- WordPress Gutenberg Block API:扩展块
- 为WordPress Gutenberg 区块创建样式变体:第1部分
- 为WordPress Gutenberg 区块创建样式变体:第2部分
欢迎回到我们使用WordPress Gutenberg Block API创建自定义块的系列好代码教程。本好代码教程是关于扩展我们在上一篇文章中创建的随机图像块。我们已经添加了一个下拉控件来选择图像类别。下来将添加更多选项,来进行更多自定义。
具体来说,我们将看到如何在编辑器的各个部分添加块设置。没错,您不仅限于直接在块本身上添加块控件!
最终的my-custom-block插件代码会提供下载。只需点击下载my-custom-block到您的计算机,然后像安装任何其他WordPress插件一样进行安装。您还可以在我们的GitHub仓库中找到源代码。
Gutenberg正在以合理的速度开发,自上一个好代码教程发布以来,已有一个新的重要版本。本好代码教程中使用的Gutenberg版本已更新至3.0.1,并且某些编辑器UI可能与本系列之前的好代码教程中显示的屏幕截图略有不同。
开始扩展吧!
我们在上一个好代码教程中添加的下拉控件位于编辑器内部,直接位于随机图像的标记下方。这很方便,但我们也有其他选择。
我们还可以将块控件添加到弹出工具栏(在选择块时显示)和块检查器面板。
在上面的界面截图中,我们可以看到段落块[1]的工具栏控件,以及面板检查器[3]中的相关控件。位置[2]显示我们的随机图像块的下拉控件。
您可能已经在考虑为自己的块设置选择哪个位置,但您不必只选择其中一个位置。它们不是相互排斥的。例如,对于段落块(如上所示),您可以看到块检查器面板和工具栏之间的设置是分开的。
此外,在编辑器中的不同位置有两个独立的控件可以影响相同的设置。你可能不想经常这样做,但还是要知道如何实现它,所以我们稍后会看到如何做到这一点。
直接块设置
让我们最简单为块添加功能的方法开始,该功能直接位于块的edit
函数内。我们已经使用这种方法添加了我们的随机图像下拉控件,因为它只需要很少的额外工作。
我们不会为块本身添加新的控件,但我们可以调整下拉控件的行为,使其更加直观。为了使其尽可能靠近前端渲染,除非选择了块,否则我们可以限制下拉显示。
我们现在就做这个修改吧。如果您上次关注本好代码教程,请在您喜欢的编辑器中打开/my-custom-block/src/random-image/index.js。这是我们随机图像块的主要JavaScript文件。
传递给所有块的一个工具是isSelected
,它保存了块的可见性状态。我们可以使用它来有条件地显示类别下拉控件。
首先,isSelected
从props
对象中拉出并将其添加到edit
函数内的常量列表中。这很有用,所以我们可以用缩短的名称(即isSelected
而不是props.isSelected
)来引用它。
1 | const { attributes: { category }, setAttributes, isSelected } = props; |
const { attributes: { category }, setAttributes, isSelected } = props;
接下来,我们可以使用此属性来确定是否应显示下拉控件:
1 2 3 4 5 6 7 8 9 10 11 | { isSelected && ( <form onSubmit={ setCategory }> <select value={ category } onChange={ setCategory }> <option value="animals">Animals</option> <option value="arch">Architecture</option> <option value="nature">Nature</option> <option value="people">People</option> <option value="tech">Tech</option> </select> </form> ) } |
{ isSelected && ( <form onSubmit={ setCategory }> <select value={ category } onChange={ setCategory }> <option value="animals">Animals</option> <option value="arch">Architecture</option> <option value="nature">Nature</option> <option value="people">People</option> <option value="tech">Tech</option> </select> </form> ) }
这是一种测试isSelected
的简便方法,因为我们无法在JSX代码中使用完整的JavaScriptif
语句。
确保您仍在观看文件并进行更改,以便将任何块的源代码(JSX,ES6 +,Sass等)转换为有效的JavaScript和CSS。如果您当前没有在文件中查看更改,请在my-custom-block插件根文件夹中打开命令行窗口并输入npm start
。
打开Gutenberg编辑器并添加随机图像块。这次,如果尚未单击块,则下拉控件不可见。
这为块提供了更好的互动体验。
工具栏控件
如果您使用了任何核心Gutenberg块(例如段落块),那么您将熟悉工具栏设置。选择“段落”块后,会出现一个弹出工具栏,其中包含用于格式化文本的按钮。这种类型的控件非常适用于具有开/关类型状态的块设置 - 例如,文本对齐或格式(如粗体或斜体)。
我们将使用内置对齐工具栏控件来允许下拉图像类别控件设置左对齐(默认),右对齐或居中对齐。
首先,我们需要从wp.blocks
中提取AlignmentToolBar
和BlockControls
组件。这些允许我们在选中块时在上方的浮动工具栏中显示对齐控件。这些是我们可以在自己的块中使用的核心组件的一部分。
1 2 3 4 5 | const { AlignmentToolbar, BlockControls, registerBlockType } = wp.blocks; |
const { AlignmentToolbar, BlockControls, registerBlockType } = wp.blocks;
该BlockControls
组件充当工具栏容器,并将AlignmentToolbar
放在里面。
我们仍然需要手动设置对齐工具栏的行为,我们可以添加新categoryAlign
属性来存储块的对齐状态(左,右或居中)。
我们的attributes
对象现在包含两个设置。
1 2 3 4 5 6 7 8 9 10 | attributes: { category: { type: 'string', default: 'nature' }, categoryAlign: { type: 'string' default: '' } } |
attributes: { category: { type: 'string', default: 'nature' }, categoryAlign: { type: 'string' default: '' } }
categoryAlign
属性的默认值为空字符串,这将导致默认情况下不应用对齐。
要引用新属性,我们可以将此值拉出到自己的常量变量中,就像我们对下拉category
属性所做的那样。
1 | const { attributes: { category, categoryAlign }, setAttributes, isSelected } = props; |
const { attributes: { category, categoryAlign }, setAttributes, isSelected } = props;
我们现在需要做的就是将两个新组件放入edit
函数中并配置属性。
1 2 3 4 5 6 | <BlockControls> <AlignmentToolbar value={ categoryAlign } onChange={ value => setAttributes( { categoryAlign: value } ) } /> </BlockControls> |
<BlockControls> <AlignmentToolbar value={ categoryAlign } onChange={ value => setAttributes( { categoryAlign: value } ) } /> </BlockControls>
正如你所看到的,我们需要做的是,当工具栏按钮被点击时,分配Alignmenttoolbar
的value
属性给categoryAlign
属性,并调用setAttributes
函数。此函数会更新categoryAlign
属性并使所有内容保持同步。
要应用下拉控件的对齐样式,我们需要向表单元素添加样式属性。
1 | <form onSubmit={ setCategory } style={ {textAlign: categoryAlign} }> |
<form onSubmit={ setCategory } style={ {textAlign: categoryAlign} }>
请注意,我们不需要此控件来影响前端的任何内容,因此我们不需要向块的save
函数添加任何代码。
添加设置面板
块检查器面板为您提供了添加块控件的空间,是更复杂控件的理想位置。
我们将专注于向检查器面板添加两个下拉控件。第一个将是类别下拉控件的副本,用来选择随机图像的类型。这演示了如何通过多个控件来更新公共属性。
更新一个控件后,相应的控件也会自动更新!但实际上,您通常只需要一个设置一个控件。
第二个下拉控件将允许您选择应用于随机图像的滤镜。PlaceIMGWeb服务支持两种类型的过滤器 —— grayscale 和 sepia ——我们可以在它们之间选择,只需添加sepia
或grayscale
到HTTP请求的网址中。如果我们不指定过滤器,则将返回标准彩色图像。
两个下拉列表的代码非常相似,因此我们将它们一起添加。
首先,让我们定义我们需要的新块和组件。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | const { AlignmentToolbar, BlockControls, registerBlockType, InspectorControls } = wp.blocks; const { PanelBody, PanelRow } = wp.components; const { Fragment } = wp.element; |
const { AlignmentToolbar, BlockControls, registerBlockType, InspectorControls } = wp.blocks; const { PanelBody, PanelRow } = wp.components; const { Fragment } = wp.element;
在这里,新的变量是InspectorControls
,PanelBody
,PanelRow
,和Fragment
,这些都是用来帮助创建Inspector面板UI。
当您需要从edit
或save
函数返回多个顶级元素但不想将它们包装在将要输出的元素中时,<Fragment>
组件会非常有用。
<Fragment>
不会在前端输出任何标记,就像一个看不见的容器。它只是一种返回多个顶级元素的便捷方式,并且是以前返回元素数组的方法的替代方法。
我们只需要添加一个名为 imageFilter
的新属性,因为现有category
属性可以重用。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | attributes: { category: { type: 'string', default: 'nature' }, categoryAlign: { type: 'string', default: '' }, imageFilter: { type: 'string', default: '' } } |
attributes: { category: { type: 'string', default: 'nature' }, categoryAlign: { type: 'string', default: '' }, imageFilter: { type: 'string', default: '' } }
在edit
函数内部,我们需要引用新属性来添加一个新变量。
1 | const { attributes: { category, categoryAlign, imageFilter }, setAttributes, isSelected } = props; |
const { attributes: { category, categoryAlign, imageFilter }, setAttributes, isSelected } = props;
添加块检查器面板非常简单。我们将使用的组件结构如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | <InspectorControls> <PanelBody> <PanelRow> ... </PanelRow> <PanelRow> ... </PanelRow> </PanelBody> <PanelBody> <PanelRow> ... </PanelRow> <PanelRow> ... </PanelRow> </PanelBody> </InspectorControls> |
<InspectorControls> <PanelBody> <PanelRow> ... </PanelRow> <PanelRow> ... </PanelRow> </PanelBody> <PanelBody> <PanelRow> ... </PanelRow> <PanelRow> ... </PanelRow> </PanelBody> </InspectorControls>
该<InspectorControls>
组件作为块检查器容器,<PanelBody>
定义了各个可折叠部分。在每个组件中,您可以拥有任意数量的<PanelRow>
组件,而这些组件又包含了您的控件。
我们已经为可以重用的类别下拉控件定义了标记。为此,将其抽象为一个单独的函数:
1 2 3 4 5 6 7 8 9 10 11 12 13 | function showForm() { return ( <form onSubmit={ setCategory } style={ {textAlign: categoryAlign} }> <select id="image-category" value={ category } onChange={ setCategory }> <option value="animals">Animals</option> <option value="arch">Architecture</option> <option value="nature">Nature</option> <option value="people">People</option> <option value="tech">Tech</option> </select> </form> ); } |
function showForm() { return ( <form onSubmit={ setCategory } style={ {textAlign: categoryAlign} }> <select id="image-category" value={ category } onChange={ setCategory }> <option value="animals">Animals</option> <option value="arch">Architecture</option> <option value="nature">Nature</option> <option value="people">People</option> <option value="tech">Tech</option> </select> </form> ); }
然后,只要我们需要渲染类别下拉控件,就可以引用此函数。块检查器面板的标记需要在块标记之外,因此我们可以在返回之前使用<Fragment>
组件将它们包裹起来。
接下来,我们需要为类别和图像过滤器下拉列表添加块检查器组件。这些需要在<PanelRow>
组件内部定义,我们还必须定义一个新的回调函数来处理onChange
事件。这与上一个好代码教程中的类别下拉代码非常相似,所以现在应该对它比较熟悉了。
把所有代码放在一起,现在edit
方法的return
函数看起来是这样的:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | return ( <Fragment> <InspectorControls> <PanelBody title={ __('Image Settings') }> <PanelRow> <label>Set Filter</label> { showForm() } </PanelRow> <PanelRow> <label>Set Filter</label> <form onSubmit={ setFilter }> <select id="image-filter" value={ imageFilter } onChange={ setFilter }> <option value="">None</option> <option value="sepia">Sepia</option> <option value="grayscale">Grayscale</option> </select> </form> </PanelRow> </PanelBody> </InspectorControls> <div className={ props.className }> <BlockControls> <AlignmentToolbar value={ categoryAlign } onChange={ value => setAttributes( { categoryAlign: value } ) } /> </BlockControls> <RandomImage filter={ imageFilter } category={ category } /> { isSelected && ( showForm() ) } </div> </Fragment> ); |
return ( <Fragment> <InspectorControls> <PanelBody title={ __('Image Settings') }> <PanelRow> <label>Set Filter</label> { showForm() } </PanelRow> <PanelRow> <label>Set Filter</label> <form onSubmit={ setFilter }> <select id="image-filter" value={ imageFilter } onChange={ setFilter }> <option value="">None</option> <option value="sepia">Sepia</option> <option value="grayscale">Grayscale</option> </select> </form> </PanelRow> </PanelBody> </InspectorControls> <div className={ props.className }> <BlockControls> <AlignmentToolbar value={ categoryAlign } onChange={ value => setAttributes( { categoryAlign: value } ) } /> </BlockControls> <RandomImage filter={ imageFilter } category={ category } /> { isSelected && ( showForm() ) } </div> </Fragment> );
而setFilter
回调被定义为:
1 2 3 4 5 | function setFilter( event ) { const selected = event.target.querySelector( '#image-filter option:checked' ); setAttributes( { imageFilter: selected.value } ); event.preventDefault(); } |
function setFilter( event ) { const selected = event.target.querySelector( '#image-filter option:checked' ); setAttributes( { imageFilter: selected.value } ); event.preventDefault(); }
要获取过滤后的图像,我们需要在RandomImage
每次更改下拉列表时更新组件以接受新的过滤器值。
1 2 3 4 5 6 7 | function RandomImage( { category, filter } ) { if(filter) { filter = '/' + filter; } const src = 'https://placeimg.com/320/220/' + category + filter; return <img src={ src } alt={ category } />; } |
function RandomImage( { category, filter } ) { if(filter) { filter = '/' + filter; } const src = 'https://placeimg.com/320/220/' + category + filter; return <img src={ src } alt={ category } />; }
请注意我们是如何在edit
方法中使用这个新的组件属性将新的过滤器值发送到PlaceIMG。
1 | <RandomImage filter={ imageFilter } category={ category } /> |
<RandomImage filter={ imageFilter } category={ category } />
所有代码更改会创建一个新的块检查器面板,其中包含两个下拉控件来更改图像类别和过滤器。
要使新的过滤器属性也适用于前端,我们只需要更新save
方法。
1 2 3 4 5 6 7 8 | save: function( props ) { const { attributes: { category, imageFilter } } = props; return ( <div> <RandomImage filter={ imageFilter } category={ category } /> </div> ); } |
save: function( props ) { const { attributes: { category, imageFilter } } = props; return ( <div> <RandomImage filter={ imageFilter } category={ category } /> </div> ); }
小结
在这篇文章中,我们介绍了向块添加设置的三种不同方法:
- 弹出工具栏
- 直接在块内部
- 块检查器面板
我们只为每个块添加了基本设置,但我们可以轻松地做更多,比如添加对多个图像的支持,添加图像标题以及控制样式(如边框颜色、半径或随机图像尺寸)。
我敢肯定,到目前为止,你可能已经有了一些创建自己的自定义块的想法。我很想知道你在自己的项目中找到哪些有用的块!
我们刚刚在Envato Tuts +开始使用Gutenberg,如果你想在未来的好代码教程中看到Gutenberg块开发的任何特定方面更深入的内容,请通过评论告诉我们。
原文:WordPress Gutenberg Block API: Extending Blocks,发布于 2018年6月18日,由倡萌@WordPress大学翻译,未经许可,禁止转载译文和他用!
本文WordPress Gutenberg Block API:扩展块到此结束。人生从来没有真正的绝境。无论遭受多少艰辛,无论经历多少苦难,只要一个人的心中还怀着一粒信念的种子,那么总有一天,他就能走出困境,让生命重新开花结果。小编再次感谢大家对我们的支持!