Wordpress Gutenberg:前端的 React 组件

Wordpress Gutenberg: React components on front end

Gutenberg 仍然很新,但我仍然希望有人遇到过这个问题并找到了解决方案。

我已经使用 create-guten-block 对项目进行样板化并创建了一个测试块。我 运行 遇到的问题是,当我尝试使用 React 组件在前端修改状态时,没有任何反应。这些组件通过 save() 加载得很好,但是当您尝试执行一些简单的操作(例如切换列表)时,前端仍然对状态更改没有响应。我还会注意到 create-guten-block 不加载任何前端 JS,所以我将编译的 javascript 换成在前端加载,但仍然无法让它工作。

这是我从 Codecademy 提取的一些代码,作为一个简单的测试示例。当您 select 一个名字时,它会更改 sibling.js 中的文本以显示该名字。该代码在 create-react-app 中运行良好,但在前端作为 Gutenberg 中的块不执行任何操作:

block.js

import { Parent } from './parent';

// More code here 

save: function( props ) {
    return (
          <div>
              <Parent />
          </div>
     );
 },

parent.js

import React from 'react';
import { Child } from './child';
import { Sibling } from './sibling';

export class Parent extends React.Component {
    constructor(props) {
        super(props);

        this.state = { name: 'Frarthur' };

        this.changeName = this.changeName.bind(this);
    }

    changeName(newName) {
        this.setState({
        name: newName
        });
    }

    render() {
        return (
        <div>
            <Child onChange={this.changeName} />
            <Sibling name={this.state.name} />
        </div>
        );
    }
};

child.js

import React from 'react';

export class Child extends React.Component {
    constructor(props) {
        super(props);

        this.handleChange = this.handleChange.bind(this);
    }

    handleChange(e) {
        const name = e.target.value;
        this.props.onChange(name);
    }

    render() {
        return (
        <div>
            <select
            id="great-names"
            onChange={this.handleChange}>

                <option value="Frarthur">Frarthur</option>
                <option value="Gromulus">Gromulus</option>
                <option value="Thinkpiece">Thinkpiece</option>
            </select>
        </div>
        );
    }
}

sibling.js

import React from 'react';

export class Sibling extends React.Component {
    render() {
        const name = this.props.name;
        return (
        <div>
            <h1>Hey, my name is {name}!</h1>
            <h2>Don't you think {name} is the prettiest name ever?</h2>
            <h2>Sure am glad that my parents picked {name}!</h2>
        </div>
        );
    }
}

据我了解,Gutenburg 仅支持等式的 编辑器 端的交互性。是的,你在 React 中定义了 view 端,但是这个视图在 post 被保存时被渲染为静态标记,然后只有这个静态标记被传递到客户(读者)。

好处是您可以免费获得 "server side rendering",并且您的客户不需要 React 来查看 post。缺点是如果你想进行客户端交互,它超出了 Gutenburg 的范围,你必须找到自己的方式。

Gutenberg 很棒,但不能说它的文档是一样的。它就像任何其他 Wordpress 文档一样,过于冗长、组织混乱和冗长。我认为它与地域和目标消费者有关。

我花了一些时间,翻了几遍手册才明白什么是方块。资源稀缺,人们通常将块与其在编辑器中的屏幕视觉表示混淆。

话虽这么说,让我们从什么是古腾堡积木开始。古腾堡块是优雅的简码,就像这样:

<!-- wp:paragraph {"key": "value"} -->
<p>Welcome to the world of blocks.</p>
<!-- /wp:paragraph -->

这些短代码由编辑器呈现为反应组件以进行可视化表示。

记住像这里这样的短代码,[gallery id="123" size="medium"] 可以通过 tinymce 插件将其呈现为可视化表示,您会在编辑器中看到完整的功能库 window。想法是一样的,只是这次古腾堡编辑器将略有不同的短代码呈现为视觉表示。

现在,混淆出现了,因为 WordPress 文档也将这些视觉表示作为块来处理。但是整个渲染-序列化-解析-重新渲染循环的真实来源是一个,那就是所谓的 "graceful shortcodes",其余的是这些短代码采用的不同形式和表示形式。比如说,在编辑器上下文中,它是一个渲染的反应组件,在前端它只是常规 html.

edit 函数的 return 元素将决定块在编辑器中的显示方式 window:

<!-- language: lang-js -->
registerBlockType(«NAMESPACE/BLOCK_NAME», {
    edit: function(props){
        // Should return a react element
    }
})

了解区块的生命周期对于更好地理解它们至关重要。让我们从头开始:

当您单击组件面板中的块图标时,save 函数的 return 将被渲染和序列化并插入到页面中。

<!-- language: lang-js -->
registerBlockType("NAMESPACE/BLOCK_NAME", {
    save: function(props){
       // Should return a react element
    }
})

save 函数应该 return 一个反应元素,这个元素将由反应呈现,并由块序列化程序 序列化 并插入到 post 内容作为 block. You can check serializer.js for how React element serialized into a block1.

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

如果是动态块,save函数会returnnull,所以不会有内容。块看起来像这样:

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

注意自动关闭评论:

blocks grammar中,第一个叫静态块(_Block_Balanced_),第二个叫动态块(_Block_Void_)。

请务必注意,静态块包含呈现的内容和一个属性对象。对于动态块,应在块注册期间将 render_callback 提供给 register_block_type 函数。

因此,当请求 the_content 时,服务器获取 the_content 并在响应请求之前将其传递给 filters

在此阶段,属性将从静态块中剥离,内容将被 returned,因为静态块本身已经包含其内容。对于动态块,render_callback 将被调用,其 return 值将被 return 编辑为块内容。这就是他们所说的 某种程度上完全同构 3 in the documentation. You can check out render_block 函数在 Wordpress 核心中的意思。

当您通过 gutenberg 的视觉元素编辑块时,块将重新经历重新序列化过程,并根据您所做的更改在页面上绘制新的视觉表示。

<!-- wp:paragraph {"key": "value"} -->
<p>Welcome to the world of blocks.</p>
<!-- /wp:paragraph -->

单击发布按钮后,如文档所述,此序列化数据或行数据将保存到数据库中。

假设您在保存后关闭页面。当您下次打开它时,保存的块将由块解析器解析,并将可视化表示绘制到页面上。你可以看看parser2

在解析期间,块标记将针对 save 函数进行验证。如果您在两次编辑之间更改了 save 函数的 return,则之前保存的块标记将无效或 deprecated。您可以通过在 registerBlockType 中的块设置中提供升级路径来更新已弃用的代码。但是,您更改 edit 函数不会产生任何影响,因为它控制块在编辑器屏幕上的显示方式。

升级路径只是一个具有功能和属性的对象数组。已弃用的块将由该数组中的每个元素根据优先级进行检查,如果块与新版本兼容,则将被迁移,否则旧版本将被 returned.

现在来回答您的问题,当请求前端服务器上的页面时,将向您发送完整的 html。所以,在前面你得到的是静态的 html,而不是反应元素。

因此,实际上 save 函数除了创建包含在块注释 <!-- wp:image --><!-- /wp:image --> 中的静态 html 之外与前端无关,这在编辑内容时发生。在前端服务 the_content 时从不 运行 或咨询。

为了增加交互性,你必须专门针对前端编写代码,就像你在 Gutenberg 之前所做的那样。

您可以通过在编辑器 window 中切换到 代码编辑器 使用 更多工具和选项 按钮,更新 按钮旁边的垂直省略号。

从前端的角度来看,创建时使用tinymce编辑器还是Gutenberg编辑器还是普通html没有区别the_content

这取决于你在注册块时将另一个 javascript 文件加入队列还是使用你通过 enqueue_block_assets 加入队列的文件。

要使用 React,您必须使用 ReactDOM 将组件挂载到文档中。好消息是 Wordpess 已经在全局 space 中提供了 React 和 ReactDOM,但是您需要在排队脚本时指明依赖关系。