定制器JavaScript API

在WordPress 4.1,新扩展的JavaScript API被引入到所有的定制器对象中。整个JavaScript API目前位于一个文件中,即wp-admin/js/customize-controls.js,它包含所有对象的模型、核心自定义控件等。

预览JS和控件JS

定制器应用程序目前被分成两个不同的区域:控件窗格和预览。预览目前是在一个iframe中,这意味着所有的JS都是在控件窗格或预览中运行。postMessage API被用来在预览和控件之间进行通信。

大多数主题只在预览中实现JavaScript,并使用它来实现通过postMessage的即时预览设置。然而,控件栏的JS可以用来做很多事情,比如根据其他设置的值动态地显示和隐藏控件,改变预览的URL,聚焦预览的部分,等等。下面是一个与预览互动的控件栏JS例子,在这个例子中,当文章的页面发生变化时,会改变预览的URL。

// Change the previewed URL to the selected page when changing the page_for_posts.

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

类似的逻辑可以用来根据设置的值来激活UI对象。Twenty Seventeen主题包括一些有用的例子,利用自定义JS API来改善用户体验。请注意,控件窗格有一个JS文件,名为customize-controls.js,预览有一个文件,名为customize-preview.js。为了清晰起见,建议所有的主题和插件都遵循这个命名惯例,即使自定义JS只在控件或预览中提供,而不是同时提供。

本页的其余部分主要是关于在WordPress 4.1中构建出来的控件端JS API。

 

控件、板块和面板的模型

就像在PHP中一样,每个定制器对象类型在JavaScript中都有一个对应的对象。有wp.customize.Control,wp.customize.Panel,wp.customize.Section 模型,以及wp.customize.panel,wp.customize.sectionwp.customize.control集合(是的,它们是单数)来存储所有控件实例。你可以通过以下方式对面板、板块和控件进行迭代。

wp.customize.panel.each( function ( panel ) { /* ... */ } );
wp.customize.section.each( function ( section ) { /* ... */ } );
wp.customize.control.each( function ( control ) { /* ... */ } );

 

将控件、板块和面板关联在一起

在PHP中注册一个新的控件时,你要传入父板块的ID:

$wp_customize->add_control( 'blogname', array(  
    'label' => __( 'Site Title' ),  
    'section' => 'title_tagline',) 
);

在JavaScript API中,一个控件的板块可以被预测地获得:

id = wp.customize.control( 'blogname' ).section(); // returns title_tagline by default

要从ID中获得板块对象,请按正常的ID查找板块:wp.customize.section( id )

你也可以使用这个板块的状态将一个控件移到另一个板块,这里是将它移到导航板块:

wp.customize.control( 'blogname' ).section( 'nav' );

你也可以用同样的方法获得一个板块的面板ID:

id = wp.customize.section( 'sidebar-widgets-sidebar-1' ).panel(); // returns widgets by default

你也可以反其道而行,以获得面板和板块的子对象:

sections = wp.customize.panel( 'widgets' ).sections();
controls = wp.customize.section( 'title_tagline' ).controls();

你可以用这些来把所有的控件从一个板块移到另一个板块:

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

 

上下文面板、板块和控件

控件、面板和板块实例有一个激活状态(一个wp.customize.Value实例)。当激活状态改变时,面板、板块和控件实例会调用它们各自的onChangeActive方法,默认情况下,如果是false和true,会将容器元素向上和向下滑动。现在还有activate()和deactivate()方法,用于操纵面板、板块和控件的这种激活状态。这些状态的主要目的是显示或隐藏对象,而不把它完全从定制器中移除。

wp.customize.section( 'nav' ).deactivate(); // slide up
wp.customize.section( 'nav' ).activate({ duration: 1000 }); // slide down slowly
wp.customize.section( 'colors' ).deactivate({ duration: 0 }); // hide immediately
wp.customize.section( 'nav' ).deactivate({ completeCallback:
function () {  
    wp.customize.section( 'colors' ).activate(); // show after nav hides completely
    } 
});

手动改变激活状态只会坚持到预览刷新或加载另一个URL。activate()/deactivate()方法被设计为遵循新扩展状态的模式。

 

聚焦UI对象

在面板、板块和控件的expand()/collapse()方法的基础上,这些模型还支持一个focus()方法,它不仅可以展开所有必要的元素,还可以将目标容器滚动到视图中,并将浏览器的焦点放在容器中第一个可关注的元素上。例如,要展开"静态首页"板块,并将焦点放在"首页"的选择下拉菜单上:

wp.customize.control( 'page_on_front' ).focus()

焦点功能是用来实现自动聚焦的:深度链接到定制器内部的面板、板块和控件。考虑一下这些URL:

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

这在WordPress核心中被用来在小工具管理页面上添加一个链接,以直接链接到定制器中的小工具面板,以及将预览中的可见编辑快捷方式与定制窗格中的相关控件相连接。

 

优先级

当在PHP中注册一个面板、板块或控件时,你可以提供一个优先级(priority)参数。这个值被存储在wp.customize.Value实例中,用于每个相应的面板、板块和控件实例。例如,你可以通过以下方式获得小工具面板的优先级。

priority = wp.customize.panel( 'widgets' ).priority(); // returns 110 by default

然后你可以动态地改变优先级,定制器UI将自动重新排列以反映新的优先级。

wp.customize.panel( 'widgets' ).priority( 1 ); // move Widgets to the top

 

自定义控件、面板和板块

当在JS中使用自定义的定制器对象时,通常最简单的是检查WordPress核心中的自定义对象来理解代码结构。参见wp-admin/js/customize-controls.js,特别是wp.customize.Panel|Section|Control模型。注意核心代码中的几个例子,特别是在媒体控件中,它们通过对象的层次结构建立在彼此的功能上。