Wordpress Gutenberg:前端的 React 组件

Posted

技术标签:

【中文标题】Wordpress Gutenberg:前端的 React 组件【英文标题】:Wordpress Gutenberg: React components on front end 【发布时间】:2019-01-17 03:52:25 【问题描述】:

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

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

这是我从 Codecademy 中提取的一些代码,作为一个简单的测试示例。当您选择一个名称时,它会更改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>
        );
    

【问题讨论】:

【参考方案1】:

Gutenberg 很棒,但不能对它的文档说同样的话。它就像任何其他 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 渲染并由块序列化器序列化 并作为block 插入到帖子内容中。你可以查看serializer.js,了解 React 元素是如何序列化为块的1

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

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

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

注意自我关闭评论:

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

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

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

在这个阶段,属性将从静态块中剥离,并且内容将被返回,因为静态块本身已经包含了它们的内容。对于动态块,将调用 render_callback 并将其返回值作为块内容返回。这就是文档中 某种程度上完全同构3 的意思。您可以在 Wordpress 核心中查看render_block 函数。

当您通过古腾堡的视觉元素编辑块时,该块将重新进行重新序列化过程,并且将根据您所做的更改将新的视觉表示绘制到页面上。

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

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

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

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

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

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

因此,实际上save 函数与前端无关,只是创建包裹在块 cmets &lt;!-- wp:image --&gt;&lt;!-- /wp:image --&gt; 中的静态 html,这在编辑内容时发生。在前端服务 the_content 时,它永远不会运行或咨询。

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

您可以在编辑器窗口中使用更多工具和选项按钮切换到代码编辑器,以纯文本形式查看the_content更新按钮。

从前端的角度来看,创建the_content时使用tinymce编辑器还是古腾堡编辑器还是纯html没有区别。

注册块时,您可以将另一个 javascript 文件排入队列或使用您通过 enqueue_block_assets 排入队列的文件。

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

【讨论】:

抱歉花了这么长时间将其标记为最佳答案。谢谢你这么彻底! 您能举例说明如何使用 ReactDOM 将组件安装到文档上吗?我有类似的问题,在保存方法中,我想使用 React 并捕获诸如 onClick 之类的事件。 @Ognyan 当然。常量元素 =

你好,世界

; ReactDOM.render(element, document.getElementById('root'));确保您的 html 文件中有 id 属性为“root”的元素。你在这里有更详细的解释reactjs.org/docs/rendering-elements.html。如果您以通常的方式将 Gutenberg 与 wordpress 一起使用,react 可能不是一个好主意。
@SnnSnn 这应该放在save 函数中吗?我需要在前端(用户应该单击按钮)而不是在编辑器中捕获事件! @Ognyan 如果你有保存功能,这意味着块内容将在前端呈现,只需使用vanilla js或jquery,就像你以前一样。【参考方案2】:

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

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

【讨论】:

谢谢贝西!在过去的三个月里,我已经很好地处理了它,并且只提供了与 jQuery 的前端交互性。不理想,但已经被 Wordpress 加入队列并且可以正常工作。 你能举例说明如何使用 ReactDOM 将组件安装到文档上吗?我有类似的问题,在保存方法中,我想使用 React 并捕获诸如 onClick 之类的事件。

以上是关于Wordpress Gutenberg:前端的 React 组件的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Wordpress 中列出和重新排列或操作 Gutenberg 块类别

Wordpress Gutenberg 自定义列块

以编程方式触发 Wordpress Gutenberg “转换为块”

scss WordPress Gutenberg专栏SCSS样式

php WordPress - 禁用Gutenberg而不使用插件。

如何向 WordPress Gutenberg 块添加自定义块?