WP DEVELOP

EP137. “Attributes 机制:让 Block 真正可交互”

首页 WordPress 开发课程 插件开发 CH2:插件里的 JS · EP137
约 12 分钟· #EP137#插件开发 CH2:插件里的 JS
🔒 登录后可标记已读

学习 Gutenberg Block 最核心的数据机制——attributes(属性):在 registerBlockType() 的配置对象里声明这个 Block 需要存哪些数据(名字、类型),edit 函数里用 props.attributes 读取当前值、用 props.setAttributes() 更新值,save 函数里同样用 props.attributes 把值填进最终输出的 HTML。做出两个可输入文字的框(天空颜色、草地颜色),编辑器里输入的内容会实时同步进 attributes,最终拼成一句「今天天空是 XX 色,草是 XX 色」的话存进数据库。顺带介绍了 attributes 的两种存储方式:默认存在 HTML 注释里,或者用 source/selector 从保存的 HTML 结构本身解析出来——作者明确表示自己偏好前者,只是作为知识点介绍后者


涉及文件

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

代码实现

src/index.js(完整文件,最终版本——默认的注释存储方式,未使用 source/selector

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: function (props) {
    function updateSkyColor(event) {
      props.setAttributes({skyColor: event.target.value})
    }

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

    return (
      <div>
        <input type="text" placeholder="sky color" value={props.attributes.skyColor} onChange={updateSkyColor} />
        <input type="text" placeholder="grass color" value={props.attributes.grassColor} onChange={updateGrassColor} />
      </div>
    )
  },
  save: function (props) {
    return (
      <p>Today the sky is <span className="skyColor">{props.attributes.skyColor}</span> and the grass is <span className="grassColor">{props.attributes.grassColor}</span>.</p>
    )
  }
})

关键改动点:

  • attributes: { skyColor: {type: "string"}, grassColor: {type: "string"} }:给 Block 声明两个数据字段,type 是唯一必填的描述属性(还可以是 array/number/boolean 等),这是 editsave 两个函数之间共享数据的「公共接口」
  • edit(props):WordPress 调用这个函数时会自动传入一个 props(属性)对象,里面包含 props.attributes(当前所有属性的值)和 props.setAttributes()(更新属性值的方法)——这是 Gutenberg/React 的标准约定,参数名 props 是业界惯例,不是强制要求但建议遵守
  • onChange={updateSkyColor}:JSX 里绑定事件监听器的写法是 on事件名={函数引用},属性名要用大写开头的驼峰onChange 而不是 onchange);每次用户在输入框里打一个字都会触发这个函数
  • updateSkyColor(event)浏览器/React 会自动把「这次事件的详细信息」作为参数传入回调函数event.target 是触发事件的那个 DOM 元素(这里是输入框本身),event.target.value 就是用户当前打进去的完整文本
  • props.setAttributes({skyColor: event.target.value}):调用这个方法、传入一个对象,WordPress 会把这个对象合并进现有的 attributes(不会影响其他没提到的属性),从而触发编辑器重新渲染、界面同步更新
  • value={props.attributes.skyColor}:给输入框加上 value 属性、绑定到 attributes 里的值——这一步是让「刷新页面后重新打开编辑器,之前输入的内容依然显示在输入框里」的关键,光有 onChange 只能捕获输入但不会自动回显
  • save(props) 同样接收 props,直接引用 props.attributes.skyColor/props.attributes.grassColor 把值嵌进最终输出的静态 HTML 里,{} 是 JSX 里插入动态 JS 表达式的标准写法
  • JSX 里的 class 属性要写成 className(不能写 class),因为 class 在 JavaScript 里是保留关键字,会跟 ES6 的 class 语法冲突
  • 数据存储的两种方式:默认方式(这一讲最终采用的)——WordPress 会把整个 attributes 对象序列化后存进一段 HTML 注释里,跟在保存的 HTML 内容前面,前台渲染不需要解析这段注释,只需要注释里的数据在编辑器重新打开时把值读回来;source+selector 方式(作者展示但明确表示自己不常用)——不额外存注释,而是让「保存的 HTML 结构本身」成为唯一数据来源,靠 CSS 选择器(比如 .skyColor)从已保存的 HTML 里重新解析出属性值,作者认为默认方式更直观、够用

[截图:Block 编辑器里两个可输入的文字框(sky color / grass color)及保存后前台显示的 "Today the sky is XX and the grass is XX." 效果]


Hook / Function 速查

名称类型用途
attributes(Block 配置属性)Gutenberg Block API声明 Block 需要存储的数据字段及类型
props.attributesGutenberg 传入 edit/save 的参数读取当前 Block 实例的属性值
props.setAttributes(obj)Gutenberg 传入 edit 的方法合并更新属性值,触发编辑器重新渲染
event.target.value浏览器原生 DOM API获取触发事件的表单元素当前的值

常见坑

  • 输入框只写 onChange 不写 value——用户输入能被捕获、存进 attributes,但刷新页面重新打开编辑器时输入框会显示为空,因为没有告诉 React 用 attributes 里的值回显
  • 修改了 save 函数生成的 HTML 结构(比如加/删标签、改 attributes 定义)之后,已经插入文章里的旧 Block 实例会报「非预期或无效内容」的错误——这是因为编辑器发现数据库存的旧 HTML 跟当前 save 函数会生成的新 HTML 对不上,这一讲的临时解法是删除旧实例、重新插入新的,更规范的处理方式后面讲座会讲到
  • 属性名用 class 而不是 className——JSX 里这是硬性规则,用错会导致编译报错或属性不生效

延伸 / 后续讲座会用到

现在的 Block 保存的都是「静态字符串」,下一讲要处理更复杂的场景:如果 Block 的内容需要在服务端用 PHP 动态生成(比如实时查询数据库),静态保存的字符串就不够用了——这是接下来要解决的问题。


Sources

Udemy:

  • Become a WordPress Developer: Unlocking Power With Code — Section 24, EP137