WordPress 4.1 还增加了对完全使用 JavaScript 渲染 JavaScript 密集型和高数量控件的支持。这允许更动态的行为,特别是与动态添加的控件相关。核心颜色和媒体控件目前利用此 API,并且所有核心控件最终将在未来使用它。基于 PHP 的控件 API 不会消失,但在未来大多数控件可能会使用新的 API,因为它为用户和开发人员提供了更快的体验。类似的用于 JS 模板化部分和面板的 API 在 WordPress 4.3 中引入;然而,截至 WordPress 4.7,JS 中动态创建对象的便利性仍存在一些差距,请参阅 #30741。
已注册的控件类型
为了引入一个概念,即拥有一个模板用于多个相同类型的自定义器控件,我们需要引入一种向自定义管理器注册控件类型的方法。以前,只有在添加自定义控件时才会遇到自定义控件对象,使用的是 WP_Customize_Manager::add_control()。但是,检测已添加的控件类型以为每种类型渲染一个模板将不允许在没有加载该类型的其他实例的情况下动态创建新控件。WP_Customize_Manager::register_control_type() 解决了这个问题:
add_action( 'customize_register', 'prefix_customize_register' );
function prefix_customize_register( $wp_customize ) {
// Define a custom control class, WP_Customize_Custom_Control.
// Register the class so that its JS template is available in the Customizer.
$wp_customize->register_control_type( 'WP_Customize_Custom_Control' );
}所有已注册的控件类型都由 WP_Customize_Manager::print_control_templates() 将其模板打印到自定义器中。
将 PHP 控件数据发送到 JavaScript
虽然自定义器控件数据一直传递给控件 JS 模型,并且这一直可以扩展,但在使用 JS 模板时,您更可能需要向下发送数据。任何您希望在 PHP 的 render_content() 中访问的内容都需要导出到 JavaScript 才能在您的控件模板中访问。WP_Customize_Control 默认导出以下控件类变量:
typelabeldescriptionactive(布尔状态)
您可以通过在自定义控件子类中覆盖 WP_Customize_Control::to_json() 来添加特定于您的自定义控件的额外参数。在大多数情况下,您也想调用父类的 to_json() 方法,以确保导出所有核心变量。以下是来自核心颜色控件的示例:
public function to_json() {
parent::to_json();
$this->json['statuses'] = $this->statuses;
$this->json['defaultValue'] = $this->setting->default;
}JS/Underscore 模板
一旦您已将自定义控件类注册为控件类型并导出任何自定义类变量,您就可以创建将渲染控件 UI 的模板。您将覆盖 WP_Customize_Control::content_template()(默认为空)以替换 WP_Customize_Control::render_content()。仍然调用渲染内容,因此请确保在您的子类中也用空函数覆盖它。
Underscore 风格的自定义控件模板与 PHP 非常相似。随着 WordPress 核心越来越多的部分由 JavaScript 驱动,这些模板变得越来越常见。核心中的一些示例模板代码可以在 媒体、修订版、主题浏览器 甚至 Twenty Fifteen 主题中 找到,其中使用 JS 模板来保存颜色方案数据并即时预览自定义器中的颜色方案更改。学习这些模板工作原理的最佳方法是研究核心中的类似代码,相应地,这里有一个简要示例:
class WP_Customize_Color_Control extends WP_Customize_Control {
public $type = 'color';
// ...
/**
* Render a JS template for the content of the color picker control.
*/
public function content_template() {
?>
<# var defaultValue = '';
if ( data.defaultValue ) {
if ( '#' !== data.defaultValue.substring( 0, 1 ) ) {
defaultValue = '#' + data.defaultValue;
} else {
defaultValue = data.defaultValue;
}
defaultValue = ' data-default-color=' + defaultValue; // Quotes added automatically.
} #>
<label>
<# if ( data.label ) { #>
<span class="customize-control-title">{{{ data.label }}}</span>
<# } #>
<# if ( data.description ) { #>
<span class="description customize-control-description">{{{ data.description }}}</span>
<# } #>
<div class="customize-control-content">
<input class="color-picker-hex" type="text" maxlength="7" placeholder="<?php esc_attr_e( 'Hex Value' ); ?>" {{ defaultValue }} />
</div>
</label>
<?php
}
}在上述核心自定义颜色控件的模板中,您可以看到在关闭 PHP 标签之后,我们有一个 JS 模板。使用 <# ... #> 表示法围绕要评估的语句——在大多数情况下,这用于条件判断。所有我们导出到 JS 的控件实例数据都存储在 `data` 对象中,我们可以使用双(转义)或三(未转义)括号表示法 {{ }} 打印变量。正如我之前所说,掌握编写此类控件的最佳方法是阅读现有示例。WP_Customize_Upload_Control 最近也更新以利用此 API,与媒体管理器的实现方式很好地集成,并从少量的代码中挤出大量的功能。如果您想获得一些很好的练习,请尝试将其他核心控件转换为使用此 API——当然还要向核心提交补丁!
将各部分组合在一起
以下是利用新 API 所需的自定义器控件子类的总结:
- 使您的 render_content() 函数为空(但它需要存在以覆盖默认函数)。
- 创建一个新函数 content_template(),并将 render_content() 的旧内容放在那里。
- 通过修改 to_json() 函数添加任何自定义类变量,这些变量需要在 JavaScript 中导出到浏览器(JSON 数据)(参见 WP_Customize_Color_Control 以获取示例)。
- 将 render_content() 中的 PHP 转换为 JS 模板,使用
<# ... #>围绕 JS 语句进行评估,并使用 {{ }} 围绕变量进行打印。PHP 类变量在 data 对象中可用;例如,可以使用 {{ data.label }} 打印标签。 - 注册自定义控件类/类型。这个关键步骤告诉自定义器打印此控件的模板。这与仅仅打印所有已添加控件的模板不同,因为想法是许多该控件类型的实例可以从一个模板渲染,并且任何已注册的控件类型都可用于未来的动态控件创建。只需做类似 $wp_customize->register_control_type( 'WP_Customize_Color_Control' ) 的事情。
自定义 API 的仅 PHP 部分仍然完全支持且使用效果良好。但鉴于使自定义器更加灵活以执行诸如在自定义器中切换主题而不需要页面加载等操作的长期目标,强烈建议在使用 JS/Underscore 模板作为所有自定义器对象(如果可行)。