You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

重写WordPress原生列区块:多InnerBlocks同步修改问题及ES5实现求助

重写WordPress原生columns区块相关问题

我计划重写WordPress(WP)原生columns区块的基础功能,原因如下:

  • WP原生列区块自带了多款我不希望向用户开放的控件(变体选择、宽度滑块)
  • 原生列区块允许用户插入任意类型的内容,我需要通过允许区块列表控制列内可插入的内容类型

我编写了如下edit函数:

( function( wp ) {

    var registerBlockType = wp.blocks.registerBlockType;
    var el = wp.element.createElement;
    var __ = wp.i18n.__;

    const { RadioControl, PanelBody, RangeControl } = wp.components;
    const { useBlockProps, InspectorControls, InnerBlocks } = wp.blockEditor;
    const allowedBlocks = [ 'core/paragraph', 'core/button' ];

    registerBlockType( 'wpboiler-core/columns', {

        apiVersion: 2,
        title: __(
            'Columns',
            'columns'
        ),
        description: __(
            'A block for displaying content in columns',
            'columns'
        ),
        category: 'design',
        icon: 'schedule',
        supports: {
            html: false,
        },
        attributes: {
            columnselect: {
                type: 'number',
                default: 2,
            },
        },

        edit: function(props) {
            const { attributes, setAttributes } = props;
            const { columnselect } = attributes;

            const onChangeColumnRange = value => setAttributes({ columnselect: value });

            let columnsContainer = [];
            for(var n = 1; n <= columnselect; n++) {
                columnsContainer.push(
                    el(
                        'div',
                        null,
                        
                        el(
                            InnerBlocks, {
                                allowedBlocks: allowedBlocks,
                            }
                        )
                    )
                );
            };

            return el(
                'section',
                useBlockProps(attributes),
                
                // INSPECTOR CONTROL BEGIN
                el(
                    InspectorControls,
                    null,

                    el(
                        PanelBody, 
                        {
                            title: "Columns",
                        },

                        el(
                            RangeControl, {
                                min: 2,
                                max: 4,
                                value: columnselect,
                                onChange: onChangeColumnRange,
                            }
                        ),
                    ),
                ),
                // INSPECTOR CONTROL END

                el(
                    'div',
                    { className: 'columns__container' },

                    columnsContainer
                        
                ),

            );
        },

        save: function() {
            return null;
        },
    } );
}(
    window.wp
) );

我遇到的问题是多个InnerBlocks的内容同步问题:函数生成了多个InnerBlocks区域,但编辑任意一个区域的内容,所有区域的内容都会同步变更。

我考虑的规避方案是自定义一个包含InnerBlock组件的column子区块,在for循环中渲染该子区块而非直接渲染InnerBlocks,思路大致如下:

for(var n = 1; n <= columnselect; n++) {
    columnsContainer.push(
        {RENDER_COLUMN_BLOCK}
    );
};

但我不确定该方案是否仍会出现内容同步变更的问题,是否需要给每个子区块实例分配唯一ID来区分不同实例?另外我当前在无构建步骤的ES5环境下开发,不清楚如何在父区块内渲染其他自定义组件,希望获得相关指导,恳请大家提供相关解决思路。


更新

我参考相关资料找到了一个临时解决方案:当InnerBlocks中子区块数量达到上限时隐藏区块添加按钮,分别注册自定义columns父区块和column子区块,每个column子区块单独配置允许插入的区块列表,代码如下:

// COLUMNS index.js
( function( wp ) {

    var registerBlockType = wp.blocks.registerBlockType;
    var el = wp.element.createElement;
    var __ = wp.i18n.__;

    const { useSelect } = wp.data;
    const { useBlockProps, InnerBlocks } = wp.blockEditor;
    const allowedBlocks = [ 'wpboiler-core/column' ];

    registerBlockType( 'wpboiler/columns', {

        apiVersion: 2,
        title: __(
            'Columns',
            'columns'
        ),
        description: __(
            'Displays content in columns',
            'columns'
        ),
        category: 'design',
        icon: 'schedule',
        supports: {
            html: false,
        },

        edit: function(props) {
            const { attributes, clientId } = props;
            const innerBlockCount = useSelect((select) => select('core/block-editor').getBlock(clientId).innerBlocks);

            return el(
                'section',
                useBlockProps(attributes),
                __( 'Add columns by pressing the + icon. Maximum 4 columns', 'columns' ),

                el(
                    'div',
                    { className: 'columns__container' },

                    innerBlockCount.length > 3 ?
                        el(
                            InnerBlocks, {
                                allowedBlocks: allowedBlocks,
                                renderAppender: false
                            }
                        )
                        :
                        el(
                            InnerBlocks, {
                                allowedBlocks: allowedBlocks,
                            }
                        ),
                )
            );
        },

        save: function() {
            return el(
                'section',
                { className: 'columns' },


                el(
                    'div',
                    { className: 'columns__container' },

                    el(
                        InnerBlocks.Content, {},
                    ),
                ),
            );
        },
    } );
}(
    window.wp
) );
// COLUMN - INDIVIDUAL index.js
( function( wp ) {

    var registerBlockType = wp.blocks.registerBlockType;
    var el = wp.element.createElement;
    var __ = wp.i18n.__;

    const { useBlockProps, InnerBlocks } = wp.blockEditor;
    const allowedBlocks = [ 'core/heading', 'core/paragraph', 'core/button', 'core/list' ];

    registerBlockType( 'wpboiler/column', {

        apiVersion: 2,
        title: __(
            'Column',
            'column'
        ),
        description: __(
            'Displays an individual column',
            'column'
        ),
        category: 'widgets',
        icon: 'schedule',
        supports: {
            html: false,
        },
        parent: [ 'wpboiler-core/columns' ],

        edit: function() {
            return el(
                'div',
                useBlockProps(),
                
                el(
                    'div',
                    { className: 'column' },

                    el(
                        InnerBlocks, 
                        {
                            allowedBlocks: allowedBlocks,
                        },
                    ),
                ),
            );
        },

        save: function() {
            return el(
                'div',
                { className: 'column' },

                el(
                    InnerBlocks.Content, {},
                ),
            );
        },
    } );
}(
    window.wp
) );

该方案虽然能实现类似原生列区块的效果,但不再支持通过范围控件选择列数,和预期功能不完全一致,欢迎大家提供其他优化建议。


内容的提问来源于stack exchange,提问作者Bagseye

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.04 16:06:00