在区块编辑器中保存自定义 WordPress 区块的设置

Avatar of Manoj Kumar
Manoj Kumar

DigitalOcean 为您旅程的每个阶段提供云产品。 立即开始使用 200 美元的免费信用额度!

在本系列中,我们已经完成了很多事情! 我们创建了一个自定义 WordPress 区块,它从外部 API 获取数据并在前端呈现。 然后我们拿这项工作并对其进行了扩展,以便数据也直接在 WordPress 区块编辑器中呈现。 之后,我们使用 WordPress InspectorControls 中的组件创建了该区块的设置 UI。

我们还有最后一部分需要介绍,那就是保存设置选项。 如果我们回想起上一篇文章,我们实际上能够在区块设置 UI 中“保存”我们的选择,但这些选择实际上并没有存储在任何地方。 如果我们进行一些选择,保存它们,然后返回帖子,则设置将完全重置。

让我们闭环并保存这些设置,以便下次我们编辑包含自定义区块的帖子时,它们会保留!

在 WordPress 区块中使用外部 API

保存设置属性

我们正在使用一个 API,它为我们提供足球足球队的排名,我们用它来获取根据国家/地区、联赛和赛季显示排名的信息。 我们可以像这样为每个排名创建新的属性

// index.js

attributes: {
  data: {
    type: "object",
  },
  settings: {
    type: "object",
    default: {
      country: {
        type: "string",
      },
      league: {
        type: "string",
      },
      season: {
        type: "string",
      },
    },
  },
},

接下来,我们需要从 LeagueSettings.js 中设置属性。 每当我们的设置 UI 中的 ComboboxControl 更新时,我们需要使用 setAttributes() 方法设置属性。 当我们只使用一个数据端点时,这更加直接。 但现在我们有多个输入,它变得更加复杂了。

这是我将如何组织它。 我将在 LeagueSettings.js 中创建一个新对象,该对象遵循设置属性及其值的结构。

// LeagueSettings.js

let localSettings = {
  country: attributes.settings.country,
  league: attributes.settings.league,
  season: attributes.settings.season,
};

我还将从 null 更改初始状态变量到相应的设置变量。

// LeagueSettings.js

const [country, setCountry] = useState(attributes.settings.country);
const [league, setLeague] = useState(attributes.settings.league);
const [season, setSeason] = useState(attributes.settings.season);

在每个 handle______Change() 中,我将创建一个 setLocalAttributes(),它有一个参数,该参数克隆并使用新国家/地区、联赛和赛季值覆盖之前的 localSettings 对象。 这是在展开运算符的帮助下完成的。

// LeagueSettings.js

function handleCountryChange(value) {
  // Initial code
  setLocalAttributes({ ...localSettings, country: value });
  // Rest of the code
}

function handleLeagueChange(value) {
  // Initial code
  setLocalAttributes({ ...localSettings, league: value });
  // Rest of the code
}

function handleSeasonChange(value) {
  // Initial code
  setLocalAttributes({ ...localSettings, season: value });
  // Rest of the code
}

我们可以像这样定义 setLocalAttributes()

// LeagueSettings.js

function setLocalAttributes(value) {
  let newSettings = Object.assign(localSettings, value);
  localSettings = { ...newSettings };
  setAttributes({ settings: localSettings });
}

因此,我们使用 Object.assign() 合并这两个对象。 然后我们可以将 newSettings 对象克隆回 localSettings,因为我们还需要在进行新的选择并发生更改时考虑每个设置属性。

最后,我们可以像平常一样使用 setAttributes() 来设置最终对象。 你可以通过在 UI 中更新选择来确认上述属性是否正在改变。

另一种确认方法是在 DevTools 中执行 console.log() 来查找属性。

The block added to a post in the block editor with DevTools open showing the saved attributes.

仔细观察该截图。 这些值存储在 attributes.settings 中。 由于 React 每当我们在设置中进行更改时都会重新渲染,因此我们可以看到它实时发生,这要归功于 useState() 钩子。

在区块设置 UI 中显示值

将设置值存储在控制选项本身中并不是很有用,因为每个值都依赖于其他设置值(例如,按联赛的排名取决于选择了哪个赛季)。 但在设置值是静态的并且设置相互独立的情况下,它非常有用。

在不使当前设置复杂化的前提下,我们可以在设置面板中创建另一个部分来显示当前属性。 您可以选择自己的方式来显示设置值,但我将从 @wordpress/components 包中导入一个 Tip 组件

// LeagueSettings.js
import { Tip } from "@wordpress/components";

在写这段代码的时候,我将对值进行条件检查,然后再在 Tip 组件中显示它们

<Tip>
  {country && league && season && (
    <>
      <h2>Current Settings: </h2>
      <div className="current-settings">
        <div className="country">
          Country: {attributes.settings.country}
        </div>
        <div className="league">
          League: {attributes.settings.league}
        </div>
        <div className="season">
          Season: {attributes.settings.season}
        </div>
      </div>
    </>
  )}
</Tip>

以下是在区块编辑器中如何实现这一点

当可以显示实时数据而无需每次都手动更新它们时,API 数据更强大。 我们将在本系列的下一部分中探讨这个问题。