自定义块开发中,设置面板(InspectorControls)里的选项往往只是临时状态。通过定义
attributes.settings对象结构,配合setAttributes方法和对象合并技巧,就能把国家、联赛、赛季这些筛选条件永久绑定到块上。代码里用useState同步属性初始值,每次下拉框变动时触发Object.assign合并新数据,最终调用setAttributes完成存储。再配上Tip组件展示当前已存值,调试起来一目了然。
啥是块属性
WordPress块属性就像每个块的“记忆硬盘”。以足球排名块为例,需要记住三个关键筛选条件:国家、联赛、赛季。这些信息不能只飘在界面上,得刻进块的数据模型里。
定义属性时采用嵌套结构:
// index.js
attributes: {
data: {
type: "object",
},
settings: {
type: "object",
default: {
country: "",
league: "",
season: "",
},
},
},settings本身是个对象,里面每个字段对应一个筛选维度。默认值设为空字符串,等设置面板里选完再填充。
动手存设置
设置面板(LeagueSettings.js)里放着三个下拉框。每次点选,都得把新值塞进块的attributes.settings。这里用一个本地对象做中转站,避免直接操作属性导致的重复渲染。
第一步:建立本地中转对象
// LeagueSettings.js
let localSettings = {
country: attributes.settings.country,
league: attributes.settings.league,
season: attributes.settings.season,
};这个localSettings会实时跟进面板里的选择状态。接着把useState的初始值改成从attributes.settings里读:
const [country, setCountry] = useState(attributes.settings.country);
const [league, setLeague] = useState(attributes.settings.league);
const [season, setSeason] = useState(attributes.settings.season);这样做的好处是:刷新编辑器后,useState能从已经存好的属性里拿到旧值,下拉框就不会变空白。
第二步:改写每个下拉框的变更函数
以国家选择为例:
function handleCountryChange(value) {
setCountry(value);
setLocalAttributes({ ...localSettings, country: value });
// 这里原本还有请求联赛列表的逻辑,保留不动
}setLocalAttributes是整个存储流程的核心:
function setLocalAttributes(value) {
let newSettings = Object.assign(localSettings, value);
localSettings = { ...newSettings };
setAttributes({ settings: localSettings });
}Object.assign把新传入的{ country: '某国' }合并到旧的localSettings里,得到newSettings。然后用扩展运算符克隆一份重新赋值给localSettings,确保下次合并时用的是最新对象。最后调用setAttributes,把整个settings对象存进块属性。
写代码时容易踩一个坑:如果直接写setAttributes({ settings: value }),会丢失没变更的其他字段。比如只改了国家,联赛和赛季就被覆盖成undefined。所以必须用合并的方式。
第三步:验证是否存进去了
打开浏览器开发者工具,在控制台输入wp.data.select('core/block-editor').getSelectedBlock().attributes,能看到settings下面已经有了选中的值。而且每次改下拉框,这个对象会实时更新——因为useState触发了React重新渲染。
| 字段名 | 示例值 | 说明 |
|---|---|---|
| country | England | 国家代码或名称 |
| league | Premier | 联赛标识 |
| season | 2023-24 | 赛季字符串 |
显示存好的值
光存不展示,调试时心里没底。在设置面板底部加一个区域,把当前已存的值列出来。从@wordpress/components引入Tip组件:
import { Tip } from "@wordpress/components";然后放在所有下拉框的后面:
<Tip>
{country && league && season && (
<>
<h2>当前已存:</h2>
<div className="current-settings">
<div>国家:{attributes.settings.country}</div>
<div>联赛:{attributes.settings.league}</div>
<div>赛季:{attributes.settings.season}</div>
</div>
</>
)}
</Tip>这个条件判断country && league && season确保三个值都非空时才显示。如果某个没选,整块就不展示,避免空信息占地方。
实际跑起来的效果:右侧设置面板里,三个下拉框下面会出现一个灰色小气泡(Tip的默认样式),里面清清楚楚写着当前保存的国家、联赛、赛季。以后不管怎么刷新页面,只要进到包含这个块的文章编辑界面,设置值都老老实实待在那里。
有一说一,这种存储方式只适合静态的、互不依赖的选项。如果联赛列表要根据国家动态变化,那就得另外处理——不过那是“实时API数据”那集的内容了,这里不展开。至少现在,块设置不会一刷新就归零,绝绝子!
