Gutenberg:块SelectControl保存属性,但在重新加载Gutenberg之后,它会加载其缺省值。为什么?

时间:2021-01-11 作者:Marc

我以为我有。我添加了一个属性;“最大液位”;和SelectControl元素“;选择MaxLevel;。一切都按照计划进行:我可以设置最大级别,它保存在块中。当我保存帖子并显示帖子时,可以看到php部分使用了;“最大液位”;变量但当我编辑帖子时,块会加载它的默认值。为什么会发生这种情况?

registerBlockType(\'simpletoc/toc\', {
  title: __(\'SimpleTOC\', \'simpletoc\'),
  icon: simpletocicon,
  category: \'layout\',
  attributes: {
        no_title: {
            type: \'boolean\',
      default: false,
        },
        max_level: {
            type: \'integer\',
      default: 6,
        },
    },
  edit: function(props) {

    return (
    <span>
    <InspectorControls>
      <Panel>
        <PanelBody>
          <PanelRow>
            <ToggleControl
                label={__("Disable heading", \'simpletoc\')}
                help={__(\'Remove "Table of contents" block heading.\', \'simpletoc\')}
                checked={ props.attributes.no_title }
                onChange={ () => props.setAttributes( {  no_title: ! props.attributes.no_title } ) }
            />
          </PanelRow>
          <PanelRow>
            <SelectControl
                label={__("Maximum Level", \'simpletoc\')}
                help={__(\'Maximum depth of the headings.\', \'simpletoc\')}
                value= { props.attributes.max_level }
                options={ [
                    { label: __(\'Including\', \'simpletoc\') + \' H6 (\' + __(\'Show all\', \'simpletoc\') + \')\' , value: \'6\' },
                    { label: __(\'Including\', \'simpletoc\') + \' H5\', value: \'5\' },
                    { label: __(\'Including\', \'simpletoc\') + \' H4\', value: \'4\' },
                    { label: __(\'Including\', \'simpletoc\') + \' H3\', value: \'3\' },
                    { label: __(\'Including\', \'simpletoc\') + \' H2\', value: \'2\' },
                ] }
                onChange={ ( level ) => props.setAttributes( { max_level: level } ) }
            />
          </PanelRow>
        </PanelBody>
      </Panel>
    </InspectorControls>
    <BlockControls>
      <ToolbarGroup>
        <ToolbarButton
          className="components-icon-button components-toolbar__control"
          label={__(\'Update table of contents\', \'simpletoc\')}
          onClick={function() {
            sendfakeAttribute(props)
          }}
          icon="update"
        />
      </ToolbarGroup>
  </BlockControls>
  <p>
    <ServerSideRender block={props.name} attributes={props.attributes} />
  </p>
  </span>
    )
  },
  save: props => {
    return null;
  },
});
相关php部分:

register_block_type(\'simpletoc/toc\', [
    \'editor_script\' => \'simpletoc-js\',
    \'editor_style\' => \'simpletoc-editor\',
        \'attributes\' => array(
                \'no_title\' => array(
                    \'type\' => \'boolean\',
              \'default\' => false,
                ),
            \'max_level\' => array(
                    \'type\' => \'integer\',
              \'default\' => 6,
                ),
            \'updated\' => array(
              \'type\' => \'number\',
              \'default\' => 0,
              \'_builtIn\' => true,
            ),
    ),
    \'render_callback\' => __NAMESPACE__ . \'\\\\render_callback\'
   ]);

1 个回复
最合适的回答,由SO网友:Sally CJ 整理而成

块编辑器使用默认值的原因-对于max_level (“最大液位”)仅属性-而不是从(块)解析的属性comment delimiter 在已保存的帖子内容中,是因为在已解析/保存的属性中,max_level 无效。

为什么无效:因为type 属性(值)的值与注册块时定义的值不匹配-max_level: { type: \'integer\', ... }.

为什么不匹配,是因为这部分使用字符串值更新属性:

// "level" here is an input value, and input values are string unless
// explicitly converted to another type (boolean, number, etc.):

onChange={ ( level ) => props.setAttributes( { max_level: level } ) }
例如,当;包括H3“;被选为;最大液位;,结果在"max_level":"3" 而不是正确的,"max_level":3:

坏-max_level 是字符串:<!-- wp:simpletoc/toc {"max_level":"3"} /-->

很好-max_level 是整数:<!-- wp:simpletoc/toc {"max_level":3} /-->

因此,请务必尊重该属性type 在你的情况下,你会想使用Number( level ) 像这样:

props.setAttributes( { max_level: Number( level ) } )
顺便说一句,我可以告诉你my answer here, 但我认为最好是针对这个问题写一个答案

其他注释ServerSideRender 组件使用wp.element.RawHTML() 将输出包装为div, 因此,您不应该将ServerSideRender 在a中p, 这(在我的情况下)导致了一个错误(在控制台中),上面写着<div> 不能是的后代<p>“参考资料”;(事实上,常规HTML<p><div>something</div></p> 确实无效:))。所以

// Instead of this:
<p><ServerSideRender .../></p>

// Use a div or Fragment as a wrapper:
<div><ServerSideRender .../></div>
<><ServerSideRender .../></>

// Or simply, no wrapper:
<ServerSideRender .../>