“遗留小部件”块允许用户添加、编辑和预览由插件注册以及使用经典小部件编辑器添加的小部件。

可以通过插入器插入“遗留小部件”块并从块的下拉菜单中选择小部件来添加第三方小部件。

也可以通过在插入器中搜索小部件名称并选择该小部件来添加第三方小部件。将插入“遗留小部件”块的一种变体。

与“遗留小部件”块的兼容性

小部件添加事件

“遗留小部件”块将以类似于自定义化器(Customizer)的方式显示小部件的表单,因此与大多数第三方小部件兼容。

如果小部件在其表单中使用 JavaScript,则必须在 document 上触发 'widget-added' jQuery 事件之后将事件添加到 DOM 中。

例如,当选中“更改密码”复选框时,小部件可能需要显示“密码”字段。

( function ( $ ) {
    $( document ).on( 'widget-added', function ( $event, $control ) {
        $control.find( '.change-password' ).on( 'change', function () {
            var isChecked = $( this ).prop( 'checked' );
            $control.find( '.password' ).toggleClass( 'hidden', ! isChecked );
        } );
    } );
} )( jQuery );

请注意,所有小部件的事件处理程序都在 widget-added 回调中添加。

显示“无预览可用。”

当未选择“遗留小部件”块时,“遗留小部件”块将显示小部件的预览。

当小部件的 widget() 函数不渲染任何内容或仅渲染空 HTML 元素时,“遗留小部件”块会自动显示“无预览可用。”消息。

小部件可以利用这一点,在不应显示预览时从 widget() 提前返回。

class ExampleWidget extends WP_Widget {
    ...
    public function widget( $instance ) {
        if ( ! isset( $instance['name'] ) ) {
            // Name is required, so display nothing if we don't have it.
            return;
        }
        ?>
        <h3>Name: <?php echo esc_html( $instance['name'] ); ?></h3>
        ...
        <?php
    }
    ...
}

允许迁移到块

您可以允许用户轻松地将包含特定小部件的“遗留小部件”块迁移到一个或多个块。这允许插件作者逐步淘汰其小部件,转而使用更直观且可在更多地方使用的块。

以下步骤展示了如何完成此操作。

1) 在 REST API 中显示小部件实例

首先,我们需要告诉 WordPress 可以安全地在 REST API 中显示您的小部件实例数组。

如果满足以下条件,则可以安全地执行此操作:

  • 您知道您的小部件在 $instance 中存储的所有值都可以表示为 JSON;并且
  • 您知道您的小部件不会在 $instance 中存储任何应隐藏于拥有自定义站点权限的用户之外的私有数据。

如果这样做是安全的,则在注册小部件时包含一个名为 show_instance_in_rest 的小部件选项,并将其值设置为 true。

class ExampleWidget extends WP_Widget {
    ...
    /**
     * Sets up the widget
     */
    public function __construct() {
        $widget_ops = array(
            // ...other options here
            'show_instance_in_rest' => true,
            // ...other options here
        );
        parent::__construct( 'example_widget', 'ExampleWidget', $widget_ops );
    }
    ...
}

这允许块编辑器和其他 REST API 客户端通过访问 REST API 响应中的 instance.raw 来查看您的小部件实例数组。

请注意,WordPress 5.8.0 之前的版本允许您通过在扩展 WP_Widget 的类中将 $show_instance_in_rest 设置为 true 来启用此功能。

class ExampleWidget extends WP_Widget {
    ...
    public $show_instance_in_rest = true;
    ...
}

现在已弃用此方法,转而使用小部件选项方法。

2) 添加块转换

现在,我们可以定义一个 块转换(block transform),以告知块编辑器用哪个块替换包含您小部件的“遗留小部件”块。

这是通过向您的块的定义添加 JavaScript 代码来完成的。在本示例中,我们定义了一个转换,将 ID 为 'example_widget' 的小部件转换为名称为 'example/block' 的块。

transforms: {
    from: [
        {
            type: 'block',
            blocks: [ 'core/legacy-widget' ],
            isMatch: ( { idBase, instance } ) => {
                if ( ! instance?.raw ) {
                    // Can't transform if raw instance is not shown in REST API.
                    return false;
                }
                return idBase === 'example_widget';
            },
            transform: ( { instance } ) => {
                return createBlock( 'example/block', {
                    name: instance.raw.name,
                } );
            },
        },
    ]
},

3) 将小部件从“遗留小部件”块中隐藏

作为最后的修饰,我们可以告诉“遗留小部件”块在“选择小部件”下拉菜单和块插入器中隐藏您的小部件。这鼓励用户使用替换您小部件的块。

可以使用 widget_types_to_hide_from_legacy_widget_block 过滤器来完成此操作。

function hide_example_widget( $widget_types ) {
    $widget_types[] = 'example_widget';
    return $widget_types;
}
add_filter( 'widget_types_to_hide_from_legacy_widget_block', 'hide_example_widget' );

在其他块编辑器中使用“遗留小部件”块(高级)

您可以选择允许在 WordPress 文章编辑器等其他块编辑器中使用“遗留小部件”块。默认情况下未启用此功能。

首先,确保加载了旧版小部件所需的任何样式和脚本。
一种方便的方法是手动执行用户浏览到小部件 WP Admin
屏幕时通常运行的所有钩子。

add_action( 'admin_print_styles', function() {
    if ( get_current_screen()->is_block_editor() ) {
        do_action( 'admin_print_styles-widgets.php' );
    }
} );
add_action( 'admin_print_scripts', function() {
    if ( get_current_screen()->is_block_editor() ) {
        do_action( 'load-widgets.php' );
        do_action( 'widgets.php' );
        do_action( 'sidebar_admin_setup' );
        do_action( 'admin_print_scripts-widgets.php' );
    }
} );
add_action( 'admin_print_footer_scripts', function() {
    if ( get_current_screen()->is_block_editor() ) {
        do_action( 'admin_print_footer_scripts-widgets.php' );
    }
} );
add_action( 'admin_footer', function() {
    if ( get_current_screen()->is_block_editor() ) {
        do_action( 'admin_footer-widgets.php' );
    }
} );

然后,使用 registerLegacyWidgetBlock 注册“遗留小部件”块,该函数
定义在 @wordpress/widgets 包中。

add_action( 'enqueue_block_editor_assets', function() {
    wp_enqueue_script( 'wp-widgets' );
    wp_add_inline_script( 'wp-widgets', 'wp.widgets.registerLegacyWidgetBlock()' );
} );