在古腾堡自定义横幅块中使用页面标题

Use page Title in Gutenberg custom banner block

我为古腾堡创建了一个自定义横幅图像块,效果很好,但是 我想知道是否可以使用页面标题作为当前横幅文本 占位符,直到它被编辑?

我的编辑功能是

 return [
            el('div', {className:'header-banner'},
                el(
                    element.Fragment,
                    null,
                    controls,
                    el( "div",{
                        className: 'banner-image',
                        style: { backgroundImage: 'url('+attributes.mediaURL+')' }
                    },
                    attributes.title || isSelected ?  el(RichText, {
                            key: 'editable',
                            tagName: "h1",
                            className: "banner-title",
                            //Can i add the page title in here if it is avaiable??
                            //placeholder: i18n.__('Write title…'),
                            value: attributes.title,
                            onChange: function onChange(value) {
                                return props.setAttributes({ title: value });
                            },
                            inlineToolbar: true
                        }) : null 

                    )
                )
            )//header-banner
        ];    

谢谢:)

Gutenberg 使用 wp.data, which is an abstraction over Redux. To get the title (or 100+ other values), we need to query the core/editor data store. Gutenberg makes it simple to retrieve post attributes with getEditedPostAttribute.

存储当前编辑器状态

一旦我们知道要查看的位置,获得标题就很简单了:

const { select } = wp.data;
const title = select("core/editor").getEditedPostAttribute( 'title' );

可行,但没有响应。当 post 标题更改时,title 不会反映新值。这有点让人失望。

为了反映对编辑器标题的更改,我们需要监听对 core/editor 数据存储的更改。有几种方法可以做到这一点。

一个解决方案是定义一个简单的更改处理程序函数并将其订阅到数据存储更新:

const { select } = wp.data;

function logTitle() {
  const title = select("core/editor").getEditedPostAttribute( 'title' );
  console.log("Editor Title:", title);
}
subscribe(logTitle);

any wp.data 存储值更新时会触发 - 这种情况经常发生。

包含 data-store 值的 Gutenberg-sanctioned 方法似乎是使用 higher-order 组件直接包含值:

const GetTitle = props => <div>{props.title}</div>;

const selectTitle = withSelect(select => ({
  title: select("core/editor").getEditedPostAttribute( 'title' )
}));
const PostTitle = selectTitle(GetTitle);

然后在块的输出中,包含一个 <PostTitle /> jsx 标记。这比嵌套回调或其他更改处理程序要干净得多。

Higher-order 组件可能难以理解。简短的解释是,它们包装一个现有组件,生成一些数据,然后 return 一个组件的副本,新数据作为 props 传递。这将逻辑与表示分离并有助于可维护性。

GetTitle 很简单,它只是一个小组件,接受带有标题键的 props object 并吐出一些 html.

withSelect 是函数构造函数或装饰器。它接受一个函数参数,并且 return 是一个需要组件的新函数。通常 returned 函数会立即调用(有点像 IIFE),但为了清楚起见,我将其存储在 selectTitle 变量中。新函数生成一个包含标题的 object,这个 object 将作为 props 传递给任何传递给 withSelect 的组件。通过某种魔法,只要更新数据存储,就会调用它。

最后,PostTitle 包含 selectTitle 的函数结果,它是一个组件 pre-populated 和生成的道具。然后可以使用 <PostTitle /> 标记将该组件放入我们的标记中。每当编辑器 data-store 更新时,higher-level 组件将反映新数据。

@joemaller 感谢您提供有用的回复。

这是一个示例,演示了如何使用 withSelect() 包装通过传递给 registerBlockType() 的块配置 object edit 属性 定义的组件。

组件通过 props title 传递。

如果用户编辑 post/page 标题,该组件会 re-rendered 具有新标题,因为它的道具会发生变化。这使其能够在 "real time" 内更新。

import { withSelect } from '@wordpress/data'

...

edit: withSelect(
  ( select ) => {
    return {
      title: select( 'core/editor' ).getEditedPostAttribute( 'title' ),
    }
  } )( props => {
    return (
      <div>{ props.title }</div>
    )
} ),