写gameCircum网站时遇见的一个奇葩问题,自定义了一个非常简单的古腾堡模块,其中只有标题、链接、内容。但是每次保存后再刷新都会出现一个错误:“此区块包含未预料的或无效的内容。”

解决思路:

先说结论,出现这个错误的原因就是edit函数和save函数输出不匹配导致的。排查的步骤非常简单:直接在古腾堡编辑器中按F12点开控制台:这个时候控制台必然报错:“Block validation: Block validation failed for 你的自定义模块”,这个时候请仔细观察下面的错误信息:

Content generated by `save` function: 指的是你save函数输出的html代码;

Content retrieved from post body: 指的是文章保存后的html代码。

只要这两段html代码不完全匹配,那么必然就会报“此区块包含未预料的或无效的内容。”,这种错误有可能是某个函数钩子修改了文章的内容格式,还有可能是wordpress编辑器自己给自己加戏,比如站长遇见的问题就是:当save函数写有target: '_blank'时,在保存后wordpress为了安全自动给a标签加上了rel="noopener",而此时我的save函数里并没有rel="noopener",因此便导致了报错。解决方案也很简单,直接在a标签代码里加上:rel: 'noopener' 即可。

希望可以给看到的开发同学省去一些踩坑的时间。

附赠以上写的例子:

(function(blocks, editor, element) {
  const el = element.createElement
  const { RichText, PlainText } = editor

  blocks.registerBlockType('gutenberg-plugin/nav-block', {
    title: '链接',
    icon: 'admin-links',
    category: 'common',
    attributes: {
      title: {
        type: 'string',
        source: 'text',
        selector: '.nav-title'
      },
      link: {
        type: 'string',
        source: 'text',
        selector: '.nav-link'
      },
      info: {
        type: 'string',
        source: 'text',
        selector: '.nav-info'
      }
    },
    edit: function(props) {
      const { attributes, setAttributes } = props

      return el('div', { className: 'wp-block-gutenberg-link' },
        el(PlainText, {
          className: 'nav-title',
          value: attributes.title,
          onChange: value => setAttributes({ title: value }),
          placeholder: '输入标题'
        }),
        el('div', { className: 'nav' },
          el('a', { href: attributes.link, target: '_blank', rel: 'noopener' }, attributes.title)
        ),
        el(PlainText, {
          className: 'nav-link',
          value: attributes.link,
          onChange: value => setAttributes({ link: value }),
          placeholder: '输入链接'
        }),
        el(RichText, {
          tagName: 'div',
          className: 'nav-info',
          value: attributes.info,
          onChange: value => setAttributes({ info: value }),
          placeholder: '输入详细介绍'
        })
      )
    },
    save: function(props) {
      const { attributes } = props

      return el('div', { className: 'wp-block-gutenberg-link' },
        el('div', { className: 'nav-title' }, attributes.title),
        el('div', { className: 'nav' },
          el('a', { href: attributes.link, target: '_blank', rel: 'noopener' }, attributes.title)
        ),
        el('div', { className: 'nav-link' }, attributes.link),
        el('div', { className: 'nav-info' }, attributes.info)
      )
    }
  })
})(window.wp.blocks, window.wp.blockEditor, window.wp.element)