上下文控件,部分和面板
WordPress 4.0和4.1还添加了为使自定义UI的一部分提供的支持,这取决于用户在自定义器预览窗口中预览的网站部分。一个简单的上下文控制示例将是您的主题仅在首页上显示标题图像和站点标语。对于Customizer Manager的GET_方法来说,这是一个完美的用例,因为我们可以直接修改这些设置的核心控件,以使它们与首页上下文相关:
// Hide core sections/controls when they aren't used on the current page.
$wp_customize->get_section( 'header_image' )->active_callback = 'is_front_page';
$wp_customize->get_control( 'blogdescription' )->active_callback = 'is_front_page';
这active_callback
面板,部分和控件的参数为核心或自定义的回调函数名称。在注册您添加的对象的对象时,也可以设置此参数。这是二十四个主题的一个例子:
$wp_customize->add_section( 'featured_content', array(
'title' => __( 'Featured Content', 'twentyfourteen' ),
'description' => //...
'priority' => 130,
'active_callback' => 'is_front_page',
) );
在上一个示例中is_front_page
直接使用。但是对于更复杂的逻辑,例如检查当前视图是否是页面(甚至是特定页面,ID),可以使用自定义功能(请参阅 #30251 有关为什么需要的详细信息)。如果您不需要支持PHP 5.2,则可以内联完成:
'active_callback' => function () { return is_page(); }
PHP 5.2支持与创建命名函数并使用Active_callback参数引用它一样简单:
//...
'active_callback' => 'prefix_return_is_page';
//...
function prefix_return_is_page() {
return is_page();
}
在自定义控件,部分和面板中,还有一个选项可以覆盖active_callback
在“自定义自定义对象类”中直接函数:
class WP_Customize_Greeting_Control extends WP_Customize_Control {
// ...
function active_callback() {
return is_front_page();
}
}
最后,有一个过滤器可以用来覆盖所有其他active_callback
行为:
// Hide all controls without a description when previewing single posts.
function title_tagline_control_filter( $active, $control ) {
if ( '' === $control->description ) {
$active = is_singular();
}
return $active;
}
add_filter( 'customize_control_active', 'title_tagline_control_filter', 10, 2 );
请注意active_callback
API在所有定制对象类型(控件,部分,和 面板)。作为额外的奖励,如果其中的所有控件在上下文上隐藏,并且面板的作品相同,则会自动隐藏部分。
选择性刷新:快速,准确的更新
在WordPress 4.5中介绍的定制器“预览”中的选择性刷新更新仅更改其关联设置的刷新区域。通过仅更新已更改的元素,它比完整iframe刷新更快且破坏性更大。其他一些好处,如 定制器中的选择性刷新,是:
- 不要重复自己(干燥)逻辑
- 准确的预览更新
- 预览部分与关联的设置和控件之间的关联以及可见的编辑快捷方式 从WordPress 4.7开始
纯javascript中的逻辑postMessage
更新是重复的。定制器中的JavaScript必须镜像产生标记的PHP,或采用快捷方式近似。但是选择性刷新是干燥由于没有JavaScript和PHP的重复。AJAX请求检索预览的新标记。
而且由于这个Ajax的电话,刷新是 准确的。它使用可以更改标记的过滤器。它显示出与前端出现的相同结果。
此外,选择性刷新部分提供了预览区域及其相应设置之间的关联。定制器利用这种关系提供可见的编辑快捷方式,可帮助用户找到与其网站特定部分相关的控件。将来,Partials API可能会扩展,以促进预览中的编辑设置,并包括一个结构化的JS API,用于预览具有部分的设置。
由于这些原因,强烈建议使用所有设置来利用选择性刷新运输以改善用户体验,并选择提供基于JavaScript的额外运输以进一步增强设置预览。
注册部分
设置预览需要选择加入,以通过注册必要的部分来使用选择性刷新。在此示例中,很大程度上取自他们 二十六,为此添加选择性刷新blogdescription
通过添加具有相同名称的部分来设置。
function foo_theme_customize_register( WP_Customize_Manager $wp_customize ) {
$wp_customize->selective_refresh->add_partial( 'blogdescription', array(
'selector' => '.site-description',
'container_inclusive' => false,
'render_callback' => function() {
bloginfo( 'description' );
},
) );
}
add_action( 'customize_register', 'foo_theme_customize_register' );
如果是settings
不提供参数,它默认为与部分ID相同,就像控制ID的控制默认设置一样。以下是部分的一些关键论点:
多变的 | 类型 | 描述 |
settings | 大批 | 设置与部分关联的ID。 |
selector | 细绳 | 针对要刷新页面标记中的元素。 |
container_inclusive | 布尔 | 如果为true,则刷新替换整个容器。否则,它只取代容器的孩子。默认为false。 |
render_callback | 功能 | 产生要在刷新时渲染的标记。 |
fallback_refresh | 布尔 | 如果文档中找不到部分,则应发生全页刷新。 |
选择性刷新JavaScript事件
这些开火wp.customize.selectiveRefresh
:
partial-content-rendered
放置时。如前所述,JavaScript驱动的小部件可以在此事件上重新构建。render-partials-response
返回数据后,请求部分渲染。服务器使用“ customize_render_partials_response”过滤此数据。partial-content-moved
当小部件在侧边栏中移动时。如上所示,JavaScript驱动的小部件可以在此事件中刷新。widget-updated
当。。。的时候WidgetPartial
用它的renderContent
方法。sidebar-updated
当侧边栏具有刷新或更新的小部件时。或当侧边栏的小部件被分类时reflowWidgets()
。
小部件:选择选择性刷新
主题和小部件 需要选择加入 使用选择性刷新。所有核心小部件和主题都已经启用了这一点。
侧栏的主题支持
为了使主题栏中的小部件部分刷新:
add_theme_support( 'customize-selective-refresh-widgets' );
重要的: 针对小部件的选择性刷新要求主题包括before_widget
/after_widget
每个小部件周围包含的包装元素都包含小部件的ID。这样的包装器是默认的register_sidebar()
。例如:
function example_widgets_init() {
register_sidebar(
array(
'name' => esc_html__( 'Sidebar', 'example' ),
'id' => 'sidebar-1',
'description' => esc_html__( 'Add widgets here.', 'example' ),
'before_widget' => '<section id="%1$s" class="widget %2$s">', // <= Key for selective refresh.
'after_widget' => '</section>',
'before_title' => '<h2 class="widget-title">',
'after_title' => '</h2>',
)
);
}
add_action( 'widgets_init', 'example_widgets_init' );
小部件支持
即使主题支持选择性刷新,小部件也必须选择加入。所有核心小部件都已经启用了它。这是一个示例窗口小部件,增加了对选择性刷新的支持:
class Foo_Widget extends WP_Widget {
public function __construct() {
parent::__construct(
‘foo’,
__( 'Example', 'bar-plugin' ),
array(
'description' => __( ‘An example widget’, ‘bar-plugin’ ),
'customize_selective_refresh' => true,
)
);
if ( is_active_widget( false, false, $this->id_base ) || is_customize_preview() ) {
add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_scripts' ) );
}
}
...
上面的第9行启用了选择性刷新:
'customize_selective_refresh' => true,
上面的第13行确保了小部件的样式表始终出现在“定制”会议中。添加小部件不会引起全页刷新来检索样式:
if ( is_active_widget( false, false, $this->id_base ) || is_customize_preview() ) {
add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_scripts' ) );
}
JavaScript驱动的小部件支持
依靠JavaScript进行标记的小部件将需要其他步骤,如图所示 实施对小部件的选择性刷新支持:
- 基于
is_customize_preview()
,如上图所示。 - 为
partial-content-rendered
事件,并根据需要刷新小部件:
wp.customize.selectiveRefresh.bind( 'partial-content-rendered', function( placement ) {
// logic to refresh
} );
- 如果小部件包含一个iframe,请添加处理程序以刷新部分:
wp.customize.selectiveRefresh.bind( 'partial-content-moved', function( placement ) {
// logic to refresh, perhaps conditionally
}
使用后邮政进行改进的设置预览
定制器会自动处理预览所有设置。这是通过默默重新加载整个预览窗口来完成的,在Ajax调用中,通过PHP过滤设置。虽然这可以正常工作,但它可能会非常慢,因为必须在每个设置更改中重新加载整个前端。选择性刷新仅通过仅刷新已更改的元素来改善这种体验,但是由于Ajax调用,查看预览的变化仍然存在延迟。
为了进一步改善用户体验,自定义器提供了用于直接在JavaScript中设置更改的API,从而允许真正的预览。下图显示了利用这项技术的自定义CSS选项的比较,称为postMessage
,与标准刷新选项相比:
要使用后邮件,请在添加设置时首先将传输参数设置为后腔。许多主题还修改了核心设置,例如标题和标语,以通过修改这些设置的运输属性来利用后期:
$wp_customize->get_setting( 'blogname' )->transport = 'postMessage';
$wp_customize->get_setting( 'blogdescription' )->transport = 'postMessage';
一旦设置的传输设置为后邮政,设置将不再触发预览的值时,当其值更改时。要实现JavaScript以更新前端预览中的设置,请首先创建并加入JavaScript文件:
function my_preview_js() {
wp_enqueue_script( 'custom_css_preview', 'path/to/file.js', array( 'customize-preview', 'jquery' ) );
}
add_action( 'customize_preview_init', 'my_preview_js' );
您的JavaScript文件应该看起来像这样:
( function( $ ) {
wp.customize( 'setting_id', function( value ) {
value.bind( function( to ) {
$( '#custom-theme-css' ).html( to );
} );
} );
wp.customize( 'custom_plugin_css', function( value ) {
value.bind( function( to ) {
$( '#custom-plugin-css' ).html( to );
} );
} );
} )( jQuery );
请注意,您不一定需要使用JavaScript来使用Postmessage – 大多数代码都是样板。从后传输中受益最大的设置的类型需要简单的JS更改,例如使用jQuery的.html()或.text()方法,或在该方法上换成类<body>
或另一个元素触发另一组CSS规则。这样做,或者通过选择性刷新更新,简化了即时预览逻辑,用户体验可以很快,而无需重复JS中的所有PHP逻辑。
设置验证
WordPress 4.6包括与验证自定义器设置值有关的新API。自定制值自引入以来,定制器已经进行了消毒。消毒涉及将值胁迫到安全到数据库的安全性:常见示例将值转换为整数或从某些文本输入中剥离标签。因此,消毒是一个有损手术。随着设置验证的添加:
- 在保存任何一个修改的设置之前,所有修改后的设置均已预先验证。
- 如果任何设置无效,则拒绝自定义保存请求:保存因此变为交易所有设置都保持肮脏,然后尝试再次保存。(定制器 交易建议 与在此处设置验证密切相关。)
- 验证错误消息显示给用户,提示他们解决错误并重试。
消毒和验证也是REST API基础架构的一部分WP_REST_Request::sanitize_params()
和WP_REST_Request::validate_params()
,分别。设置的价值在经过消毒之前经过验证。
有关验证行为和其他代码示例的更多信息,请参见 功能公告职位。
验证PHP中的设置
就像您可以提供sanitize_callback
注册设置时,您还可以提供validate_callback
Arg:
$wp_customize->add_setting( 'established_year', array(
'sanitize_callback' => 'absint',
'validate_callback' => 'validate_established_year'
) );
function validate_established_year( $validity, $value ) {
$value = intval( $value );
if ( empty( $value ) || ! is_numeric( $value ) ) {
$validity->add( 'required', __( 'You must supply a valid year.' ) );
} elseif ( $value < 1900 ) {
$validity->add( 'year_too_small', __( 'Year is too old.' ) );
} elseif ( $value > gmdate( 'Y' ) ) {
$validity->add( 'year_too_big', __( 'Year is too new.' ) );
}
return $validity;
}
就像提供一个sanitize_callback
ARG添加了一个过滤器customize_sanitize_{$setting_id}
,也是如此提供validate_callback
ARG会为customize_validate_{$setting_id}
。假设WP_Customize_Setting
实例将过滤器应用于它们validate
方法,如果需要为以前添加的设置添加验证,则可以添加此过滤器。
这validate_callback
和任何customize_validate_{$setting_id}
过滤回调为WP_Error
实例是其第一个参数(最初是添加的任何错误),然后是$value
被消毒,最后是WP_Customize_Setting
正在验证的实例。
自定义设置类也可以覆盖validate
设置类的方法直接。
客户端验证
如果您的设置纯粹是通过JavaScript预览的(以及postMessage
运输没有选择性刷新),您还应添加客户端验证。否则,任何验证错误都将持续存在,直到发生完整的刷新或尝试保存。客户端验证不得代替服务器端验证,因为恶意用户可以绕过客户端验证,以保存无效的值,如果没有相应的服务器端验证。
有一个validate
可用的方法wp.customize.Setting
JS课(实际上,wp.customize.Value
基类)。它的名称有些误导,因为它的行为实际上与WP_Customize_Setting::sanitize()
PHP方法,但可以用来既清理和验证JS中的值。请注意,此JS在定制器的上下文中运行窗格不是预览,所以任何这样的JS都应该拥有customize-controls
作为依赖性(不是customize-preview
),并在customize_controls_enqueue_scripts
行动。一些示例JS验证:
wp.customize( 'established_year', function ( setting ) {
setting.validate = function ( value ) {
var code, notification;
var year = parseInt( value, 10 );
code = 'required';
if ( isNaN( year ) ) {
notification = new wp.customize.Notification( code, {message: myPlugin.l10n.yearRequired} );
setting.notifications.add( code, notification );
} else {
setting.notifications.remove( code );
}
code = 'year_too_small';
if ( year < 1900 ) {
notification = new wp.customize.Notification( code, {message: myPlugin.l10n.yearTooSmall} );
setting.notifications.add( code, notification );
} else {
setting.notifications.remove( code );
}
code = 'year_too_big';
if ( year > new Date().getFullYear() ) {
notification = new wp.customize.Notification( code, {message: myPlugin.l10n.yearTooBig} );
setting.notifications.add( code, notification );
} else {
setting.notifications.remove( code );
}
return value;
};
} );
通知
通知提供用户反馈,通常基于控件设置的值。错误通知已添加到设置notifications
设置验证例程返回时收集WP_Error
实例。每个错误添加到PHP中WP_Error
实例表示为wp.customize.Notification
在JavaScript中:
- A
WP_Error
’code
可用notification.code
在JS。 - A
WP_Error
’message
可用notification.message
在JS。请注意,如果在PHP中的给定错误代码中添加了多个消息,它们将在JS中加入单个消息。 - A
WP_Error
’data
可用notification.data
在JS。这对于将其他错误上下文从服务器传递到客户端很有用。
任何时候WP_Error
从服务器上的验证例程返回wp.customize.Notification
被用type
“错误”的属性。
虽然目前不支持从PHP设置非错误通知(请参阅#37281),但您还可以添加使用JS的非错误通知如下:
wp.customize( 'blogname', function( setting ) {
setting.bind( function( value ) {
var code = 'long_title';
if ( value.length > 20 ) {
setting.notifications.add( code, new wp.customize.Notification(
code,
{
type: 'warning',
message: 'This theme prefers title with max 20 chars.'
}
) );
} else {
setting.notifications.remove( code );
}
} );
} );
您还可以作为通知的“信息”提供type
。默认值type
是“错误”。也可以提供自定义类型,并且可以使用CSS选择器匹配来对通知进行样式notice.notice-foo
所提供的类型是“ foo”。控制还可以覆盖通过覆盖通知的默认行为wp.customize.Control.renderNotifications
方法。