构建块的好处之一是能够允许用户通过块属性来控制块的外观和行为。
让我们学习如何向块添加属性,以及如何向块添加控件,让用户能够更改这些属性。
向块添加属性
属性是块中可由用户控制的特性。例如,对于版权日期块,起始年份就是一个用户可以更改的属性。
要向块添加属性,您需要在块的元数据文件 block.json 中定义它们。
打开 src 目录中的 block.json 文件,并添加以下代码:
{
"apiVersion": 2,
"name": "example/copyright-date-block",
"title": "Copyright Date Block",
"category": "text",
"icon": "calendar",
"description": "显示版权日期",
"supports": {
"html": false
},
"attributes": {
"startingYear": {
"type": "string",
"default": "2020"
}
},
"editorScript": "file:./index.js",
"editorStyle": "file:./index.css",
"style": "file:./style-index.css"
}
JSON 格式的好处之一是,只要使用预期的属性名称,您就可以在现有 JSON 对象中的任何位置添加新属性。在这种情况下,attributes 属性是块注册过程所预期的,因此您可以将其添加到 JSON 对象中的任何位置。
在此示例中,我们向块添加了一个名为 startingYear 的属性。type 属性定义了属性的数据类型,default 属性设置了属性的初始值。
如果您正在运行开发服务器,您可能会注意到在编辑块元数据时它会崩溃。如果发生这种情况,只需重新启动开发服务器即可。
访问块的属性
要在块的编辑组件中访问块的属性,您可以在编辑组件函数中指定一个 props 参数。
编辑组件和保存函数都设置为始终接受这个包含块所有属性的 props 对象。
export default function Edit( props ) {
// 在这里使用 props
}
然后,您可以使用 props 对象访问块的属性。例如,要访问 startingYear 属性,您可以使用 props.attributes.startingYear。
export default function Edit( props ) {
const blockProps = useBlockProps();
return (
<p { ...blockProps }>
© { props.attributes.startingYear }
</p>
);
}
您还可以更新保存函数以包含块的属性。
export default function save( props ) {
const blockProps = useBlockProps.save();
return (
<p { ...blockProps }>
© { props.attributes.startingYear }
</p>
);
}
每次访问起始年份属性时,不必写出 props.attributes.startingYear,您可以使用一种称为解构赋值的语法,先从 props 对象中提取 attributes,然后再从 attributes 中提取 startingYear。
export default function Edit( { attributes } ) {
const blockProps = useBlockProps();
return (
<p { ...blockProps }>
© { attributes.startingYear }
</p>
);
}
export default function save( { attributes } ) {
const blockProps = useBlockProps.save();
return (
<p { ...blockProps }>
© { attributes.startingYear }
</p>
);
}
如果您不熟悉对象解构,这是一种从对象中提取属性并将其分配给变量的方法。一开始可能有点奇怪,但一旦习惯了,它就能节省大量时间和代码。
让构建过程完成,然后将块添加到文章或页面中,您会看到块现在显示起始年份属性,并带有您定义的默认值。
块恢复
如果您碰巧在文章或页面中测试块,并在每次更改块属性的默认值或 save 函数时刷新浏览器,有时可能会遇到以下错误:
此块包含意外或无效的内容。
这是因为当块的 save 函数运行时,它会将 save 函数的输出与数据库中已保存的输出进行比较。如果它们不同,就会显示此错误。
如果您打开浏览器开发者工具的“控制台”选项卡,您会看到这被报告为块验证错误。
您可以通过使用“尝试块恢复”按钮来修复此问题,该按钮会重新渲染块并重新保存其输出。
向块添加设置面板
要允许用户更改块的属性,您需要使用块控件。
有两种添加控件的方法:一种是在块工具栏中(当块被选中时出现在块上方),另一种是在设置侧边栏中(也称为检查器,当块被选中时出现在侧边栏中)。
由于 startingYear 属性是一个文本字符串,您可以在块侧边栏中使用 TextControl 来允许用户更改起始年份。
要为您的块向块侧边栏添加控件,您首先需要导入一些内容。
- 您需要从
@wordpress/block-editor 包中导入 InspectorControls 组件。
- 您需要从
@wordpress/components 包中导入 PanelBody 和 TextControl 组件。
首先将这些导入添加到您的 Edit 组件的顶部。
打开 src 目录中的 edit.js 文件,找到导入 useBlockProps 的那一行。
import { useBlockProps, InspectorControls } from '@wordpress/block-editor';
import { PanelBody, TextControl } from '@wordpress/components';
InspectorControls 组件也可以以相同的方式从 @wordpress/block-editor 包中导入。
import { useBlockProps, InspectorControls } from '@wordpress/block-editor';
PanelBody 和 TextControl 组件可以通过相同的方式从 @wordpress/components 包中导入。
import { PanelBody, TextControl } from '@wordpress/components';
现在你可以使用这些组件为区块侧边栏添加控件。
首先,在 Edit 组件的输出中添加 InspectorControls 组件。该组件是区块侧边栏中控件的包装容器。
然后添加一个 PanelBody 组件,并为其设置 title 属性。
<InspectorControls>
<PanelBody title={ __( 'Settings', 'copyright-date-block' ) }>
Settings
</PanelBody>
</InspectorControls>
在“构建你的第一个区块”课程中,你应该记得 React 组件只能返回一个父级容器。
目前你还没有一个单一的父级容器,因为你在段落组件旁边添加了 InspectorControls 组件。
这也是你的 IDE 可能会提示代码存在问题的原因。
此时,你有两个选择。
你可以更新 Edit 组件,使其渲染一个父级 div 标签,并将区块属性移到父级 div 上。
<div { ...useBlockProps() }>
<InspectorControls>
<PanelBody title={ __( 'Settings', 'copyright-date-block' ) }>
Testing
</PanelBody>
</InspectorControls>
<p>
{ __(
'Copyright',
'copyright-date-block'
) }
© { startingYear } - { currentYear }
</p>
</div>
或者,你可以使用 React Fragment 将所有内容包裹在一个父级容器中。
<>
<InspectorControls>
<PanelBody title='Settings'>
Testing
</PanelBody>
</InspectorControls>
<p { ...useBlockProps() }>
{ __(
'Copyright',
'copyright-date-block'
) }
© { startingYear } - { currentYear }
</p>
</>
由于该区块的功能实际上只需要段落标签,因此在这种情况下使用 Fragment 是最佳选择。如果你的区块需要更多标记,例如段落上方的标题标签,那么使用 div 选项可能更合理。
构建过程完成后,如果你将区块添加到文章或页面,并启用编辑器设置侧边栏,你将看到添加到区块侧边栏的设置面板。
为了遵循 WordPress 插件开发实践,你可能需要进行一个小更新:使用 __() 函数来翻译 PanelBody 组件的标题。
<PanelBody title={ __( 'Settings', 'copyright-date-block' ) }>
向区块侧边栏添加 TextControl
设置面板就位后,你现在可以添加一个 TextControl 组件,让用户编辑你的属性。
TextControl 组件是一个文本输入字段,允许用户输入字符串。你需要在 TextControl 组件上设置三个属性。前两个是标签和值:
label:输入字段上方显示的标签
value:输入字段的值
让我们看看这会是怎样的效果:
<PanelBody title={ __( 'Settings', 'copyright-date-block' ) }>
<TextControl
label={ __( 'Starting Year', 'copyright-date-block' ) }
value={ startingYear }
/>
</PanelBody>
你需要设置的另一个属性是 onChange 属性。该属性是一个函数,当输入字段的值发生变化时被调用,并接收用户输入的新值。
<PanelBody title={ __( 'Settings', 'copyright-date-block' ) }>
<TextControl
label={ __( 'Starting Year', 'copyright-date-block' ) }
value={ startingYear }
onChange={ ( newStartingYear ) => {
// update startingYear with newValue
} }
/>
</PanelBody>
然后,该函数用于更新区块的 startingYear 属性。
这个函数的语法与你之前看到的略有不同。这是一个箭头函数语法的示例,它是 JavaScript 中编写函数的一种更简洁的方式。
为了更新属性,你可以使用传递给 Edit 组件的 props 对象上的另一个属性——setAttributes 函数。该函数用于将区块的任何属性更新为新值。
你可以将 setAttributes 添加到从 props 对象解构的属性列表中,然后使用它来更新 startingYear 属性。
export default function Edit( { attributes, setAttributes } ) {
然后,要更新 startingYear 属性,你需要使用 setAttributes 函数,并将 startingYear 属性的新值传递给它。
<PanelBody title={ __( 'Settings', 'copyright-date-block' ) }>
<TextControl
label={ __( 'Starting Year', 'copyright-date-block' ) }
value={ startingYear }
onChange={ ( newStartingYear ) => {
setAttributes( { startingYear: newStartingYear } );
} }
/>
</PanelBody>
等待构建过程完成,然后将区块添加到文章或页面。你会看到现在可以在区块侧边栏中更改起始年份的值,并且区块会实时更新。
你还可以将区块编辑器切换到代码编辑器视图,你会看到起始年份值以 JSON 对象的形式存储在区块包装器上。
最后,如果你预览区块,它会使用 startingYear 属性的新值。
其他资源
如需进一步阅读这些主题,请务必查看区块编辑器手册中的属性指南。