块编辑器开发文档

💡 云策文档标注

概述

本文档介绍了 WordPress 块模板的概念、作用及实现方式。块模板用于定义编辑器会话的默认初始状态,支持动态设置、注册到文章类型,并计划扩展为页面模板和主题层次结构。

关键要点

  • 块模板由块列表组成,可包含预定义属性、占位符内容,分为静态或动态类型。
  • 模板范围包括客户端动态设置默认状态(如 defaultBlock)和注册为特定文章类型的默认模板。
  • API 支持在 PHP 或 JavaScript 中声明模板,通过数组定义块类型(块名称和可选属性)。
  • 自定义文章类型可在注册时指定模板,使用 template 参数。
  • 锁定功能通过 template_lock 属性控制模板在 UI 中的操作权限,如防止插入、移动或删除块。
  • 支持嵌套模板,容器块(如 columns)可分配嵌套模板以实现复杂布局。

代码示例

// PHP 示例:为文章类型注册模板
<?php
function myplugin_register_template() {
    $post_type_object = get_post_type_object( 'post' );
    $post_type_object->template = array(
        array( 'core/image' ),
    );
}
add_action( 'init', 'myplugin_register_template' );

// JavaScript 示例:使用 InnerBlocks 和模板创建新块
const el = React.createElement;
const { registerBlockType } = wp.blocks;
const { InnerBlocks } = wp.blockEditor;

const BLOCKS_TEMPLATE = [
    [ 'core/image', {} ],
    [ 'core/paragraph', { placeholder: 'Image Details' } ],
];

registerBlockType( 'myplugin/template', {
    title: 'My Template Block',
    category: 'widgets',
    edit: ( props ) => {
        return el( InnerBlocks, {
            template: BLOCKS_TEMPLATE,
            templateLock: false,
        } );
    },
    save: ( props ) => {
        return el( InnerBlocks.Content, {} );
    },
} );

注意事项

  • 块属性参考 block.json 文件,例如 wp-includes/blocks/heading/block.json 中的 level 属性和 anchor 参数支持。
  • 锁定选项包括 contentOnly(阻止所有操作,不可覆盖)、all(阻止插入、移动、删除块)和 insert(阻止插入或删除,但允许移动)。
  • 模板锁定可被 InnerBlocks 继承,若无设置则使用父级或文章类型的锁定配置。
  • 块级锁定通过 lock 属性实现,优先级高于 templateLock,可控制移动和移除权限。

📄 原文内容

A block template is defined as a list of block items. Such blocks can have predefined attributes, placeholder content, and be static or dynamic. Block templates allow specifying a default initial state for an editor session.

The scope of templates include:

  • Setting a default state dynamically on the client. (like defaultBlock)
  • Registered as a default for a given post type.

Planned additions:

  • Saved and assigned to pages as “page templates”.
  • Defined in a template.php file or pulled from a custom post type (wp_templates) that is site specific.
  • As the equivalent of the theme hierarchy.

API

Templates can be declared in JS or in PHP as an array of blockTypes (block name and optional attributes).

The first example in PHP creates a template for posts that includes an image block to start, you can add as many or as few blocks to your template as needed.

PHP example:

<?php
function myplugin_register_template() {
    $post_type_object = get_post_type_object( 'post' );
    $post_type_object->template = array(
        array( 'core/image' ),
    );
}
add_action( 'init', 'myplugin_register_template' );

The following example in JavaScript creates a new block using InnerBlocks and templates, when inserted creates a set of blocks based off the template.

const el = React.createElement;
const { registerBlockType } = wp.blocks;
const { InnerBlocks } = wp.blockEditor;

const BLOCKS_TEMPLATE = [
    [ 'core/image', {} ],
    [ 'core/paragraph', { placeholder: 'Image Details' } ],
];

registerBlockType( 'myplugin/template', {
    title: 'My Template Block',
    category: 'widgets',
    edit: ( props ) => {
        return el( InnerBlocks, {
            template: BLOCKS_TEMPLATE,
            templateLock: false,
        } );
    },
    save: ( props ) => {
        return el( InnerBlocks.Content, {} );
    },
} );

See the Meta Block Tutorial for a full example of a template in use.

Block attributes

To find a comprehensive list of all block attributes that you can define in a template, consult the block’s block.json file, and look at the attributes and supports values.

For example, packages/block-library/src/heading/block.json shows that the block has a level attribute, and supports the anchor parameter.

If you don’t have the Gutenberg plugin installed, you can find block.json files inside wp-includes/blocks/heading/block.json.

Custom post types

A custom post type can register its own template during registration:

function myplugin_register_book_post_type() {
    $args = array(
        'public' => true,
        'label'  => 'Books',
        'show_in_rest' => true,
        'template' => array(
            array( 'core/image', array(
                'align' => 'left',
            ) ),
            array( 'core/heading', array(
                'placeholder' => 'Add Author...',
            ) ),
            array( 'core/paragraph', array(
                'placeholder' => 'Add Description...',
            ) ),
        ),
    );
    register_post_type( 'book', $args );
}
add_action( 'init', 'myplugin_register_book_post_type' );

Locking

Sometimes the intention might be to lock the template on the UI so that the blocks presented cannot be manipulated. This is achieved with a template_lock property.

function myplugin_register_template() {
    $post_type_object = get_post_type_object( 'post' );
    $post_type_object->template = array(
        array( 'core/paragraph', array(
            'placeholder' => 'Add Description...',
        ) ),
    );
    $post_type_object->template_lock = 'all';
}
add_action( 'init', 'myplugin_register_template' );

Options:

  • contentOnly — prevents all operations. Additionally, the block types that don’t have content are hidden from the list view and can’t gain focus within the block list. Unlike the other lock types, this is not overridable by children.
  • all — prevents all operations. It is not possible to insert new blocks, move existing blocks, or delete blocks.
  • insert — prevents inserting or removing blocks, but allows moving existing blocks.

Lock settings can be inherited by InnerBlocks. If templateLock is not set in an InnerBlocks area, the locking of the parent InnerBlocks area is used. If the block is a top level block, the locking configuration of the current post type is used.

Individual block locking

Alongside template level locking, you can lock individual blocks; you can do this using a lock attribute on the attributes level. Block-level lock takes priority over the templateLock feature. Currently, you can lock moving and removing blocks.

attributes: {
  // Prevent a block from being moved or removed.
  lock: {
    remove: true,
    move: true,
  }
}

Options:

  • remove — Locks the ability of a block from being removed.
  • move — Locks the ability of a block from being moved.

You can use this with templateLock to lock all blocks except a single block by using false in remove or move.

$template = array(
    array( 'core/image', array(
        'align' => 'left',
    ) ),
    array( 'core/heading', array(
        'placeholder' => 'Add Author...',
    ) ),
    // Allow a Paragraph block to be moved or removed.
    array( 'core/paragraph', array(
        'placeholder' => 'Add Description...',
        'lock' => array(
            'move'   => false,
            'remove' => false,
        ),
    ) ),
);

Nested templates

Container blocks like the columns blocks also support templates. This is achieved by assigning a nested template to the block.

$template = array(
    array( 'core/paragraph', array(
        'placeholder' => 'Add a root-level paragraph',
    ) ),
    array( 'core/columns', array(), array(
        array( 'core/column', array(), array(
            array( 'core/image', array() ),
        ) ),
        array( 'core/column', array(), array(
            array( 'core/paragraph', array(
                'placeholder' => 'Add an inner paragraph'
            ) ),
        ) ),
    ) )
);