8

我正在尝试阻止自定义列,因为古腾堡使用的 wordpress 默认值不是我需要的。

所以我查看了它是如何工作的,它使用带有布局定义的 InnerBlocks 块,但是没有办法指定 html 标记和列的类,所以它对我来说没用。

然后我决定使用 map 循环出列,效果很好,然后我在每一列中添加了 InnerBlocks 组件以允许将其他块插入到列中,但问题是在每一列中 InnerBlocks 的内容是共享的,所以我已尝试将每个 InnerBlock 和列的键属性设置为唯一,并且它们的内容仍然是共享的(不,我没有使用共享块)。

看起来古腾堡在每一列中都使用了相同的 InnerBlocks 实例。

我正在尝试构建一个块类型,您可以在其中动态添加列,并在每列中添加带有一些信息的“卡片”。

为了说明我在做什么,这里是编辑功能的返回:

<section className="infonav">
            <div className="infonav__container">
                <div>
                    <button onClick={onAddBox}>{__('Add column', 'zmg-blocks')}</button>
                </div>
                <div className="infonav__row">
                    {[...new Array(columns).keys()].map((item, index) => {
                        return (
                                <div className="infonav__row__col" key={"info_cols"+index}>
                                    <div>
                                        <button onClick={onRemoveBox.bind(index)}>
                                            {__('Remove', 'zmg-blocks')}
                                        </button>
                                    </div>
                                    <InnerBlocks key={"info_boxes"+index}/>
                                </div>
                        );
                    })}
                </div>
            </div>
        </section>

谢谢

4

3 回答 3

5

似乎gutenberg Innerblocks只能在一个块中使用一次

注意:一个块在编辑和保存时最多只能渲染一个 InnerBlocks 和 InnerBlocks.Content 元素。要创建嵌套块的不同排列,请创建一个单独的块类型,该类型呈现其自己的 InnerBlocks 并指定为唯一的 allowedBlocks 类型。

来源:https ://github.com/WordPress/gutenberg/tree/master/packages/block-editor/src/components/inner-blocks

您需要创建另一个自定义块(仅用于列)以及该块,该块也在其中使用 Innerblock,以便其他块可以嵌套在其中。您可以使用 allowedBlocks 仅允许此块中的自定义列

于 2019-01-12T04:46:04.373 回答
1

如果您打算通过InnerBlock如下所示的“块编辑器”添加多个古腾堡块,则无法添加多个块:

const BLOCK_TEMPLATE = [
  ['image-slider', { width: 800, height: 400 }],
  ['menu'],
];

registerBlockType('peregrine/inner-block-demo', {

  title: 'Inner Block Demo',

  edit({ className }) {
    return (
      <div className={className}>
        <InnerBlocks
          template={BLOCK_TEMPLATE}
          templateLock="all"
        />
      </div>
    );
  },

  save() {
    return (
      <div>
        <InnerBlocks.Content />
      </div>
    );
  },
});

多个内部块具有看起来不值得努力的复杂性,并且通常它暗示应该将块分解为多个更简单的块,或者具有块属性(不是子块)。让我们知道上述建议如何为您服务,我们可以重新考虑。

您可以在此处关注讨论:https ://github.com/WordPress/gutenberg/issues/6808

但是,您的代码看起来更像是添加内部元素,这是可能的。

因此,为了进一步澄清,您提供给 registerBlockType 函数的不是块。古腾堡会阻止优雅的简码,如下所示:

<!-- wp:image -->
<figure class="wp-block-image"><img src="source.jpg" alt="" /></figure>
<!-- /wp:image -->

或这个:

<!-- wp:latest-posts {"postsToShow":4,"displayPostDate":true} /-->

第一个被称为静态块,因为它有它的内容。第二个称为动态块,因为它是自闭块并且没有内容。当您注册您的块时,将从您提供的 php 回调中检索内容。

Gutenberg 使用 React 将块的可视化表示打印到编辑器屏幕上。设置对象上的编辑方法应该返回一个反应元素,这个元素将用于在编辑器中为块生成可视化表示。save 方法也应该返回 react 元素,但是这个元素会被渲染成静态 html 并保存到 database:<figure class="wp-block-image"><img src="source.jpg" alt="" /></figure>中。现在,动态块没有返回元素,因为它们返回 null,因此它们中没有内容,这就是它们自关闭的原因。

当服务器响应请求时,它会获取存储在数据库中的内容,并通过解析器运行它来查看它是静态块还是动态块。如果块是静态的,它本身就有它的内容,所以内容将被返回。如果是动态的,则会调用注册的回调函数并返回其返回值。

现在,要回答您的问题,保存和编辑功能应该返回反应元素。react 元素必须有单个根元素,但内部元素可以是任何常规 html,例如:

<div>
  <h1>Hello world</h1>
  <p>This is a sentence</p>
</div>

这是出于性能原因。DOM 操作是昂贵的,这就是为什么它有一个进入 DOM 的入口点。这就是为什么它非常快。然后它有自己的 DOM,一整棵树驻留在内存中。当发生更改时,React 将遍历其 DOM 树并仅渲染更改的分支,不会对每一个微小的更改都绘制整个树。

这里重要的细节是上面的代码看起来像 html 但它不是,它是 jsx。React 不能直接渲染 html。Jsx 会被 babel 之类的转译器转译成 react 元素。

React 上还有 createElement 方法,可用于创建反应元素。wp 重新导出此方法。

您可以在另一个中渲染一个反应元素。如果不学习反应,您将永远无法完全掌握积木的力量或潜力。React 库并没有那么大。一旦你掌握了它背后的想法,你就可以在一两周内学会它,从而提高工作效率。

于 2019-01-29T18:54:32.333 回答
0

我遇到了同样的问题,根据Swopnil Dangol 的回答,我创建了如下内容:

父块:

registerBlockType("my-plugin/parent-block", {

    title: "Parent block",

    // Amount of columns
    attributes: {
        columns: { type: "number", default: 3 },
    }

    edit(props) {
        const { attributes: { columns } } = props;

        const onChangeColumns = (newColumns) => {
            setAttributes({ columns: newColumns });
        };

        // Either go for the template route
        // (create an inner block template based on amount of columns)
        const template = Array.from(Array(columns).keys()).map((i) => [
            "my-plugin/custom-inner-block",
        ]);
      
        // Or go for the allowed blocks route
        const allowedBlocks = ["my-plugin/custom-inner-block"];

        return (
            <div {...useBlockProps()}>

                {/* Use RangeControl in the InspectorControls to 
                    control the number of columns. */}
                <InspectorControls key="setting">
                    <div class="block-editor-block-card">
                        <fieldset>
                            <legend className="blocks-base-control__label">
                                {__("Amount of columns", "gutenpride")}
                            </legend>
                            <RangeControl
                                label="Columns"
                                value={columns}
                                onChange={(value) => onChangeColumns(value)}
                                min={1}
                                max={3}
                            />
                        </fieldset>
                    </div>
                </InspectorControls>
    
                <InnerBlocks
                    template={activeTemplate}
                    templateLock="all"
                    allowedBlocks={allowedBlocks}
                />
            </div>
        )
    },

    save() {
        return (
            <div {...useBlockProps.save()}>
                <InnerBlocks.Content />
            </div>
        );
    },

    // ...
}

自定义内部块:

registerBlockType("my-plugin/custom-inner-block", {

    title: "Custom Inner Block",

    edit(props) {
        const { attributes } = props;
        const { title } = attributes;

        return (
            <div {...useBlockProps()}>
                <InnerBlocks/>
            </div>
        );
    },

    save() {
        return (
            <div {...useBlockProps.save()}>
                <InnerBlocks.Content />
            </div>
        );
    },

    // ...
});
于 2022-01-27T22:38:13.543 回答