EP135. “第一个自定义 Block 类型:registerBlockType 基础”
🔒 登录后可标记已读插件开发第二章开篇:用 JavaScript 注册一个全新的 Gutenberg Block 类型。先用 PHP 新建插件骨架,把一个测试用的 JS 文件挂到「Block 编辑器」专属的资源加载钩子上(不是普通的前台/后台通用钩子);再用 WordPress 提供的全局对象 wp.blocks.registerBlockType() 注册一个最简单的 Block,分别用 edit(编辑器里长什么样)和 save(保存进数据库、前台显示的是什么)两个函数描述它。这一讲刻意先用 WordPress 原生的 wp.element.createElement() 手写 HTML 结构,为下一讲引入更好用的 JSX 语法做对比铺垫。
涉及文件
wp-content/plugins/are-you-paying-attention/index.php(新建)wp-content/plugins/are-you-paying-attention/test.js(新建)
代码实现
index.php(完整文件):
<?php
/*
Plugin Name: Are You Paying Attention Quiz
Description: Give your readers a multiple choice question.
Version: 1.0
Author: Brad
Author URI: https://www.udemy.com/user/bradschiff/
*/
if( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
class AreYouPayingAttention {
function __construct() {
add_action('enqueue_block_editor_assets', array($this, 'adminAssets'));
}
function adminAssets() {
wp_enqueue_script('ournewblocktype', plugin_dir_url(__FILE__) . 'test.js', array('wp-blocks', 'wp-element'));
}
}
$areYouPayingAttention = new AreYouPayingAttention();
test.js(完整文件):
wp.blocks.registerBlockType("ourplugin/are-you-paying-attention", {
title: "Are You Paying Attention?",
icon: "smiley",
category: "common",
edit: function () {
return wp.element.createElement("h3", null, "Hello, this is from the admin editor screen.")
},
save: function () {
return wp.element.createElement("h1", null, "This is the frontend.")
}
})
关键改动点:
enqueue_block_editor_assets是专属于 Block 编辑器页面的资源加载钩子,跟之前给普通后台页面加载资源用的admin_enqueue_scripts是不同的钩子——只在打开文章/页面编辑器时才会触发,不会影响其他后台页面wp_enqueue_script($handle, $src, $deps)的第三个参数(依赖数组)里写了wp-blocks和wp-element——这两个是 WordPress 核心自带的 JS 包,分别提供wp.blocks(注册/管理 Block 类型的工具)和wp.element(WordPress 自己包装的一层类 React 元素创建工具)。声明依赖能确保浏览器先加载好这两个包,我们自己的脚本才能安全地使用wp.blocks/wp.element这些全局对象,不会出现「用到时还没加载好」的问题wp.blocks.registerBlockType(name, config):第一个参数是 Block 的唯一标识符,格式固定是命名空间/短名(这里是ourplugin/are-you-paying-attention),命名空间通常用插件自己的名字,避免跟别的插件的 Block 撞名- 配置对象里的
title(用户在插入 Block 菜单里看到的名字)、icon(这里先用内建的 dashicon 短名smiley)、category(决定这个 Block 出现在插入菜单的哪个分类下,common是内建的通用分类)都是 WordPress 固定认的属性名,不能随便改 edit和save两个函数是一个 Block 类型的核心:edit控制的是编辑器里这个 Block 长什么样(作者可以互动编辑的界面);save控制的是最终存进数据库、前台访问者看到的内容——两者可以完全不同(这一讲故意让两者输出不同的标题级别和文字,来清楚区分这两个函数各自的职责)wp.element.createElement(tag, props, children)是 WordPress 提供的、不需要额外配置就能直接用的「创建 HTML 元素」的原生方式:第一个参数是标签名(字符串),第二个参数是属性对象(没有属性传null),第三个参数是子内容(文字或更多嵌套元素)——这个函数本质上就是 React 的createElement,只是套了 WordPress 自己的命名空间
📌 前台渲染的本质:save 函数返回的内容只是在你点击「更新/发布」的那一刻,被 WordPress 转换成一段静态 HTML 字符串(作为一个带特殊注释标记的 Block 序列化文本)存进数据库,前台访问者看到的页面完全不涉及 JavaScript 执行——数据库 post_content 字段里能直接看到类似 <!-- wp:ourplugin/are-you-paying-attention --> 这样的注释标记包裹着最终的 HTML。真正需要在前台跑 JavaScript(比如做互动问答的判分逻辑)要用课程后面才会讲到的另一种技巧。
[截图:Block 编辑器插入面板里搜到 "Are You Paying Attention?" Block、插入后编辑器内显示的 "Hello, this is from the admin editor screen." 效果]
Hook / Function 速查
| 名称 | 类型 | 用途 |
|---|---|---|
enqueue_block_editor_assets | WP hook | 只在 Block 编辑器页面触发的资源加载钩子 |
wp.blocks.registerBlockType(name, config) | WP 全局 JS 对象方法 | 注册一个新的 Gutenberg Block 类型 |
wp.element.createElement(tag, props, children) | WP 全局 JS 对象方法 | WordPress 原生的、不需要额外工具链就能用的 HTML 元素创建方式(本质是 React 的 createElement) |
常见坑
- 依赖数组里漏写
wp-blocks/wp-element——虽然 Block 编辑器页面几乎总是已经加载了这些包,属于「侥幸能用」,但明确声明依赖才是最佳实践,能避免未来 WordPress 内部加载顺序变化导致的意外故障 - 以为
save函数返回的内容在前台访问时还会重新执行 JavaScript——实际上只在编辑器里保存那一刻执行一次,结果被序列化成静态 HTML 存进数据库,前台纯粹是显示这段已经生成好的 HTML
延伸 / 后续讲座会用到
直接用 wp.element.createElement() 手写复杂 HTML 结构会很啰嗦,下一讲开始引入 JSX 语法(借助 WordPress 官方提供的 @wordpress/scripts 工具包简化配置),让 Block 的 HTML 结构写起来更接近真实 HTML。
Sources
Udemy:
- Become a WordPress Developer: Unlocking Power With Code — Section 24, EP135