title: "关于传统小工具区块" post_status: publish comment_status: open taxonomy: category: - gutenberg-docs post_tag: - Widgets - How To Guides - Repos


关于传统小工具区块

传统小工具区块允许用户添加、编辑和预览由插件注册的第三方小工具,以及使用经典小工具编辑器添加的小工具。

可通过区块插入器添加传统小工具区块,并从区块下拉菜单中选择小工具来添加第三方小工具。

也可通过在区块插入器中搜索小工具名称并选择小工具来添加第三方小工具。系统将插入一个传统小工具区块的变体。

与传统小工具区块的兼容性

widget-added 事件

传统小工具区块将以类似于自定义工具的方式显示小工具表单,因此与大多数第三方小工具兼容。

如果小工具在其表单中使用 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 回调中添加。

Displaying "No preview available."

The Legacy Widget block will display a preview of the widget when the Legacy Widget block is not selected.

A "No preview available." message is automatically shown by the Legacy Widget block when the widget's widget() function does not render anything or only renders empty HTML elements.

Widgets may take advantage of this by returning early from widget() when a preview should not be displayed.

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) Display the widget's instance in the REST API

First, we need to tell WordPress that it is OK to display your widget's instance array in the REST API.

This can be safely done if:

If it is safe to do so, then include a widget option named show_instance_in_rest with its value set to true when registering your widget.

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

This allows the block editor and other REST API clients to see your widget's instance array by accessing instance.raw in the REST API response.

Note that versions of WordPress prior to 5.8.0 allowed you to enable this feature by setting $show_instance_in_rest to true in the class that extends WP_Widget.

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

This is now deprecated in favour of the widget option method.

2) Add a block transform

Now, we can define a block transform which tells the block editor what to replace the Legacy Widget block containing your widget with.

This is done by adding JavaScript code to your block's definition. In this example, we define a transform that turns a widget with ID 'example_widget' into a block with name '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 管理界面时通常运行的所有钩子。

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' );
    }
} );

然后,使用 @wordpress/widgets 包中定义的 registerLegacyWidgetBlock 注册传统小工具区块。

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