woocommerce/packages/php/email-editor/docs/zh-cn/block-registration.md
2026-04-15 10:18:01 +08:00

15 KiB
Raw Permalink Blame History

电子邮件编辑器的区块注册

本指南解释了如何注册 WordPress 区块以支持在 WooCommerce 电子邮件编辑器中进行电子邮件渲染。电子邮件编辑器扩展了 WordPress 古腾堡区块,增加了电子邮件特定的渲染功能,允许区块生成与电子邮件客户端兼容的 HTML。

目录

概述

WooCommerce 邮件编辑器允许在邮件兼容的 HTML 中渲染 WordPress 区块。要使一个区块兼容邮件渲染,您需要:

  1. 启用邮件支持:在区块配置中设置 supports.email = true
  2. 提供邮件渲染回调函数:该函数生成邮件兼容的 HTML
  3. 实现渲染逻辑:将区块内容转换为邮件友好的标记

邮件编辑器会自动检测支持邮件的区块,并使用其自定义的渲染回调函数,而不是默认的 WordPress 区块渲染。

区块配置

电子邮件支持属性

要表明区块支持电子邮件渲染,请在区块的 supports 配置中将 email 属性设置为 true

$block_settings = array(
    'name'     => 'my-plugin/custom-block',
    'title'    => 'Custom Block',
    'supports' => array(
        'email' => true,  // 启用电子邮件支持
        // ... 其他支持
    ),
    // ... 其他设置
);

邮件渲染回调

提供专门用于邮件渲染的自定义渲染回调:

$block_settings = array(
    'name'                  => 'my-plugin/custom-block',
    'render_email_callback' => array( $this, 'render_block_for_email' ),
    // ... 其他设置
);

渲染回调应接受三个参数:

  • string $block_content - 原始区块 HTML 内容
  • array $parsed_block - 包含属性的已解析区块数据
  • Rendering_Context $rendering_context - 邮件渲染上下文

为邮件支持注册区块

方法一:使用 block_type_metadata_settings 过滤器

推荐的方法是在 block.json 文件或 JS 客户端注册中添加 supports.email

另一种方法是使用 block_type_metadata_settings 过滤器在注册期间修改块设置:

/**
 * 为自定义区块添加邮件支持。
 */
function add_email_support_to_blocks( $settings, $metadata ) {
    // 应支持邮件渲染的区块列表
    $email_supported_blocks = array(
        'my-plugin/custom-block',
        'my-plugin/another-block',
    );

    if ( in_array( $settings['name'], $email_supported_blocks, true ) ) {
        // 启用邮件支持
        $settings['supports']['email'] = true;
        
        // 设置邮件渲染回调
        $settings['render_email_callback'] = array( 
            'My_Plugin_Email_Renderer', 
            'render_block' 
        );
    }

    return $settings;
}
add_filter( 'block_type_metadata_settings', 'add_email_support_to_blocks', 10, 2 );

方法二:直接区块注册

您也可以直接注册支持邮件的区块:

/**
 * 注册一个支持邮件的自定义区块。
 */
function register_custom_email_block() {
    register_block_type( 'my-plugin/custom-block', array(
        'title'       => __( '自定义邮件区块', 'my-plugin' ),
        'description' => __( '一个支持邮件的自定义区块。', 'my-plugin' ),
        'category'    => 'widgets',
        'supports'    => array(
            'email' => true,
            // ... 其他支持项
        ),
        'attributes'  => array(
            'content' => array(
                'type'    => 'string',
                'default' => '',
            ),
            // ... 其他属性
        ),
        'render_email_callback' => 'my_plugin_render_email_block',
    ) );
}
add_action( 'init', 'register_custom_email_block' );

创建邮件区块渲染器

抽象区块渲染器

对于更复杂的区块,您可以创建一个专用的渲染器类,该类继承自抽象区块渲染器:

<?php

namespace My_Plugin\Email\Renderer;

use Automattic\WooCommerce\EmailEditor\Integrations\Core\Renderer\Blocks\Abstract_Block_Renderer;
use Automattic\WooCommerce\EmailEditor\Engine\Renderer\ContentRenderer\Rendering_Context;
use Automattic\WooCommerce\EmailEditor\Integrations\Utils\Table_Wrapper_Helper;

/**
 * 自定义区块的邮件渲染器。
 */
class Custom_Block_Renderer extends Abstract_Block_Renderer {

    /**
     * 为邮件渲染区块内容。
     *
     * @param string            $block_content 区块内容。
     * @param array             $parsed_block 解析后的区块数据。
     * @param Rendering_Context $rendering_context 渲染上下文。
     * @return string
     */
    public function render( string $block_content, array $parsed_block, Rendering_Context $rendering_context ): string {
        $attributes = $parsed_block['attrs'] ?? array();
        
        // 提取区块属性
        $content    = $attributes['content'] ?? '';
        $text_color = $attributes['textColor'] ?? '';
        $bg_color   = $attributes['backgroundColor'] ?? '';
        
        // 构建邮件兼容的 HTML
        $styles = array();
        if ( $text_color ) {
            $styles[] = 'color: ' . esc_attr( sanitize_hex_color( $text_color ) );
        }
        if ( $bg_color ) {
            $styles[] = 'background-color: ' . esc_attr( sanitize_hex_color( $bg_color ) );
        }
        
        $style_attr = ! empty( $styles ) ? ' style="' . implode( '; ', $styles ) . '"' : '';
        
        $html = sprintf(
            '<div%s>%s</div>',
            $style_attr,
            wp_kses_post( $content )
        );
        
        // 包装成邮件兼容的表格结构
        return Table_Wrapper_Helper::render_table_wrapper( $html );
    }
}

渲染上下文

Rendering_Context 对象提供对主题选项和其他渲染上下文的访问:

public function render( string $block_content, array $parsed_block, Rendering_Context $rendering_context ): string {
    // 获取主题选项
    $theme_settings = $rendering_context->get_theme_settings();
    
    // 主题样式值
    $theme_styles = $rendering_context->get_theme_styles();

    // 获取主题 json
    $theme_json = $rendering_context->get_theme_json();
    
    // 在您的渲染逻辑中使用主题值
    // ...
    
    return $rendered_html;
}

表格包装助手

邮件客户端对 CSS 的支持有限,因此推荐使用基于表格的布局。Table_Wrapper_Helper 提供了用于创建邮件兼容表格结构的实用工具:

use Automattic\WooCommerce\EmailEditor\Integrations\Utils\Table_Wrapper_Helper;

// 基本表格包装
$html = Table_Wrapper_Helper::render_table_wrapper( $content );

// 带自定义属性的表格包装
$html = Table_Wrapper_Helper::render_table_wrapper(
    $content,
    array( 'width' => '100%' ),           // 表格属性
    array( 'style' => 'padding: 20px;' ), // 单元格属性
    array(),                              // 行属性
    true                                  // 渲染单元格包装
);

完整示例

以下是一个注册支持邮件的自定义区块的完整示例:

<?php
/**
 * Plugin Name: Custom Email Block
 * Description: A newsletter signup block with email editor support
 * Version: 1.0.0
 * Author: Your Name
 * Text Domain: my-plugin
 */

// 防止直接访问
if ( ! defined( 'ABSPATH' ) ) {
    exit;
}


/**
 * Custom Email Block Plugin
 */
class My_Custom_Email_Block {

    public function __construct() {
        add_action( 'init', array( $this, 'register_block' ) );
    }

    /**
     * 使用直接注册方法注册自定义区块。
     */
    public function register_block() {
        // 加载区块 JavaScript
        wp_register_script(
            'newsletter-signup-block',
            plugin_dir_url( __FILE__ ) . 'simple-block.js',
            array( 'wp-blocks', 'wp-element', 'wp-block-editor', 'wp-components', 'wp-i18n' ),
            '1.0.0'
        );

        // 注册区块类型
        register_block_type( 'my-plugin/newsletter-signup', array(
            'editor_script'   => 'newsletter-signup-block',
            'render_callback' => array( $this, 'render_frontend_block' ),
            'render_email_callback' => array( $this, 'render_email_block' ),
        ) );
    }

    /**
     * 为前端(非邮件上下文)渲染区块。
     */
    public function render_frontend_block( $attributes ) {
        $title       = $attributes['title'] ?? 'Subscribe to our newsletter';
        $description = $attributes['description'] ?? 'Get the latest updates delivered to your inbox.';
        $button_text = $attributes['buttonText'] ?? 'Subscribe';
        $button_url  = $attributes['buttonUrl'] ?? '';

        $html = '<div class="newsletter-signup-block">';
        $html .= '<h3>' . esc_html( $title ) . '</h3>';
        $html .= '<p>' . esc_html( $description ) . '</p>';

        if ( $button_url && $button_text ) {
            $html .= '<a href="' . esc_url( $button_url ) . '">' . esc_html( $button_text ) . '</a>';
        }

        $html .= '</div>';

        return $html;
    }

    /**
     * 为邮件渲染区块。
     */
    public function render_email_block( $block_content, $parsed_block, $rendering_context ) {
        $attributes = $parsed_block['attrs'] ?? array();

        $title       = $attributes['title'] ?? 'Default Email Title';
        $description = $attributes['description'] ?? 'Default Email: Get the latest updates delivered to your inbox.';
        $button_text = $attributes['buttonText'] ?? 'Default Email: Subscribe';
        $button_url  = $attributes['buttonUrl'] ?? '';

// 创建兼容电子邮件的 HTML
        $html = '<table role="presentation" cellpadding="0" cellspacing="0" style="width: 100%;">
            <tr>
                <td style="padding: 20px; text-align: center; background-color: #f8f9fa;">
                    <h2 style="margin: 0 0 15px 0; font-family: Arial, sans-serif; color: #333;">' . esc_html( $title ) . '</h2>
                    <p style="margin: 0 0 20px 0; font-family: Arial, sans-serif; color: #666; line-height: 1.5;">' . esc_html( $description ) . '</p>';

        if ( $button_url && $button_text ) {
            $html .= '<a href="' . esc_url( $button_url ) . '" style="display: inline-block; padding: 12px 24px; background-color: #007cba; color: #ffffff; text-decoration: none; border-radius: 4px; font-family: Arial, sans-serif;">' . esc_html( $button_text ) . '</a>';
        }

        $html .= '</td>
            </tr>
        </table>';

        return $html;
    }
}

// 初始化插件
new My_Custom_Email_Block();

JS

/**
 * 通讯区块的简单测试版本
 */
(function() {
    console.log('Newsletter block JavaScript is loading...');

    // 检查 WordPress 依赖项是否可用
    if (typeof wp === 'undefined') {
        console.error('WordPress dependencies not available');
        return;
    }

    const { __ } = wp.i18n;
    const { createElement } = wp.element;
    const { registerBlockType } = wp.blocks;
    const { useBlockProps } = wp.blockEditor;

    console.log('Registering newsletter-signup block...');

    registerBlockType('my-plugin/newsletter-signup', {
        title: __('Newsletter Signup', 'my-plugin'),
        icon: 'email-alt',
        category: 'widgets',
        description: __('A newsletter signup form for emails.', 'my-plugin'),
		supports: {
			email: true, // 电子邮件编辑器所需。
		},
        attributes: {
            title: {
                type: 'string',
                default: 'Subscribe to our newsletter'
            }
        },

        edit: function(props) {
            const blockProps = useBlockProps();

            return createElement(
                'div',
                blockProps,
                createElement(
                    'div',
                    {
                        style: {
                            padding: '20px',
                            border: '1px solid #ccc',
                            textAlign: 'center'
                        }
                    },
                    createElement('h3', null, props.attributes.title),
                    createElement('p', null, 'Newsletter signup block - working!')
                )
            );
        },

        save: function() {
            return null; // 服务器端渲染
        }
    });

    console.log('Newsletter signup block registered successfully!');
})();

最佳实践

邮件兼容的 HTML

  1. 使用基于表格的布局 - 邮件客户端对 CSS 的支持不一致
  2. 内联 CSS 样式 - 外部样式表通常会被阻止
  3. 避免复杂的 CSS - 坚持使用基本的属性,如颜色、背景颜色、填充
  4. 使用网页安全字体 - Arial, Helvetica, Times New Roman 等
  5. 跨邮件客户端测试 - 使用 Litmus 或 Email on Acid 等工具

区块设计

  1. 保持简洁 - 复杂的布局可能无法一致地渲染
  2. 使用语义化 HTML - 有助于无障碍和渲染
  3. 提供备用方案 - 为不支持的产品特点提供优雅降级
  4. 考虑移动端 - 许多邮件在移动设备上阅读

代码质量

  1. 转义输出 - 正确使用 esc_html()esc_url()wp_kses_post()
  2. 验证输入 - 检查属性并提供合理的默认值
  3. 优雅地处理错误 - 如果渲染失败,则返回原始内容
  4. 遵循 WordPress 编码标准 - 保持代码风格一致

故障排除

区块在邮件中不渲染

  1. 检查邮件支持 - 确保 supports.email 设置为 true
  2. 验证回调 - 确认 render_email_callback 已正确设置
  3. 钩子时机 - 确保筛选器在区块注册前添加
  4. 检查区块名称 - 确保区块名称完全匹配

邮件显示问题

  1. 在多个客户端中测试 - 不同的邮件客户端处理 HTML 的方式不同
  2. 验证 HTML - 使用 HTML 验证器检查错误
  3. 检查 CSS 支持 - 某些 CSS 属性在邮件中不受支持
  4. 使用表格进行布局 - 在邮件中比 CSS flexbox/网格更可靠

调试信息

启用调试日志记录以排查问题:

// 将此添加到 wp-config.php 以进行调试
define( 'WP_DEBUG', true );
define( 'WP_DEBUG_LOG', true );

// 邮件编辑将日志记录到 WordPress 调试日志

检查 WordPress 调试日志 (/wp-content/debug.log) 中与邮件编辑相关的消息。