无需重新发明轮子即可更新块的编辑/保存

时间:2021-01-28 作者:kero

TL;DR如何更改editsave 核心块的结果,而无需在我自己的代码中重新实现其大部分功能?

问题我熟悉block filters 我已经能够使用它们添加属性或新的InspectorControl。然而,它让我感到不安的是,我似乎无法更新编辑/保存的JSX/HTML,而不必覆盖整个块。

设想以下场景:我想向core/button 阻止在文本后附加图标。所以最后的HTMLshould not

<div class="wp-block-button">
    <a class="wp-block-button__link">Hello World</a>
</div>
但相反desired result

<div class="wp-block-button">
    <a class="wp-block-button__link">Hello World</a>
    <span class="wp-block-button__icon">X</span>
</div>
用于save 我可能需要wp.element.cloneElement 将我自己的元素添加为附加子元素。

但是为什么edit? 我目前的理解是,只要块不使用SlotFills, 我真的没有选择。

在像这样的常规设置中

const withInspectorControls = createHigherOrderComponent((BlockEdit) => {
  return (props) => {
    const { name, attributes, setAttributes } = props
    if (name !== \'core/button\') {
      return <BlockEdit {...props} />
    }

    const { showIcon } = attributes

    return (
      <Fragment>
        <BlockEdit {...props} />
        <InspectorControls>
          <PanelBody title={__(\'Show Icon?\', \'my-plugin\')}>
            <ToggleControl
              label={__(\'Show Icon?\', \'my-plugin\')}
              checked={showIcon}
              onChange={(showIcon) => setAttributes({ showIcon })}
            />
          </PanelBody>
        </InspectorControls>
      </Fragment>
    )
  }
})

addFilter(\'editor.BlockEdit\', \'my-plugin/add-icon-inspector\', withInspectorControls)
我可以放下<BlockEdit {..props} /> 分离并重新执行按钮。但是看看the source of the edit 我知道我要么重新实施ButtonEdit 方法,这是我想要避免的。

该堆栈上的各种指南以及其他答案意味着创建一个新的块(并取消注册/黑名单核心块)更有意义,这在2021仍然有效吗?

1 个回复
SO网友:Tom J Nowell

You would do this with the format API, for example, this code from the handbook will add a <samp> tag around text:

import { registerFormatType, toggleFormat } from \'@wordpress/rich-text\';
import { RichTextToolbarButton } from \'@wordpress/block-editor\';
 
const MyCustomButton = ( props ) => {
    return <RichTextToolbarButton
        icon=\'editor-code\'
        title=\'Sample output\'
        onClick={ () => {
            props.onChange( toggleFormat(
                props.value,
                { type: \'my-custom-format/sample-output\' }
            ) );
        } }
        isActive={ props.isActive }
    />;
};
 
registerFormatType(
    \'my-custom-format/sample-output\', {
        title: \'Sample output\',
        tagName: \'samp\',
        className: null,
        edit: MyCustomButton,
    }
);

Likewise, you can use the same tricks the image format uses to insert a single element without it wrapping text:

https://github.com/WordPress/gutenberg/blob/master/packages/format-library/src/image/index.js

Specifically, it imports insertObject:

                            insertObject( value, {
                                type: name,
                                attributes: {
                                    className: `wp-image-${ id }`,
                                    style: `width: ${ Math.min(
                                        imgWidth,
                                        150
                                    ) }px;`,
                                    url,
                                    alt,
                                },
                            } )

Where name is the name of the format that was registered. The result is an inline <img> tag.

相关推荐