WordPress自定义器JavaScript API:让主题定制更灵活

WordPress的自定义器(Customizer)不仅仅是拖拖拽拽改改颜色那么简单。从WordPress 4.1开始,核心团队为自定义器引入了一套完整的JavaScript API,这意味着开发者可以通过JS代码深度控制自定义器的行为——动态显示或隐藏控件、调整预览URL、自动聚焦到特定设置项,甚至创建全新的交互方式。本文将带你理清这套API的核心概念:面板(Panel)、区块(Section)、控件(Control)三者的层级关系,以及如何通过activate()、focus()、priority()等方法让自定义器变得更智能、更懂用户。无论你是想优化主题的用户体验,还是准备开发高级功能,理解这套API都是绕不开的一步。


两套JS,分工明确

在开始写代码之前,需要先搞清楚自定义器的运行机制。整个自定义器界面实际上分成了两个独立的区域:

  • 控制面板:就是你在左侧看到的那些设置项和控件。
  • 预览窗口:右侧用iframe嵌入的网站预览。

这两个环境互不干扰,各自运行着自己的JavaScript代码。它们之间通过postMessage API进行通信。

正因为如此,官方推荐将JS代码分成两个文件来管理:

text

- customize-controls.js   // 控制面板端逻辑
- customize-preview.js    // 预览窗口端逻辑

哪怕你只写了其中一端,也建议保持这个命名规范,方便自己和他人维护。

核心三要素:面板、区块、控件

在自定义器里,所有东西都围绕这三个概念展开:

  • 面板(Panel):顶层,相当于一个大分类。例如“小工具”就是一个面板。
  • 区块(Section):面板下面的一级分组。比如“站点身份”区块下包含了网站标题、标语等设置。
  • 控件(Control):具体的设置项,也就是用户实际操作的输入框、颜色选择器、下拉菜单等。

在JavaScript里,这三个对象都有对应的模型和集合:

javascript

// 遍历所有面板
wp.customize.panel.each(function(panel) {
    console.log(panel.id);
});

// 遍历所有区块
wp.customize.section.each(function(section) {
    console.log(section.id);
});

// 遍历所有控件
wp.customize.control.each(function(control) {
    console.log(control.id);
});

注意,这里的集合名称都是单数形式:wp.customize.panel、wp.customize.section、wp.customize.control。

理清层级关系

在PHP中注册控件时,需要指定它属于哪个区块:

php

$wp_customize->add_control('blogname', array(
    'label'   => __('网站标题'),
    'section' => 'title_tagline',
));

到了JavaScript这边,你可以随时获取或改变这种归属关系:

javascript

// 获取控件所属的区块ID
var sectionId = wp.customize.control('blogname').section();

// 将控件移动到另一个区块
wp.customize.control('blogname').section('nav');

// 获取区块所属的面板ID
var panelId = wp.customize.section('title_tagline').panel();

// 获取一个面板下的所有区块
var sections = wp.customize.panel('widgets').sections();

// 获取一个区块下的所有控件
var controls = wp.customize.section('title_tagline').controls();

有了这些方法,你可以实现很多动态效果。比如把某个区块下的所有控件一键迁移到另一个区块:

javascript

_.each(wp.customize.section('title_tagline').controls(), function(control) {
    control.section('nav');
});

动态显隐控件

每个面板、区块、控件都有一个active状态,通过activate()和deactivate()方法可以控制它们的显示与隐藏:

javascript

// 隐藏导航区块(向上收起)
wp.customize.section('nav').deactivate();

// 慢速展开颜色区块,持续1秒
wp.customize.section('colors').activate({ duration: 1000 });

// 立即隐藏,不要动画
wp.customize.section('colors').deactivate({ duration: 0 });

// 等导航完全隐藏后再显示颜色区块
wp.customize.section('nav').deactivate({
    completeCallback: function() {
        wp.customize.section('colors').activate();
    }
});

注意,这种显隐状态在预览刷新后会重置,适合做临时性的交互反馈,而不是性的配置变更。

自动聚焦:直达目标

focus()方法是提升用户体验的利器。它会自动展开目标所在的层级、滚动到可视区域,并把光标定位到一个可输入的控件上。

javascript

// 直接聚焦到“首页”控件
wp.customize.control('page_on_front').focus();

这个功能正是用来实现URL深度链接的:

text

/wp-admin/customize.php?autofocus[panel]=widgets
/wp-admin/customize.php?autofocus[section]=colors
/wp-admin/customize.php?autofocus[control]=blogname

在后台的“小工具”管理页面点击“在自定义器中编辑”,就会自动跳转到自定义器并聚焦到小工具面板,用的就是这套机制。

调整优先级:控制显示顺序

注册时设置的priority参数在JS中也可以随时读取和修改:

javascript

// 读取小工具面板的优先级(默认是110)
var p = wp.customize.panel('widgets').priority();

// 把小工具面板置顶
wp.customize.panel('widgets').priority(1);

修改后,自定义器UI会自动重新排序,无需刷新页面。

预览交互示例

下面这段代码来自WordPress核心,演示了当用户修改“文章页面”设置时,预览窗口自动跳转到对应的页面:

javascript

wp.customize('page_for_posts', function(setting) {
    setting.bind(function(pageId) {
        pageId = parseInt(pageId, 10);
        if (pageId > 0) {
            api.previewer.previewUrl.set(
                api.settings.url.home + '?page_id=' + pageId
            );
        }
    });
});

这种模式下,用户改了设置立刻就能看到效果,体验非常流畅。

开发自定义控件

官方文档的建议很实在:想写自定义控件,直接看核心源码wp-admin/js/customize-controls.js里的例子,特别是媒体控件那部分,通过继承和扩展可以快速上手。

总结

WordPress自定义器的JavaScript API提供了一套完整的方法来操作面板、区块和控件。掌握这三个核心对象以及它们之间的层级关系,就能实现很多高级的交互效果:动态显隐、自动聚焦、实时预览、动态排序等等。对于主题开发者来说,熟练运用这套API是提升用户体验的关键一步。