扩展古登堡组块:如何正确组合多个属性?

时间:2020-09-02 作者:jsjqueryreact

我正在扩展组块。我遇到的问题是,如果我选择一个选项,后端不会发生任何变化。但如果我再次更改它,它将显示上一个选定选项的类。我认为const组合导致了这个问题。我真的不知道如何正确地组合多个属性。你能帮帮我吗?

/**
 * Create HOC to add group control to inspector controls of block.
 */
const withGroupControl = createHigherOrderComponent( ( BlockEdit ) => {
    return ( props ) => {
        // Do nothing if it\'s another block than our defined ones.
        if ( ! enableGroupControlOnBlocks.includes( props.name ) ) {
            return (
                <BlockEdit { ...props } />
            );
        }

        const { width } = props.attributes;
        const { color } = props.attributes;
        const { highlight } = props.attributes;
        
        const combo = width + \' \' + color + \' \' + highlight;
        
        if ( combo ) {
        props.attributes.className = `${ combo }`;
        }

        return (
            <Fragment>
                <BlockEdit { ...props } />
                <InspectorControls>
                    <PanelBody
                        title={ \'Functions\' }
                        initialOpen={ true }
                    >
                        <SelectControl
                            label={ \'Width settings\' }
                            value={ width }
                            options={ groupWidthControlOptions }
                            onChange={ ( selectedWidthOption ) => {
                                props.setAttributes( {
                                    width: selectedWidthOption,
                                } );
                            } }
                        />
                        <SelectControl
                            label={ \'Color settings\' }
                            value={ color }
                            options={ groupColorControlOptions }
                            onChange={ ( selectedColorOption ) => {
                                props.setAttributes( {
                                    color: selectedColorOption,
                                } );
                            } }
                        />
                        <SelectControl
                            label={ \'Highlight settings\' }
                            value={ highlight }
                            options={ groupHighlightControlOptions }
                            onChange={ ( selectedHighlightOption ) => {
                                props.setAttributes( {
                                    highlight: selectedHighlightOption,
                                } );
                            } }
                        />
                    </PanelBody>
                </InspectorControls>
            </Fragment>
        );



    };
}, \'withGroupControl\' );

addFilter( \'editor.BlockEdit\', \'ww-group/with-group-control\', withGroupControl );

1 个回复
SO网友:bosco

要修改属性,应使用setAttributes() 与代码中其他地方的操作相同。此函数用于更新古腾堡数据存储中的值,从而触发任何组件的重新渲染,并在保存帖子时在数据库中分期更新更改。

        const { width } = props.attributes;
        const { color } = props.attributes;
        const { highlight } = props.attributes;
        
        const combo = width + \' \' + color + \' \' + highlight;
        
        if ( combo ) {
          props.attributes.className = `${ combo }`;
        }
此外,在此代码中if( combo ) 条件将始终执行,因为combo 赋值将始终计算为非空字符串,即;“真实的”;在JavaScript中。如果width, color, 和highlight 未定义,combo 成为字符串"undefined undefined undefined", 对于HTML类名来说,这似乎是不可取的。

我认为在每个属性派生类名前面加上前缀是一个好主意,这样您就可以将它们彼此区分开来,例如。att-highlight-red 而不是red. 将键/值对的对象转换为类名并忽略未定义值的函数对此非常有用:

function attsToClassNames( atts = {} ) {
  const classes = [];

  for( const [ key, value ] in Object.entries( atts ) ) {
    if( ! value && value !== 0 ) // Ignore falsey values, except 0
      continue;

    classes.push( `att-${key}-${value}` );
  }

  return classes;
}
考虑到以上所有内容,我将用以下内容替换此答案开头引用的代码部分:

const {
  attributes,
  setAttributes,
} = props;
const {
  width,
  color,
  highlight,
  className,
} = attributes;

// Retrieve the current attribute classes.
const attClasses = attsToClassNames( { width, color, highlight } ).join( \' \' );

// If the `className` attribute does not reflect the current attribute classes,
// update it.
if( className !== attClasses )
  setAttributes( { className: attClasses } );
现在className 应始终反映从其他属性派生的最新类名列表,并将与post&;的其余部分一起保存在Gutenberg的数据存储中;块属性。

为了提高效率(非常轻微),我们可以利用ReactuseEffect() 挂钩(从导入@wordpress/element) 并在;依赖关系数组-这将使重建属性类仅在第一次渲染时发生,然后仅当其中一个或多个属性在此之后发生更改时发生:

useEffect(
  () => {
    const attClasses = attsToClassNames( { width, color, highlight } ).join( \' \' );
    
    if( className !== attClasses )
      setAttributes( { className: attClasses } );
  },
  [ width, color, highlight ]
);
这可能仍然会带来一些其他潜在问题,具体取决于您的特定用例-即如果您希望合并任何其他外部className 就像传来的一样props.

相关推荐