9

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

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

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

块.js

import { Parent } from './parent';

// More code here 

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

父.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>
        );
    }
}

兄弟.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>
        );
    }
}
4

2 回答 2

25

古腾堡很棒,但不能对它的文档说同样的话。它就像任何其他 Wordpress 文档一样,过于冗长、组织不善和健谈。我认为它与领土和目标消费者有关。

我花了一些时间和几次通过手册来了解什么是块。资源稀缺,人们通常会将块与编辑器中的屏幕视觉表示混淆。

话虽如此,让我们从古腾堡区块开始。Gutenberg 块是优雅的短代码,如下所示:

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

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

请记住这里的短代码,[gallery id="123" size="medium"]它可以通过 tinymce 插件呈现为可视化表示,您将在编辑器窗口中看到完全形成且正常运行的画廊。这个想法是一样的,只是这次古腾堡编辑器将略有不同的短代码呈现为视觉表示。

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

函数的返回元素edit将决定块在编辑器窗口中的显示方式:

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

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

当您单击组件面板中的块图标时,save函数的返回将被呈现并序列化并插入到页面中。

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

save函数应该返回一个 react 元素,该元素将由 react 渲染并由块序列化器序列化并作为插入到帖子内容中。您可以检查serializer.jsReact 元素如何序列化为块1

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

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

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

注意自我关闭评论:

块语法中,第一个称为静态块(_Block_Balanced_),第二个称为动态块(_Block_Void_)。

需要注意的是,静态块包含渲染内容和属性对象。对于动态块,render_callbackregister_block_type在块注册期间提供功能。

因此,当the_content被请求时,服务器会在响应请求之前获取the_content并通过几个过滤器。

在此阶段,将从静态块中剥离属性并返回内容,因为静态块本身已包含其内容。对于动态块,将调用 render_callback 并将其返回值作为块内容返回。这就是他们在文档中以某种方式完全同构的3的意思。render_block您可以在 Wordpress 核心中签出功能。

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

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

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

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

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

升级路径只是一个具有函数和属性的对象数组。不推荐使用的块将由该数组上的每个元素根据优先级进行检查,如果块与新版本兼容,将被迁移,如果不是旧版本,则返回。

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

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

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

您可以通过使用更多工具和选项按钮在编辑器窗口中the_content切换到代码编辑器来查看其纯文本形式,更新按钮旁边的垂直省略号。

从前端的角度来看,在创建the_content.

这取决于您将另一个 javascript 文件排入队列或使用您enqueue_block_assets在注册块时通过的那个。

要使用 React,您必须使用 ReactDOM 将组件安装到文档上。好消息是 Wordpess 已经在全局空间中提供了 React 和 ReactDOM,但是您需要在对脚本进行排队时指出依赖关系。

于 2019-01-28T22:30:37.337 回答
5

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

好处是您可以免费获得“服务器端渲染”,并且您的客户端不需要 React 即可查看帖子。缺点是如果你想做客户端交互,它超出了古腾堡的范围,你必须找到自己的方式。

于 2018-11-05T12:17:22.587 回答