EP155. “新插件起步:用 Starter 模板跳过样板代码”
🔒 登录后可标记已读开始做第二个 Block 类型练习项目——Featured Professor(教授推荐卡):在文章里选一位 Professor 文章类型的实例,插入一张实时拉取该 Professor 最新数据渲染出来的推荐卡片,且这个关联是双向的(Professor 详情页也会反过来列出「被哪些文章提到」)。因为前几个插件已经把「注册脚本/样式、注册 Block、创建插件类」这套样板代码写过很多遍,这一讲用课程提供的 Starter 压缩包直接跳过这些没有新概念的重复劳动,规定插件文件夹要重命名成 featured-professor。这一讲的实际内容是先跑通 npm init -y + 安装 @wordpress/scripts、把 build/start 脚本写进 package.json,再动手搭出一个先用假数据(1/2/3)硬编码的下拉选择框,新增 profId 字符串属性存储选中值,验证「选完之后刷新页面还记得选择」这条数据链路先通了,再在下一讲换成真正查询 Professor 文章列表。
涉及文件
wp-content/plugins/featured-professor/featured-professor.php(课程提供的 Starter 模板,未修改,直接使用)wp-content/plugins/featured-professor/src/index.scss(课程提供的 Starter 模板,未修改,直接使用)wp-content/plugins/featured-professor/package.json(新建)wp-content/plugins/featured-professor/src/index.js(修改,基于 Starter 模板)
代码实现
featured-professor.php(Starter 模板原样,插件基础骨架):
<?php
if( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
class FeaturedProfessor {
function __construct() {
add_action('init', [$this, 'onInit']);
}
function onInit() {
wp_register_script('featuredProfessorScript', plugin_dir_url(__FILE__) . 'build/index.js', array('wp-blocks', 'wp-i18n', 'wp-editor'));
wp_register_style('featuredProfessorStyle', plugin_dir_url(__FILE__) . 'build/index.css');
register_block_type('ourplugin/featured-professor', array(
'render_callback' => [$this, 'renderCallback'],
'editor_script' => 'featuredProfessorScript',
'editor_style' => 'featuredProfessorStyle'
));
}
function renderCallback($attributes) {
return '<p>We will replace this content soon.</p>';
}
}
$featuredProfessor = new FeaturedProfessor();
终端命令:初始化 npm 项目、安装官方构建工具:
npm init -y
npm install @wordpress/scripts
package.json:scripts 里新增 build/start:
"scripts": {
"build": "wp-scripts build",
"start": "wp-scripts start",
"test": "echo \"Error: no test specified\" && exit 1"
}
src/index.js:把占位文字换成硬编码假数据的下拉选择框,接上 profId 属性:
import "./index.scss"
wp.blocks.registerBlockType("ourplugin/featured-professor", {
title: "Professor Callout",
description: "Include a short description and link to a professor of your choice",
icon: "welcome-learn-more",
category: "common",
attributes: {
profId: {type: "string"}
},
edit: EditComponent,
save: function () {
return null
}
})
function EditComponent(props) {
return (
<div className="featured-professor-wrapper">
<div className="professor-select-container">
<select onChange={e => props.setAttributes({profId: e.target.value})}>
<option value="">Select a professor</option>
<option value="1" selected={props.attributes.profId == 1}>1</option>
<option value="2" selected={props.attributes.profId == 2}>2</option>
<option value="3" selected={props.attributes.profId == 3}>3</option>
</select>
</div>
<div>
The HTML preview of the selected professor will appear here.
</div>
</div>
)
}
关键改动点:
- Starter 压缩包只提供插件骨架,不含任何新概念:PHP 类、
init钩子里注册脚本/样式/Block(写法跟之前几个插件完全一致)、render_callback先返回一段占位文字;JS 端的EditComponent先返回两个占位<div>(一个给下拉框用、一个给预览卡片用),registerBlockType也先不带attributes - 用 Starter 模板时要注意:
EditComponent原本没有声明props参数(因为还没接任何属性),这一讲第一次用到props.setAttributes()/props.attributes时要记得把这个参数补上——这是作者特别提醒的一个「Starter 模板本该带上但漏掉」的细节 npm init -y:-y让命令行跳过所有交互式提问,直接用默认值生成package.jsonnpm install @wordpress/scripts:这个插件项目还没有像 Quiz Block 插件那样用过任何第三方 npm 包,所以这是这个新插件资料夹里第一次跑npm installattributes: {profId: {type: "string"}}:即使 Professor 文章的 ID 本质是数字,属性类型依然选string——作者说这是自己长期实践下来的经验:WordPress 从数据库读出来的数据、以及做字符串比较时,用string类型更省心、更少踩坑<select onChange={e => props.setAttributes({profId: e.target.value})}>:下拉框整体绑定onChange,从事件对象e.target.value拿到用户选中的那个<option>的value- 第一个
<option value="">Select a professor</option>:没有默认必选值时的占位选项,value是空字符串 <option value="1" selected={props.attributes.profId == 1}>1</option>:每个选项都要单独判断「当前保存的profId是否等于这个选项的值」来决定要不要标记selected,这样刷新页面后下拉框才能正确回显之前选过的值——这里先用硬编码的 1/2/3 三个假选项验证这条「选择 → 存属性 → 刷新回显」的链路,下一讲会换成真正从数据库查出来的 Professor 列表
[截图:Gutenberg 编辑器里插入 Featured Professor Block,下拉框只有硬编码的 1/2/3 三个占位选项]
Hook / Function 速查
| 名称 | 类型 | 用途 |
|---|---|---|
npm init -y | npm 命令 | 跳过交互式提问,用默认值快速生成 package.json |
<option selected={布尔表达式}> | JSX/HTML 写法 | 用布尔表达式动态决定某个下拉选项是否默认选中 |
常见坑
- 用 Starter 模板时
EditComponent函数忘记补上props参数——一旦要用props.setAttributes()/props.attributes就会报错,因为函数体内根本没有这个变量 profId属性类型设成number——作者建议统一用string,跟 WordPress 数据库读出来的值、字符串比较逻辑更兼容,减少后续踩坑- 每个
<option>各自判断selected,如果拿错比较的属性名或者漏了某个选项没写selected判断——刷新页面后下拉框不会正确回显之前的选择
延伸 / 后续讲座会用到
下一讲要把这几个硬编码的假选项换成真正查询数据库里所有 Professor 文章、动态生成选项列表。
Sources
Udemy:
- Become a WordPress Developer: Unlocking Power With Code — Section 26, EP155