WP DEVELOP

EP141. “Quiz Block 骨架:WordPress 内建组件与 SCSS”

首页 WordPress 开发课程 GUTENBERG BLOCK 入门(block.json) · EP141
约 14 分钟· #EP141#GUTENBERG BLOCK 入门(block.json)
🔒 登录后可标记已读

📌 并入 EP140 的提醒:这一章录制完不久后,WordPress 官方改成推荐用 block.json 文件来声明/加载 Block 的 JS、CSS 资源。这不影响本章接下来教的「怎么写 Block 本身」的任何技巧,纯粹是加载资源文件的方式有新旧两种写法——本章后面会补一讲专门讲 block.json 的新写法,两种做法都合法,新写法只是官方现在更推荐的「标准姿势」。

开始做真正会用到的 Block——多选题问答(Quiz)。这一讲先把界面骨架搭出来,重点是尽量用 WordPress 自带的组件@wordpress/components 包里的 TextControlFlexButtonIcon 等)而不是从零手写 HTML+CSS,好处是不用自己写样式就能获得跟 WordPress 后台一致的视觉效果。同时把 edit 函数抽成独立的具名组件(EditComponent),并引入 SCSS 文件写少量自定义样式。


涉及文件

  • wp-content/plugins/are-you-paying-attention/src/index.js (修改)
  • wp-content/plugins/are-you-paying-attention/src/index.scss (新建)
  • wp-content/plugins/are-you-paying-attention/index.php (修改)

代码实现

src/index.js:把 edit 抽成独立组件,用内建组件搭界面骨架

import "./index.scss"
import {TextControl, Flex, FlexBlock, FlexItem, Button, Icon} from "@wordpress/components"

wp.blocks.registerBlockType("ourplugin/are-you-paying-attention", {
  title: "Are You Paying Attention?",
  icon: "smiley",
  category: "common",
  attributes: {
    skyColor: {type: "string"},
    grassColor: {type: "string"}
  },
  edit: EditComponent,
  save: function (props) {
    return null
  }
})

function EditComponent (props) {
  function updateSkyColor(event) {
    props.setAttributes({skyColor: event.target.value})
  }

  function updateGrassColor(event) {
    props.setAttributes({grassColor: event.target.value})
  }

  return (
    <div className="paying-attention-edit-block">
      <TextControl label="Question:" />
      <p>Answers:</p>
      <Flex>
        <FlexBlock>
          <TextControl />
        </FlexBlock>
        <FlexItem>
          <Button>
            <Icon icon="star-empty" />
          </Button>
        </FlexItem>
        <FlexItem>
          <Button>Delete</Button>
        </FlexItem>
      </Flex>
    </div>
  )
}

src/index.scss(新建)

.paying-attention-edit-block {
  padding: 20px;
  border-radius: 2px;
  border: 1px solid #f1f1f1;
  background-color: #d6d6d6;
}

index.php:注册并挂载编辑器专属的 CSS

function adminAssets() {
  wp_register_style('quizeditcss', plugin_dir_url(__FILE__) . 'build/index.css');
  wp_register_script('ournewblocktype', plugin_dir_url(__FILE__) . 'build/index.js', array('wp-blocks', 'wp-element', 'wp-editor'));
  register_block_type('ourplugin/are-you-paying-attention', array(
    'editor_script' => 'ournewblocktype',
    'editor_style' => 'quizeditcss',
    'render_callback' => array($this, 'theHTML')
  ));
}

关键改动点:

  • edit: EditComponent:把原本直接写在配置对象里的匿名函数,抽成文件底部一个独立、具名的函数。React 的约定是组件名要大写字母开头EditComponent 而不是 editComponent),这样 React 才能区分「这是一个自定义组件」还是「这是一个普通 HTML 标签」
  • import {TextControl, Flex, ...} from "@wordpress/components":不需要额外执行 npm install 就能直接导入——@wordpress/scripts 内部的构建配置认识 @wordpress/* 这类包名,遇到时会自动转换成「去浏览器全局作用域里找 WordPress 已经加载好的对应模块」,而不是打包进产物里。React 和 ReactDOM 也是同样处理,避免打包出重复的 React 副本增加访问者的下载体积
  • import 组件还不够,还要在 PHP 里给依赖数组加上 wp-editor——@wordpress/components 这些包实际运行时依赖 WordPress 提供的 wp-editor 等脚本先加载好,缺了会在浏览器报错说找不到对应的全局对象
  • TextControl(文字输入框)、Flex/FlexBlock/FlexItem(弹性布局容器,FlexBlock 会尽量占满可用空间,FlexItem 只占自己需要的最小空间)、ButtonIcon(配合内建 dashicon 名称如 star-empty 使用)——这些组件在这个阶段只是拿来摆架子,还没有接上任何真实的交互逻辑,纯粹练习「用现成组件代替手写 HTML/CSS 能省多少事」
  • SCSS 文件直接 import "./index.scss" 到 JS 文件顶部,@wordpress/scripts 会自动识别并把编译后的纯 CSS 抽取到 build/index.css不需要任何额外配置——跟前面「零配置支持 JSX」是同一套理念
  • PHP 侧用 wp_register_style() 注册 CSS 文件(不带依赖数组,因为纯 CSS 不需要依赖其他资源),再通过 register_block_type()editor_style 参数把它跟 Block 关联起来,只在编辑器页面加载这份样式

[截图:Gutenberg 编辑器里插入 Quiz Block 后的骨架界面,含问题输入框、答案输入行、星标按钮和 Delete 按钮]


Hook / Function 速查

名称类型用途
@wordpress/componentsWordPress 官方 JS 包提供一整套跟 WordPress 后台视觉风格一致的现成 UI 组件(输入框、按钮、布局容器等)
wp-editor(脚本依赖名)WP 内建脚本句柄@wordpress/components 等编辑器相关包的运行时依赖
wp_register_style($handle, $src)WP 内建 function注册(不立即加载)一个 CSS 文件
editor_styleregister_block_type 参数)Gutenberg Block API指定该 Block 在编辑器里需要加载的 CSS

常见坑

  • import@wordpress/components 却忘记在 PHP 依赖数组里加 wp-editor——编辑器页面会直接报 JS 错误,因为浏览器全局作用域里找不到对应模块
  • React 组件函数名用小写开头——React 会把它当成普通 HTML 标签名处理而不是自定义组件,导致渲染出错或出现意外行为
  • 手写一整套 HTML+CSS 来实现 WordPress 已经提供现成组件的效果——多做了不必要的工作,还可能跟后台整体视觉风格不一致

延伸 / 后续讲座会用到

下一讲继续微调样式,让界面更接近最终效果,然后开始写 JavaScript 让「新增答案行」「标记正确答案」「删除答案行」这些交互真正动起来。


Sources

Udemy:

  • Become a WordPress Developer: Unlocking Power With Code — Section 25, EP141(含 EP140 提醒并入)