搞了半天的WordPress块设置,一刷新页面就回到解放前?这谁顶得住啊!别慌,今天就来盘盘怎么把这些选项值真正存到块属性里,让设置不再“翻车”。

2,472字
10–16 分钟
in

自定义块开发中,设置面板(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重新渲染。

字段名示例值说明
countryEngland国家代码或名称
leaguePremier联赛标识
season2023-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数据”那集的内容了,这里不展开。至少现在,块设置不会一刷新就归零,绝绝子!