标签: 古腾堡开发

  • 如何为古腾堡创建动态区块

    如何为古腾堡创建动态区块

    你还在为古腾堡感到困惑吗?或者您是那些坚信区块编辑器的潜力并想知道使用区块编辑器可以将他们的创造力推到多远的人中的一员?

    无论您属于哪种类型的用户,古腾堡都会留下来,这篇文章将让您深入了解 WordPress 块编辑器幕后发生的事情。但这还不是全部!

    我们之前的教程中我们提供了对Gutenberg区块开发的一般介绍之后,本文超越了基础知识,介绍了更高级的区块类型。这些块被称为动态区块。

    今天,您将了解什么是动态区块、它们是如何工作的,以及从头开始创建动态区块所需了解的一切。

    那么,什么是Gutenberg动态区块,静态区块和动态区块之间的主要区别是什么?

    1. 什么是动态区块?一个例子
    2. 从开发人员的角度来看Gutenberg动态区块
    3. 如何访问文章数据
    4. 如何创建动态区块:示例项目
    5. 在编辑器中构建要渲染的区块
    6. 构建要在页面上呈现的区块
    7. 动态区块开发的推荐资源

    什么是动态区块?一个例子

    使用静态区块时,用户在编辑文章或页面时手动添加内容,而使用动态区块时,内容会在页面加载时动态加载和处理。使用动态区块,区块内容从数据库中提取并按原样显示或由任何类型的数据操作产生。

    让我们用一个例子来解释一下。假设您要创建一组嵌套区块,显示文章作者详细信息以及来自同一作者的最新文章的选择。

    包括文章作者和最新文章组区块

    包括文章作者和最新文章组区块

    作为Gutenberg用户,您可以使用以下区块:

    • 标题核心区块
    • 文章作者核心区块
    • 最新文章核心区块

    您还可以创建一个包含这些区块的组,并将该组添加到可重复使用的区块中以供将来使用。

    将组区块添加到可重用区块

    将组区块添加到可重用区块

    这很简单,不是吗?您可以创建一个动态区块并将其添加到您的文章和页面中。

    WordPress 5.9开始,区块编辑器提供了90多个不同的区块,您很可能会立即找到适合您的区块。而且,如果您需要更多,请在WordPress插件目录中快速搜索,您会发现很多免费插件提供了额外的区块

    但是,如果您是WordPress开发人员,或者您正计划从事WordPress开发人员的职业怎么办?也许您有非常特定的需求,找不到您正在寻找的区块,或者您只是想获得新的专业技能。在这种情况下,您可能想学习如何创建动态区块。

    从开发人员的角度来看Gutenberg动态区块

    动态区块有两个主要用例。

    第一个用例是当包含区块的页面尚未更新时,您需要更新区块的内容。例如,当区块包含最新文章或评论的列表时会发生这种情况,并且通常每当区块的内容是使用从数据库检索的数据动态生成时。

    添加查询循环区块

    添加查询循环区块

    第二个用例是需要立即在前端显示对区块代码的更新。使用动态区块而不是静态区块会导致更改立即应用于所有出现的区块。

    另一方面,如果您要更改由静态区块生成的HTML,用户将看到一个无效对话框,直到该区块的先前版本的每个实例都被删除并替换为新版本,或者您将旧版本标记为不推荐使用的版本(另请参阅弃用区块验证、弃用和迁移经验)。

    意外或无效的内容

    意外或无效的内容

    话虽如此,在开始构建动态区块之前,您需要了解一些概念。

    1. 应用程序状态和数据存储
    2. Gutenberg中的模块化、包和数据存储
    3. WordPress数据存储

    应用程序状态和数据存储

    Gutenberg是一个React SPA应用程序,Gutenberg中的所有内容都是一个React组件。编辑器中的文章标题、标题、段落、图像和任何HTML内容块都是React组件,以及侧边栏和区块工具栏控件。

    在我们之前的文章中,我们只使用属性来存储数据。在本文中,我们将通过引入state的概念更进一步。

    简单地说,state对象是一个普通的JavaScript对象,用于包含有关组件的信息。组件的state可以随着时间而改变,并且任何时候改变,组件都会重新渲染。

    state对象类似,属性是普通的JavaScript对象,用于保存有关组件的信息。但是props和state之间有一个关键区别

    props传递给组件(类似于函数参数),而状态在组件内管理(类似于在函数中声明的变量)。

    您可以将状态视为在给定时间点获取的数据快照,应用程序存储这些数据以控制组件的行为。例如,如果块编辑器设置侧边栏打开,则一条信息将存储在state对象的某个位置。

    当信息在单个组件内共享时,我们称之为本地状态。当信息在应用程序内的组件之间共享时,我们称之为应用程序状态

    Application State与store的概念密切相关。根据Redux文档

    一个store保存着应用程序的整个状态树。更改其内部状态的唯一方法是在其上分派一个操作

    因此,Redux将应用程序状态存储在单个不可变对象树(即存储)中。对象树只能通过使用actionsreducers创建新对象来更改。

    在WordPress中,商店由WordPress数据模块管理。

    Gutenberg中的模块化、包和数据存储

    Gutenberg存储库从头开始构建在几个可重用且独立的模块上,这些模块组合在一起构建了编辑界面。这些模块也称为

    官方文档列出了两种不同类型的包

    • 生产包组成了在浏览器中运行的生产代码。WordPress中有两种类型的生产包:
    • 开发包用于开发模式。这些包包括用于linting、测试、构建等的工具。

    在这里,我们最感兴趣的是带有数据存储的包,用于检索和操作数据。

    WordPress数据存储

    WordPress 数据模块建立在Redux之上,并共享三个Redux核心原则,尽管有一些关键区别

    Info Redux是JavaScript应用程序的状态管理器。Redux的工作方式总结为三个基本原则

    • 单一事实来源:应用程序的全局状态存储在单个存储中的对象树中。
    • 状态是只读的:改变状态的唯一方法是发出一个动作,一个描述发生了什么的对象。
    • 使用纯函数进行更改:要指定状态树如何通过操作进行转换,您可以编写纯reducer。

    官方文档提供了以下定义

    WordPress的数据模块用作管理插件和 WordPress 本身的应用程序状态的中心,提供工具来管理不同模块内和模块之间的数据。它被设计为一种用于组织和共享数据的模块化模式:简单到足以满足小型插件的需求,同时可扩展以服务于复杂的单页应用程序的需求。

    默认情况下,Gutenberg在应用程序状态中注册多个数据存储。这些商店中的每一个都有特定的名称和用途:

    通过这些商店,您将能够访问一大堆数据:

    1. 与当前文章相关的数据,例如文章标题、摘录、类别和标签、区块等。
    2. 与用户界面相关的数据,即开关是打开还是关闭。
    3. 与整个WordPress安装相关的数据,例如注册分类法、文章类型、博客标题、作者等。

    这些存储存在于全局wp对象中。要访问商店的状态,您将使用select函数。

    要查看它是如何工作的,请创建一个新文章或页面并启动浏览器的检查器。找到控制台并输入以下代码行:

    wp.data.select(“core”)
    wp.data.select(“core”)
    wp.data.select("core")

    结果将是一个对象,其中包含可用于从core数据存储中获取数据的函数列表。这些函数称为选择器并充当访问状态值的接口。

    核心WordPress数据存储对象

    核心WordPress数据存储对象

    Info selectors对象包括一组用于访问和导出状态值的函数。选择器是一个接受状态和可选参数并从状态返回一些值的函数。调用选择器是从您的状态中检索数据的主要机制,并作为对原始数据的有用抽象,这些原始数据通常更容易更改并且不太容易用作规范化对象。(来源:Github

    WordPress数据存储通常包含有关WordPress的信息,选择器是您获取该信息的方式。例如,getCurrentUser()返回当前用户的详细信息:

    wp.data.select(“core”).getCurrentUser()
    wp.data.select(“core”).getCurrentUser()
    wp.data.select("core").getCurrentUser()

    检查getCurrentUser响应

    检查getCurrentUser响应

    另一个可用于从数据存储中检索用户详细信息的选择器是getUsers():

    wp.data.select(“core”).getUsers()
    wp.data.select(“core”).getUsers()
    wp.data.select("core").getUsers()

    下图显示了响应对象:

    检查getUsers响应

    检查getUsers响应

    要获取单个用户的详细信息,您只需键入以下行:

    wp.data.select(“core”).getUsers()[0]
    wp.data.select(“core”).getUsers()[0]
    wp.data.select("core").getUsers()[0]

    使用相同的选择器,您还可以检索author分配了角色的站点用户:

    wp.data.select( ‘core’ ).getUsers({ who: ‘authors’ })
    wp.data.select( ‘core’ ).getUsers({ who: ‘authors’ })
    wp.data.select( 'core' ).getUsers({ who: 'authors' })

    您还可以检索已注册的分类法:

    wp.data.select(“core”).getTaxonomies()
    wp.data.select(“core”).getTaxonomies()
    wp.data.select("core").getTaxonomies()

    检查getTaxonomies响应

    检查getTaxonomies响应

    已注册的文章类型列表:

    wp.data.select(“core”).getPostTypes()
    wp.data.select(“core”).getPostTypes()
    wp.data.select("core").getPostTypes()

    或插件列表:

    wp.data.select(“core”).getPlugins()
    wp.data.select(“core”).getPlugins()
    wp.data.select("core").getPlugins()

    现在让我们尝试访问不同的数据存储。为此,您仍将使用select函数,但提供不同的命名空间。让我们尝试以下方法:

    wp.data.select(“core/edit-post”)
    wp.data.select(“core/edit-post”)
    wp.data.select("core/edit-post")

    现在您将获得以下响应对象。

    访问编辑器的UI数据

    访问编辑器的UI数据

    如果您想知道设置侧边栏是否打开,您可以使用isEditorSidebarOpened选择器:

    wp.data.select(“core/edit-post”).isEditorSidebarOpened()
    wp.data.select(“core/edit-post”).isEditorSidebarOpened()
    wp.data.select("core/edit-post").isEditorSidebarOpened()

    如果侧边栏打开,则此函数返回true

    侧边栏已打开

    侧边栏已打开

    如何访问文章数据

    您现在应该对如何访问数据有了基本的了解。现在我们将仔细研究一个特定的选择器getEntityRecords函数,它是提供对post数据的访问权限的选择器。

    在块编辑器中,右键单击并选择Inspect。在控制台选项卡中,复制并粘贴以下行:

    wp.data.select(“core”).getEntityRecords(‘postType’, ‘post’)
    wp.data.select(“core”).getEntityRecords(‘postType’, ‘post’)
    wp.data.select("core").getEntityRecords('postType', 'post')

    这会向Rest API发送请求,并返回与上次发布的博客文章相对应的记录数组。

    getEntityRecords返回文章列表

    getEntityRecords返回文章列表

    Info 请注意,第一次将请求发送到Rest API时,响应将一直持续为null到请求完成。所以,如果你得到null了,不用担心,然后再试一次。

    getEntityRecords接受三个参数

    • kind 字符串:实体类型(即postType)。
    • name 字符串:实体名称(即post)。
    • query ?Object:可选术语查询(即{author: 0})。

    您可以使用arguments对象构建更具体的请求。

    例如,您可以决定响应应该只包含指定类别的文章:

    wp.data.select