在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.section
和wp.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模型。注意核心代码中的几个例子,特别是在媒体控件中,它们通过对象的层次结构建立在彼此的功能上。