这是我上一篇关于 “在前端的 WordPress 块中呈现外部 API 数据”. 在最后一个中,我们学习了如何获取外部 API 并将其与一个块集成,该块在 WordPress 网站的前端呈现获取的数据。
问题是,我们以一种阻止我们在 WordPress 块编辑器中看到数据的方式完成了这项工作。 换句话说,我们可以在页面上插入块,但我们无法预览它。 我们只有在区块发布时才能看到它。
让我们重新回顾一下我们在上一篇文章中制作的示例块插件。 只有这一次,我们将利用 WordPress 的 JavaScript 和 React 生态系统在后端块编辑器中获取和呈现该数据。
我们离开的地方
当我们开始这件事时, 这是一个演示 我们在您可以参考的上一篇文章中登陆的地方。 你可能已经注意到我使用了 render_callback
上一篇文章中的方法,以便我可以利用 PHP 文件中的属性并呈现内容。
好吧,这在您可能必须使用一些本机 WordPress 或 PHP 函数来创建动态块的情况下可能很有用。 但是,如果您只想使用 WordPress 的 JavaScript 和 React(特别是 JSX)生态系统来呈现静态 HTML 以及存储在数据库中的属性,您只需要关注 Edit
和 Save
块插件的功能。
-
Edit
函数根据您希望在块编辑器中看到的内容呈现内容。 您可以在此处拥有交互式 React 组件。 -
Save
函数根据您想在前端看到的内容呈现内容。 你不能在这里拥有常规的 React 组件或钩子。 它用于返回与属性一起保存到数据库中的静态 HTML。
Save
函数是我们今天闲逛的地方。 我们可以在前端创建交互式组件,但为此我们需要在前端手动包含和访问它们 Save
像我们在上一篇文章中所做的那样在文件中运行。
因此,我将介绍我们在上一篇文章中所做的相同内容,但这次您可以在块编辑器中看到预览 before 您将其发布到前端。
方块道具
我故意省略了关于 edit
上一篇文章中的函数道具,因为那会使焦点从主要点,渲染上移开。
如果你有 React 背景,你可能会明白我在说什么,但如果你是新手,我会推荐 查看 React 文档中的组件和道具.
如果我们记录 props
对象到控制台,它返回与我们的块相关的 WordPress 函数和变量的列表:
我们只需要 attributes
对象和 setAttributes
我将从中解构的函数 props
我的代码中的对象。 在上一篇文章中,我修改了 RapidAPI 的代码,以便我可以通过以下方式存储 API 数据 setAttributes()
. 道具只是可读的,所以我们无法直接修改它们。
块道具类似于状态变量和 setState
在 React 中,但 React 在客户端工作,并且 setAttributes()
用于在保存帖子后将属性永久存储在 WordPress 数据库中。 所以,我们需要做的就是将它们保存到 attributes.data
然后调用它作为初始值 useState()
变量。
edit
功能
我将复制粘贴我们在 football-rankings.php
在上一篇文章中并稍微编辑一下以转移到 JavaScript 背景。 还记得我们在上一篇文章中是如何为前端样式和脚本创建两个附加文件的吗? 以我们今天处理事物的方式,无需创建这些文件。 相反,我们可以将其全部移至 Edit
功能。
完整代码
import { useState } from "@wordpress/element";
export default function Edit(props) {
const { attributes, setAttributes } = props;
const [apiData, setApiData] = useState(null);
function fetchData() {
const options = {
method: "GET",
headers: {
"X-RapidAPI-Key": "Your Rapid API key",
"X-RapidAPI-Host": "api-football-v1.p.rapidapi.com",
},
};
fetch(
"https://api-football-v1.p.rapidapi.com/v3/standings?season=2021&league=39",
options
)
.then((response) => response.json())
.then((response) => {
let newData = { ...response }; // Deep clone the response data
setAttributes({ data: newData }); // Store the data in WordPress attributes
setApiData(newData); // Modify the state with the new data
})
.catch((err) => console.error(err));
}
return (
{apiData && (
Rank
Logo
Team name
GP
GW
GD
GL
GF
GA
Pts
Form history
{/* Usage of [0] might be weird but that is how the API structure is. */}
{apiData.response[0].league.standings[0].map((el) => {
{/* Destructure the required data from all */}
const { played, win, draw, lose, goals } = el.all;
return (
{el.rank}
{el.team.name}
{played}
{win}
{draw}
{lose}
{goals.for}
{goals.against}
{el.points}
{el.form.split("").map((result) => {
return (
{result}
);
})}
);
}
)}
)}
);
}
我已经包含了 React 钩子 useState()
止 @wordpress/element
而不是从 React 库中使用它。 那是因为如果我以常规方式加载,它会为我正在使用的每个块下载 React。 但是如果我使用 @wordpress/element
它从单一来源加载,即 React 之上的 WordPress 层。
这一次,我也没有把代码包裹在里面 useEffect()
但是在一个仅在单击按钮时调用的函数内部,以便我们可以实时预览获取的数据。 我使用了一个名为的状态变量 apiData
有条件地渲染排行榜。 因此,一旦单击按钮并获取数据,我正在设置 apiData
到里面的新数据 fetchData()
并且有可用的足球排名表的 HTML 重新渲染。
您会注意到,一旦保存帖子并刷新页面,排行榜就消失了。 那是因为我们使用的是空状态(null
) apiData
的初始值。 帖子保存时,属性会保存到 attributes.data
对象,我们称它为初始值 useState()
像这样的变量:
const [apiData, setApiData] = useState(attributes.data);
save
功能
我们将对 save
功能,但稍微修改一下。 比如前端不需要“获取数据”按钮, apiData
状态变量也是不必要的,因为我们已经在 edit
功能。 但我们确实需要随机 apiData
检查变量 attributes.data
有条件地渲染 JSX,否则它将抛出未定义的错误,并且块编辑器 UI 将变为空白。
完整代码
export default function save(props) {
const { attributes, setAttributes } = props;
let apiData = attributes.data;
return (
{/* Only render if apiData is available */}
{apiData && (
Rank
Logo
Team name
GP
GW
GD
GL
GF
GA
Pts
Form history
{/* Usage of [0] might be weird but that is how the API structure is. */}
{apiData.response[0].league.standings[0].map((el) => {
const { played, win, draw, lose, goals } = el.all;
return (
{el.rank}
{el.team.name}
{played}
{win}
{draw}
{lose}
{goals.for}
{goals.against}
{el.points}
{el.form.split("").map((result) => {
return (
{result}
);
})}
);
})}
)}
);
}
如果您正在修改 save
块编辑器中已经存在块之后的函数,它会显示如下错误:
那是因为保存内容中的标记与我们新建的标记不同 save
功能。 由于我们处于开发模式,因此更容易从当前页面中删除块并将其重新插入为新块——这样,更新的代码就会被使用,并且事情会恢复同步。
如果我们使用了 render_callback
方法,因为输出是动态的,由 PHP 而不是保存函数控制。 所以每种方法都有它自己的优点和缺点。
汤姆·诺威尔 (Tom Nowell) 对在 save
功能 这个堆栈溢出 回答.
在编辑器和前端中设置块的样式
关于样式,它与我们在上一篇文章中看到的几乎相同,但有一些我在评论中解释过的细微变化。 我只是在这里提供完整的样式,因为这只是一个概念证明,而不是你想要复制粘贴的东西(除非你真的需要一个块来显示像这样风格的足球排名)。 请注意,我仍在使用在构建时编译为 CSS 的 SCSS。
编辑器样式
/* Target all the blocks with the data-title="Football Rankings" */
.block-editor-block-list__layout
.block-editor-block-list__block.wp-block[data-title="Football Rankings"] {
/* By default, the blocks are constrained within 650px max-width plus other design specific code */
max-width: unset;
background: linear-gradient(to right, #8f94fb, #4e54c8);
display: grid;
place-items: center;
padding: 60px 0;
/* Button CSS - From: https://getcssscan.com/css-buttons-examples - Some properties really not needed :) */
button.fetch-data {
align-items: center;
background-color: #ffffff;
border: 1px solid rgb(0 0 0 / 0.1);
border-radius: 0.25rem;
box-shadow: rgb(0 0 0 / 0.02) 0 1px 3px 0;
box-sizing: border-box;
color: rgb(0 0 0 / 0.85);
cursor: pointer;
display: inline-flex;
font-family: system-ui, -apple-system, system-ui, "Helvetica Neue", Helvetica, Arial, sans-serif;
font-size: 16px;
font-weight: 600;
justify-content: center;
line-height: 1.25;
margin: 0;
min-height: 3rem;
padding: calc(0.875rem - 1px) calc(1.5rem - 1px);
position: relative;
text-decoration: none;
transition: all 250ms;
user-select: none;
-webkit-user-select: none;
touch-action: manipulation;
vertical-align: baseline;
width: auto;
&:hover,
&:focus {
border-color: rgb(0, 0, 0, 0.15);
box-shadow: rgb(0 0 0 / 0.1) 0 4px 12px;
color: rgb(0, 0, 0, 0.65);
}
&:hover {
transform: translateY(-1px);
}
&:active {
background-color: #f0f0f1;
border-color: rgb(0 0 0 / 0.15);
box-shadow: rgb(0 0 0 / 0.06) 0 2px 4px;
color: rgb(0 0 0 / 0.65);
transform: translateY(0);
}
}
}
前端样式
/* Front-end block styles */
.wp-block-post-content .wp-block-football-rankings-league-table {
background: linear-gradient(to right, #8f94fb, #4e54c8);
max-width: unset;
display: grid;
place-items: center;
}
#league-standings {
width: 900px;
margin: 60px 0;
max-width: unset;
font-size: 16px;
.header {
display: grid;
gap: 1em;
padding: 10px;
grid-template-columns: 1fr 1fr 3fr 4fr 3fr;
align-items: center;
color: white;
font-size: 16px;
font-weight: 600;
background-color: transparent;
background-repeat: no-repeat;
background-size: contain;
background-position: right;
.stats {
display: flex;
gap: 15px;
& > div {
width: 30px;
}
}
}
}
.league-table {
background: white;
box-shadow:
rgba(50, 50, 93, 0.25) 0px 2px 5px -1px,
rgba(0, 0, 0, 0.3) 0px 1px 3px -1px;
padding: 1em;
.position {
width: 20px;
}
.team {
display: grid;
gap: 1em;
padding: 10px 0;
grid-template-columns: 1fr 1fr 3fr 4fr 3fr;
align-items: center;
}
.team:not(:last-child) {
border-bottom: 1px solid lightgray;
}
.team-logo img {
width: 30px;
top: 3px;
position: relative;
}
.stats {
display: flex;
gap: 15px;
& > div {
width: 30px;
text-align: center;
}
}
.last-5-games {
display: flex;
gap: 5px;
& > div {
width: 25px;
height: 25px;
text-align: center;
border-radius: 3px;
font-size: 15px;
& .result-W {
background: #347d39;
color: white;
}
& .result-D {
background: gray;
color: white;
}
& .result-L {
background: lightcoral;
color: white;
}
}
}
我们将此添加到 src/style.scss
它负责编辑器和前端的样式。 我将无法分享演示 URL,因为它需要编辑器访问权限,但我录制了一段视频供您观看演示:
很整洁,对吧? 现在我们有了一个功能齐全的块,它不仅可以在前端渲染,还可以获取 API 数据并直接在块编辑器中渲染——带有一个刷新按钮来启动!
但如果我们想采取 , 利用 WordPress 块编辑器的优势,我们应该考虑将块的一些 UI 元素映射到 块控制 用于设置颜色、排版和间距等。 这是块开发学习之旅的一个很好的下一步。