WordPress管理界面重新设计预览
WordPress正处于管理界面重新设计的过程中。在这个过渡阶段,管理界面由两部分组成:已存在十多年的“经典”界面,以及随区块和站点编辑器而来的“现代”界面。
如果你正在构建一个需要设置页面的插件,并且希望与WordPress核心用户体验保持一致,那么现在就开始采用将成为新标准的设计元素和模式是值得的。
一种方法是在构建设置页面时使用WordPress React组件。《如何为插件页面使用WordPress React组件》一文介绍了这种方法。然而,得益于过去一年左右许多人的工作,现在有一个值得考虑和探索的可行替代方案。
在本文中,你将学习如何重建之前使用独立React组件构建的相同设置页面,但这次使用DataForm。DataForm组件提供了一种声明式创建表单和面板的方法,无需导入单独的组件。
作为预览,以下是设置页面当前的外观:

以下是重构完成后的最终结果:

前提条件
本文假设你已经阅读过《如何为插件页面使用WordPress React组件》并熟悉其中构建的内容。如果还没有,现在是个好时机!
本文不涉及如何注册管理页面、加载资源或通过REST API注册和公开设置。所有这些都在前一篇文章中介绍过,并且保持不变。
如果你想跟着操作,可以下载或克隆Unadorned Announcement Bar插件的仓库作为起点,并按照设置说明操作。本文的工作从前一篇文章结束的地方继续。
如果你在任何地方卡住了,可以将你的更改与dataform-refactor分支进行比较。每个步骤都单独提交了。
原始的SettingsPage组件
“原始”的设置页面组件由多个组件和一个用于管理状态的自定义Hook组成。
SettingsPage组件的代码如下所示:
const SettingsPage = () => {
const {
message,
setMessage,
display,
setDisplay,
size,
setSize,
saveSettings,
} = useSettings();
return (
<>
<SettingsTitle />
<Notices />
<Panel>
<PanelBody>
<PanelRow>
<MessageControl
value={ message }
onChange={ ( value ) => setMessage( value ) }
/>
</PanelRow>
<PanelRow>
<DisplayControl
value={ display }
onChange={ ( value ) => setDisplay( value ) }
/>
</PanelRow>
</PanelBody>
<PanelBody
title={ __( 'Appearance', 'unadorned-announcement-bar' ) }
initialOpen={ false }
>
<PanelRow>
<SizeControl
value={ size }
onChange={ ( value ) => setSize( value ) }
/>
</PanelRow>
</PanelBody>
</Panel>
<SaveButton onClick={ saveSettings } />
</>
);
};
所有内容都是使用@wordpress/components包中的组件构建的。即使是像MessageControl这样的自定义组件,也仅仅是WordPress提供的组件的包装器:
const MessageControl = ( { value, onChange } ) => {
return (
<TextareaControl
label={ __( 'Message', 'unadorned-announcement-bar' ) }
value={ value }
onChange={ onChange }
__nextHasNoMarginBottom
/>
);
};
使用DataForm时,不需要这些单独的组件,只需要DataForm本身。
安装@wordpress/dataviews包
第一步,安装@wordpress/dataviews包,因为DataForm组件是其中的一部分。
在插件文件夹内运行以下命令:
npm install @wordpress/dataviews --save
接下来,通过在你的/src/components/settings-page.jsx文件开头添加以下内容来导入DataForm:
import { DataForm } from '@wordpress/dataviews/wp';
目前,在WordPress环境中使用@wordpress/dataviews(与独立应用相对)时,必须从@wordpress/dataviews/wp导入,以确保依赖项正确解析。
添加DataForm组件
由于你的settings-page.jsx文件中不再需要大多数独立组件,你可以将整个Panel组件及其子组件替换为DataForm组件:
const SettingsPage = () => {
const {
// ...
} = useSettings();
return (
<>
<SettingsTitle />
<Notices />
<DataForm />
<SaveButton onClick={ saveSettings } />
</>
);
};
DataForm需要一些属性(data、fields、form、onChange),但现在你可以提供空值来开始。你马上就会看到它们的用途。
更改后,settings-page.jsx应该如下所示:
const SettingsPage = () => {
const {
// ...
} = useSettings();
const data = {};
const fields = [];
const form = {};
return (
<>
<SettingsTitle />
<Notices />
<DataForm
data={ data }
fields={ fields }
form={ form }
onChange={ () => {} }
/>
<SaveButton onClick={ saveSettings } />
</>
);
};
虽然你可以将属性值内联,但使用变量会使代码更易读,因为这些值将有多行长。
如果你刷新设置页面,应该只看到标题和保存按钮,就像从一张白纸开始一样。

配置表单字段
DataForm是配置驱动的。要定义一个字段,你至少需要提供一个id、一个label和一个type。
id是字段的唯一标识符,可以是任何字符串。label是UI中显示的字段名称。
type定义了字段持有的数据类型,包括text、integer、boolean、datetime等。有关完整列表,请查看文档,因为列表会随着包的演进而增长。
添加消息字段
对于消息字段,使用text类型,因为它需要是一个自由格式的文本字段。
要添加配置,请更新settings-page.jsx中的fields变量,该变量将保存所有字段的配置:
const SettingsPage = () => {
// ...
const data = {};
const fields = [
{
id: 'message',
label: __( 'Message', 'unadorned-announcement-bar' ),
type: 'text',
},
];
const form = {};
// ..
};
这定义了字段但并未渲染它。要实际显示消息字段,需要在form变量中包含字段的id:
const SettingsPage = () => {
// ...
const data = {};
const fields = [
{
id: 'message',
// ...
}
];
const form = {
fields: [ 'message' ],
};
// ..
};
最后,你必须通过更新data变量来定义一个初始值。现在,将message字段设置为空字符串。
更新后的settings-page.jsx代码应如下所示:
const SettingsPage = () => {
// ...
const data = {
message: '',
};
const fields = [
{
id: 'message',
// ...
}
];
const form = {
fields: [ 'message' ],
};
// ..
};
此时,如果你刷新插件的设置页面,应该会看到一个文本输入框被渲染出来。

虽然它不像之前那样是文本区域,但你很快就会看到如何改变这一点。
添加显示字段
你可以对显示字段采用相同的方法。这次使用boolean类型而不是text类型,因为它代表开/关状态。
按如下方式更新settings-page.jsx中的变量:
const SettingsPage = () => {
// ...
const data = {
message: '',
display: false,
};
const fields = [
{
id: 'message',
// ...
},
{
id: 'display',
label: __( 'Display', 'unadorned-announcement-bar' ),
type: 'boolean',
},
];
const form = {
fields: [ 'message', 'display' ],
};
// ..
};
在浏览器中刷新设置页面后,你应该会看到消息字段下方渲染了一个复选框字段。

添加字体大小字段
剩下的字段是字体大小。这应该允许用户从预定义的选项(如小、中等和其他)中进行选择。
DataForm中没有专门的“选择”类型。相反,使用text类型(因为值以字符串形式存储),并添加可选的elements属性来定义选项。当存在elements时,DataForm会渲染一个选择输入而不是文本输入。
更新后,settings-page.jsx应如下所示:
const SettingsPage = () => {
// ...
const data = {
message: '',
display: false,
size: 'small',
};
const fields = [
{
id: 'message',
// ...
},
{
id: 'display',
// ...
},
{
id: 'size',
label: __( 'Font size', 'unadorned-announcement-bar' ),
type: 'text',
elements: [
{
value: 'small',
label: __( 'Small', 'unadorned-announcement-bar' ),
},
{
value: 'medium',
label: __( 'Medium', 'unadorned-announcement-bar' ),
},
{
value: 'large',
label: __( 'Large', 'unadorned-announcement-bar' ),
},
{
value: 'x-large',
label: __( 'Extra Large', 'unadorned-announcement-bar' ),
},
]
}
];
const form = {
fields: [ 'message', 'display', 'size' ],
};
// ..
};
这样,你的设置页面应该有三个字段,无需导入任何特定组件,全部通过配置对象定义。

自定义字段UI组件
当你为字段指定type而没有额外配置时,每种类型都会映射到一个默认的UI组件。
正如你所看到的,当未定义元素时,text类型会渲染一个文本输入。boolean会渲染一个复选框。
但是,你可以通过指定Edit属性来更改默认的UI组件。最简单的选项是使用预定义的UI组件之一:textarea、toggle、radio、toggleGroup等。
要完成此操作,请按如下方式将Edit属性添加到settings-page.jsx中的字段:
const SettingsPage = () => {
// ...
const fields = [
{
id: 'message',
// ...
Edit: 'textarea',
},
{
id: 'display',
// ...
Edit: 'toggle',
},
{
id: 'size',
// ...
Edit: 'toggleGroup',
},
];
// ..
};
现在,如果你刷新设置页面,应该会看到字段显示为文本区域、切换开关和切换组。

如果你需要的不仅仅是内置的UI组件,你可以使用自己的自定义组件。这允许你使用配置来驱动设置页面,而不受可用UI组件的限制。
请参阅文档以了解如何操作以及当前有哪些内置组件可用。新的组件会随着时间的推移而添加!
配置表单布局
此时,你拥有了与之前相同的控件,但布局不同。字段没有分组到面板下,字体大小控件默认也没有隐藏。
DataForm不仅允许你使用配置定义字段,还可以配置用于显示它们的整体布局。
将字段分组到部分
要重新创建之前的布局,请将字段分组到不同的部分。为此,请按如下方式更新settings-page.jsx中的form变量:
const SettingsPage = () => {
// ...
const form = {
fields: [
{
id: 'bar',
label: __( 'Bar', 'unadorned-announcement-bar' ),
children: [ 'message', 'display' ],
},
{
id: 'appearance',
label: __( 'Appearance', 'unadorned-announcement-bar' ),
children: [ 'size' ],
},
],
};
// ..
};
配置需要一个id和一个label,就像字段定义一样。但是,不是定义type,而是将现有字段分配为children。
如果你刷新设置,可以看到字段被分成了两个部分。

切换布局类型
默认情况下,DataForm使用regular布局,这是隐式的,它将字段一个接一个地排列在单独的行中。但是,还有其他可用的布局:panel、card和row。
卡片布局最接近“原始设计”,但也可以尝试其他布局,看看它们的外观!
要切换到卡片布局,请按如下方式更新settings-page.jsx中form的配置:
const SettingsPage = () => {
// ...
const form = {
fields: [
{
id: 'bar',
// ...
layout: { type: 'card' },
},
{
id: 'appearance',
// ...
layout: { type: 'card' },
},
],
};
// ..
};
如果适合你,你甚至可以分别为每个组混合和匹配布局类型,从而创建各种组合。

调整布局选项
根据布局,你可以指定其他设置。
例如,对于card布局,你可以控制是否显示标题,或者卡片本身默认是展开还是折叠。要查看每种类型的所有选项,请查看文档。
要从第一个组中移除标题并使第二个组默认折叠,请按如下方式修改layout配置:
const SettingsPage = () => {
// ...
const form = {
fields: [
{
id: 'bar',
// ...
layout: { type: 'card', withHeader: false },
},
{
id: 'appearance',
// ...
layout: { type: 'card', isOpened: false },
},
],
};
// ..
};
进行此更改后,如果你刷新设置页面,UI将与之前存在的界面非常接近。

某些元素的间距和宽度仍需要微调,但这些问题可以通过使用VStack和自定义CSS来解决。
只需几行代码,你就可以完善这些细节以达到最终结果:

由于编写CSS超出了本文的整体范围,请参考GitHub仓库以查看其实现方式。
将DataForm连接到settings状态
设置页面已渲染,但它仍然使用传递给DataForm的硬编码data,并且onChange尚未实现:
const SettingsPage = () => {
const {
// ...
} = useSettings();
const data = {
message: '',
display: false,
size: 'small',
};
// ...
return (
<>
<SettingsTitle />
<Notices />
<DataForm
data={ data }
fields={ fields }
form={ form }
onChange={ () => {} }
/>
<SaveButton onClick={ saveSettings } />
</>
);
};
最后一步是将DataForm与处理状态管理的useSettings自定义Hook连接起来。
重构useSettings Hook
目前,字段的状态使用三个useState调用单独存储,但实际设置是作为对象在unadorned_announcement_bar键下获取和保存的。
作为参考,以下是当前自定义Hook在/src/hooks/use-settings.js中的代码:
const useSettings = () => {
const [ message, setMessage ] = useState();
const [ display, setDisplay ] = useState();
const [ size, setSize ] = useState();
const { createSuccessNotice } = useDispatch( noticesStore );
useEffect( () => {
apiFetch( { path: '/wp/v2/settings' } ).then( ( wpSettings ) => {
setMessage( wpSettings.unadorned_announcement_bar.message );
setDisplay( wpSettings.unadorned_announcement_bar.display );
setSize( wpSettings.unadorned_announcement_bar.size );
} );
}, [] );
const saveSettings = () => {
apiFetch( {
path: '/wp/v2/settings