CodeRoadMap
首页路线题库资源库文章社区
CodeRoadMap

程序员的学习成长路线图。内容免费开放,登录后可同步路线图与课时进度。

由 程序员柏风 独立维护 · 关于作者

学习

  • 路线图
  • 课程
  • 面试题
  • 文章
  • 我

更多

  • 资源
  • 社区
  • 关于作者
  • 内容说明

© 2026 CodeRoadMap

津ICP备2026012044号-1·津公网安备12011002026155号·coderoadmap@126.com
WordPress 开发入门/课时/区块编辑器
RawBlame
课时目录12 节

WordPress 开发入门

  1. 01WordPress 概览
  2. 02环境搭建
  3. 03主题开发
  4. 04区块编辑器
  5. 05插件生态
  6. 06Hooks 与 CPT
  7. 07PHP 架构
  8. 08数据库
  9. 09AJAX 与 Headless
  10. 10安全加固
  11. 11性能与运维
  12. 12综合练习

区块编辑器

Block、Loop 与 Shortcodes。

30 分钟

Gutenberg 区块开发

这一课你将能做到

  1. 用官方脚手架 create-block 生成、构建并在编辑器里插入一个自定义区块
  2. 读懂 block.json 的关键字段,为区块声明 attributes 并在编辑态读写
  3. 把区块改造成「动态区块」,用 render.php 在服务端实时输出内容(如最新文章列表)

为什么要学

WP 6.x 的编辑器整个建立在 Gutenberg 之上:文章、页面、主题模板都是区块的排列组合。会写区块,你就从「用别人插件的人」变成「造组件的人」;而且区块的 edit 组件是 React 写的——本站 java-nav 前端同款技术栈,学习成本直接复用。

人话:区块 = 编辑器里的 React 组件 + 前台的渲染输出。你在一个项目里同时练 React 和 PHP,这笔投资只赚不亏。

先建立图像

一个区块在两个世界里的样子:

编辑器(React 世界)            前台(PHP/HTML 世界)
┌─────────────────────┐        ┌──────────────────────┐
│ edit.js  编辑态 UI    │  保存   │ 静态区块: save.js 生成的│
│ attributes (状态)     │ ─────→ │ HTML 存进 post_content │
└─────────────────────┘        │ 动态区块: render.php    │
                               │ 服务端实时渲染          │
                               └──────────────────────┘
post_content 里的区块长这样:
<!-- wp:qrocmq/course-card {"level":"进阶"} /-->

静态区块把 HTML「焊死」进内容,动态区块只存锚点注释 + 属性,前台每次请求由 PHP 现渲染——要展示会变的数据,选动态。

跟着做

步骤 1:脚手架生成区块

前置:Node.js 20+。在插件开发目录执行:

npx @wordpress/create-block qrocmq-course-card --namespace=qrocmq
cd qrocmq-course-card
npm start        # 开发模式,热更新

启用生成的插件(或 wp plugin activate qrocmq-course-card),新建一篇文章,插入「Course Card」区块,输入文字,保存并预览——第一版已经能跑。

步骤 2:读懂 block.json

打开 src/block.json,核心字段:

{
    "$schema": "https://schemas.wp.org/trunk/block.json",
    "apiVersion": 3,
    "name": "qrocmq/course-card",
    "version": "1.0.0",
    "title": "Course Card",
    "category": "widgets",
    "icon": "welcome-learn-more",
    "description": "课程卡片:标题 + 难度",
    "attributes": {
        "title":   { "type": "string", "default": "课程标题" },
        "level":   { "type": "string", "default": "入门" }
    },
    "supports": {
        "html": false,
        "align": [ "wide", "full" ],
        "color": { "text": true, "background": true }
    },
    "textdomain": "qrocmq-course-card",
    "editorScript": "file:./index.js",
    "editorStyle": "file:./editor.css",
    "style": "file:./style.css"
}

name 规则:命名空间/小写连字符,全局唯一,不可改。

步骤 3:编辑态加一个难度选择

改 src/edit.js,用 RichText 编辑标题、用 Select 切难度:

import { useBlockProps, RichText } from '@wordpress/block-editor';

export default function Edit( { attributes, setAttributes } ) {
    const { title, level } = attributes;
    return (
        <div { ...useBlockProps() }>
            <RichText
                tagName="h3"
                value={ title }
                onChange={ ( v ) => setAttributes( { title: v } ) }
                placeholder="课程标题"
            />
            <select
                value={ level }
                onChange={ ( e ) => setAttributes( { level: e.target.value } ) }
            >
                <option value="入门">入门</option>
                <option value="进阶">进阶</option>
            </select>
        </div>
    );
}

保存刷新编辑器:属性变化即时生效,这就是 attributes 的读写闭环。

步骤 4:改成动态区块

动态区块不需要 save.js。把 src/save.js 改为:

export default function save() {
    return null;   // 交给服务端 render.php
}

在主入口 src/index.js 的 registerBlockType 所在文件旁,让 PHP 端注册渲染回调。新建 qrocmq-course-card.php(插件主文件已存在则在其中加):

<?php
/**
 * Plugin Name: QROCMQ Course Card
 * Requires PHP: 8.2
 */
add_action( 'init', function () {
    register_block_type( __DIR__ . '/build', array(
        'render_callback' => function ( $attributes ) {
            $recent = get_posts( array(
                'numberposts' => 3,
                'post_status' => 'publish',
            ) );
            $items = '';
            foreach ( $recent as $p ) {
                $items .= sprintf(
                    '<li><a href="%s">%s</a></li>',
                    esc_url( get_permalink( $p ) ),
                    esc_html( get_the_title( $p ) )
                );
            }
            return sprintf(
                '<div %1$s><h3>%2$s</h3><ul>%3$s</ul></div>',
                get_block_wrapper_attributes(),
                esc_html( $attributes['title'] ?? '' ),
                $items
            );
        },
    ) );
} );

npm run build 后,前台插入该区块的位置会实时输出最新 3 篇文章标题。

步骤 5:看产物

构建输出在 build/(block.json + index.js + css)。注意:线上部署的是 build 目录,src 只是源码。

讲清楚要点

  1. 注册是双向的:register_block_type() 读 build 目录里的 block.json(服务端),编辑器端由 registerBlockType()(index.js)接上——两边靠 name 对齐。
  2. attributes 存在哪:序列化进 post_content 的注释里(如 {"level":"进阶"}),随文章一起入 MySQL。所以属性默认不必声明 source,整包存 JSON 最稳。
  3. 静态 vs 动态的选型标准:纯展示且编辑时确定 → 静态(save 输出 HTML);内容依赖数据库或需要实时计算 → 动态(render_callback)。课程卡片拉课程列表,必须动态。
  4. useBlockProps / get_block_wrapper_attributes 成对出现:编辑态 React 挂 class(对齐、颜色),服务端输出同样包装,保证前后台样式一致。
  5. @wordpress/scripts 帮你管好工具链:webpack/esbuild、ESLint、热更新全内置,你只写 src。
  6. supports 是免费的能力开关:align、color、spacing 打开后,工具栏自动出现对应控件,样式自动注入——不要手写这些轮子。

你可能会懵的地方

  • 为什么前台没内容? 动态区块 save 返回 null 后,前台全靠 render_callback;忘了 npm run build 或 build 目录里没有 block.json,都会导致渲染失败。

  • RichText 和普通 input 有什么区别? RichText 保留行内格式(加粗、链接)并与区块属性同步;input 只存纯文本。编辑标题用 RichText 是惯例。

  • attributes 里的 source 是干什么的? 声明「从保存的 HTML 里提取属性」(如 source: 'children')。新版本推荐不写 source,让整包属性存进注释,避免迁移地狱。

  • 编辑器里报「此区块遇到错误」? 区块 JS 运行时异常。F12 看 Console 红字,多为 import 路径、未 build 或 JSX 语法错。

  • 区块和短代码(shortcode)怎么选? 有编辑态 UI、可视化预览需求选区块;纯服务端文本替换、要嵌在经典编辑器里,短代码仍可用,但新项目默认区块。

错法对照

错法问题正解
save 输出 HTML 且又有 render_callback前台内容重复动态区块 save 返回 null
name 写成 Qrocmq/CourseCard注册失败qrocmq/course-card 全小写
改了 src 直接看效果编辑器跑的是 build 产物开发期 npm start,上线 npm run build
render_callback 里不转义输出XSS 漏洞esc_html / esc_url(第 10 课展开)
漏掉 get_block_wrapper_attributes()对齐与颜色 class 丢失输出根元素时始终包裹

卡点急救

  1. 区块插入后编辑器报错:Console 定位;确认 npm start 进程存活、build/ 与 src 同步。
  2. 前台样式不生效:确认 block.json 的 style/editorStyle 路径存在;style.scss 是前后台共用,editor.scss 只进编辑器。
  3. create-block 下载卡住:切换 npm 源或使用代理;也可以 --template=static 生成最小模板减少依赖。

面试常问

  • 静态区块和动态区块的区别与选型? 静态在保存时把 HTML 写入 post_content,渲染零成本;动态只存属性、由服务端 render_callback 实时渲染,适合展示数据库内容或需保持模板逻辑同步的场景。

  • block.json 的作用? 区块的元数据与注册清单:name、attributes、supports、脚本样式入口,服务端与编辑器共享同一份定义,是 6.x 区块规范的核心文件。

  • 区块的属性数据最终存在哪? 序列化在文章 post_content 的区块注释中(JSON 形式),随 wp_posts 表存储;动态区块前台的 HTML 不落库,每次请求渲染。

自测三问

  1. 动态区块为什么把 save.js 返回 null?
  2. 写出 register_block_type 读构建目录的最小代码。
  3. supports 里开启 align 与 color 后,分别带来什么自动能力?

小结一句话

区块 = block.json 声明 + React 编辑态 + save 或 render_callback 输出;静态存 HTML、动态跑 PHP,会写一个课程卡片区块,就打通了 WP 6.x 内容组件化的任督二脉。

延伸

  • Create a Block 官方教程
  • block.json 元数据参考
  • 下一课:插件开发与 Hook 体系——让 action/filter 接管 WP 的执行流程。
加载本节练习…
← 上一课主题开发下一课 →插件生态