## 上下文控制,部分和面板
WordPress 4.0和4.1還增加了對Customizer UI部分的顯示或隱藏的支持,這取決于用戶在Customizer預覽窗口中預覽的部分網站。 一個簡單的上下文控制示例將是您的主題僅在首頁上顯示標題圖像和站點標語。 這是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();
}
```
在自定義控件,Sections和面板中,還有一個選項可以直接在自定義Customizer對象類中覆蓋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 );
```
>[warning] 請注意,對于所有Customizer對象類型(控件,節和面板),active_callback API的工作原理相同。 作為一個額外的好處,如果其中的所有控件都被上下文隱藏,則部分將自動隱藏,并且面板的功能相同。
## 選擇性刷新:快速,準確的更新
在WordPress 4.5中引入,定制程序中的選擇性刷新更新“預覽”僅刷新相關設置更改的區域。通過僅更新已更改的元素,它比完全iframe刷新更快,更少破壞性。在定制器中選擇性刷新中所述的其他一些好處是:
不要重復(DRY)邏輯
準確的預覽更新
預覽部分與相關設置和控件之間的關聯以及WordPress 4.7中的可見編輯快捷方式
純JavaScript postMessage更新中的邏輯重復。定制程序中的JavaScript必須鏡像生成標記的PHP,或者使用快捷方式近似它。但是Selective Refresh是DRY,因為沒有JavaScript和PHP的重復。 Ajax請求檢索預覽的新標記。
而且由于這個Ajax調用,刷新是準確的。它使用可以更改標記的過濾器。它顯示與前端相同的結果。
另外,選擇性刷新部分會提供預覽區域與其對應設置之間的關聯。定制工具利用這種關系提供可見的編輯快捷方式,幫助用戶找到與其網站特定部分相關聯的控件。在將來,部分API可以擴展,以便在預覽中直接編輯設置,并且包含一個結構化的JS API,用于預覽部分設置。
由于這些原因,強烈建議所有設置利用選擇性刷新傳輸以改善用戶體驗,并提供額外的基于JavaScript的傳輸以進一步增強設置預覽。
## 注冊部分
設置預覽需要通過注冊必要的部分來選擇使用選擇性刷新。 在這個例子中,很大程度上取自于他們二十六,通過添加相同名稱的部分,為博客描述設置添加了選擇性刷新。
```
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' );
```
如果沒有提供設置參數,它默認與部分ID相同,與控件的設置默認為控件ID相同。 以下是部分的一些主要參數:
|變量 |類型 |描述|
|--|--|--|
|settings |array |設置與部分相關聯的ID。|
|selector |string |指定要更新的頁面標記中的元素。|
|container_inclusive |boolean |如果為真,刷新將替換整個容器。 否則,它只會替換容器的孩子。 默認為false.|
|render_callback |function |生成要刷新的標記.|
|fallback_refresh |bool |是否在文檔中找不到部分文件時是否應進行全頁刷新.|
## 選擇性刷新JavaScript事件
這些火wp.customize.selectiveRefresh:
部分內容呈現
展示位置時。 如上所述,JavaScript驅動的小部件可以重新構建在此事件上。
渲染部分響應
數據返回后,請求部分呈現。 服務器使用'customize_render_partials_response'過濾這些數據。
部分內容移動
當窗口小部件在其側邊欄中移動時。 如上所示,JavaScript驅動的小部件可以刷新此事件。
小部件更新
當使用其renderContent方法刷新WidgetPartial時。
側邊欄更新
當邊欄具有刷新或更新的小部件時。 或者當側邊欄的小部件被排序時,使用reflowWidgets()。
## 小部件:選擇性選擇性刷新
主題和小部件都需要選擇使用選擇性刷新。 所有核心小部件和主題已經啟用。
## 側欄中的主題支持
為了允許部分刷新主題的邊欄中的小部件:
```
add_theme_support( 'customize-selective-refresh-widgets' );
```
## 小部件支持
即使主題支持選擇性刷新,小部件也必須選擇加入。 所有核心小部件已經啟用它。 這是一個添加對Selective Refresh的支持的示例窗口小部件:
```
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行確保小部件的樣式表始終顯示在Customizer會話中。 添加小部件不會導致全頁刷新來檢索樣式:
```
if ( is_active_widget( false, false, $this->id_base ) || is_customize_preview() ) {
add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_scripts' ) );
}
```
請參閱實現小部件的選擇性刷新支持。
## JavaScript驅動的小部件支持
依賴JavaScript進行標記的小部件將需要其他步驟,如實現Widget的選擇性刷新支持所示:
按照is_customize_preview()排列任何JavaScript文件,如上圖所示。
添加部分內容渲染事件的處理程序,并根據需要刷新窗口小部件:
```
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
}
```
## 使用PostMessage改進設置預覽
定制程序會自動處理即時預覽所有設置。這是通過靜默地重新加載整個預覽窗口來完成的,在Ajax調用中PHP被過濾。雖然這樣做很好,但它可能非常慢,因為整個前端必須重新加載,以進行每一個設置更改。選擇性刷新通過僅刷新已更改的元素來改善此體驗,但由于Ajax調用,在預覽中看到更改仍然有延遲。
為了進一步改善用戶體驗,Customizer提供了一個API,用于直接在JavaScript中管理設置更改,從而實現真實的預覽。下圖顯示了使用此技術(稱為postMessage)與標準刷新選項的自定義CSS選項的比較:
使用postMessage設置傳輸的Customizer中的自定義CSS設置。
Customizer中的自定義CSS設置,具有默認的刷新設置傳輸。
要使用postMessage,請在添加設置時先將傳輸參數設置為postMessage。許多主題還可以通過修改這些設置的傳輸屬性來修改核心設置,如標題和標語來利用postMessage。
```
$wp_customize->get_setting( 'blogname' )->transport = 'postMessage';
$wp_customize->get_setting( 'blogdescription' )->transport = 'postMessage';
```
一旦設置的傳輸設置為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 );
```
>[warning] 請注意,您不一定需要使用JavaScript來使用postMessage - 大多數代碼是樣板。 從PostMessage傳輸中受益最大的設置類型需要簡單的JS更改,例如使用jQuery的.html()或.text()方法,或者在`<body>`或另一個元素上交換一個類,以觸發不同的 CSS規則。 做到這一點,或者通過選擇性刷新更新完全準確的更改來簡化即時預覽邏輯,用戶體驗可以快速,而不會重復JS中的所有PHP邏輯。
## 設置驗證
WordPress 4.6包括與Customizer設置值的驗證相關的新API。定制程序自介紹以來已經對設置值進行了消毒。消毒涉及強制將某個值安全地保留到數據庫中:常見的示例是將值轉換為整數或從一些文本輸入中剝離標簽。因此,消毒是一種有損運作。隨著設置驗證的增加:
- 所有修改的設置在保存之前先驗證。
- 如果任何設置無效,則定制程序保存請求被拒絕:保存因此變為事務性,所有設置為臟,以便再次保存。 (定制器交易建議與設置驗證密切相關。)
- 驗證錯誤消息顯示給用戶,提示他們修復錯誤,然后重試。
- 消毒和驗證也分別通過WP_REST_Request :: sanitize_params()和WP_REST_Request :: validate_params()作為REST API基礎結構的一部分。設定值通過驗證后進行清潔。
有關驗證行為的更多信息和其他代碼示例,請參閱功能公告帖子。
## 驗證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_callback和任何customize_validate _ {$ setting_id}過濾器回調采用WP_Error實例是其第一個參數(最初沒有添加任何錯誤),其次是$值被清理,最后是正在驗證的WP_Customize_Setting實例。
自定義設置類也可以直接覆蓋設置類的validate方法。
## 客戶端驗證
如果您有一個純粹通過JavaScript進行預覽的設置(并且postMessage傳輸沒有選擇性刷新),那么您還應該添加客戶端驗證。否則,任何驗證錯誤將持續,直到完全刷新發生或嘗試保存。客戶端驗證不能取代服務器端驗證,因為如果相應的服務器端驗證不到位,惡意用戶可能會繞過客戶端驗證來保存無效值。
在wp.customize.Setting JS類(實際上是wp.customize.Value基類)中有一個可用的驗證方法。它的名字有點誤導,因為它實際上與WP_Customize_Setting :: sanitize()PHP方法類似,但它可以用于在JS中對某個值進行清理和驗證。請注意,此JS在“定制器”窗格的上下文中運行而不是預覽,因此任何此類JS應具有自定義控件作為依賴關系(而不是自定義預覽),并在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;
};
} );
```
## 通知
錯誤通知通知提供用戶反饋,通常基于控件設置的值。當設置的驗證例程返回WP_Error實例時,會將錯誤通知添加到設置的通知集合中。添加到PHP WP_Error實例的每個錯誤都表示為一個wp.customize.Notification在JavaScript中:
WP_Error的代碼可以作為JS中的notification.code使用。
WP_Error的消息在JS中可用作notification.message。請注意,如果在PHP中添加了給定錯誤代碼的多個消息,它們將被連接到JS中的單個消息中。
WP_Error的數據在JS中可用作notification.data。這將有助于將額外的錯誤上下文從服務器傳遞給客戶端。
任何時候從服務器上的驗證例程返回WP_Error,將導致一個wp.customize.Notification被創建,其類型屬性為“error”。
當前不支持從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 );
}
} );
} );
```
您也可以提供“信息”作為通知的類型。 默認類型為“error”。 也可以提供自定義類型,并且可以使用CSS選擇器匹配notice.notice-foo來設置通知,其中“foo”是提供的類型。 控件也可以覆蓋通過覆蓋wp.customize.Control.renderNotifications方法來呈現通知的默認行為。
- 簡介
- 主題開發
- WordPress許可證
- 什么是主題
- 開發環境
- 主題開發示例
- 主題基礎
- 模板文件
- 主樣式表(style.css)
- 文章類型
- 規劃主題文件
- 模板層級
- 模板標簽
- 循環
- 主題函數
- 連接主題文件和目錄
- 使用CSS和JavaScript
- 條件標簽
- 類別,標簽和自定義分類
- 模板文件
- 內容模板文件
- 頁面模板文件
- 附件模板文件
- 自定義內容類型
- 部分和其他模板文件
- 評論模板
- 分類模板
- 404頁面
- 主題功能
- 核心支持的功能
- 管理菜單
- 自定義Headers
- 自定義Logo
- 文章格式
- 置頂文章
- Sidebars
- Widgets
- 導航菜單
- 分頁
- 媒體
- Audio
- Images
- Galleries
- Video
- 精選圖片和縮略圖
- 國際化
- 本地化
- 輔助功能
- 主題選項 – 自定義API
- 定制對象
- 改進用戶體驗的工具
- 定制JavaScript API
- JavaScript / Underscore.js渲染的自定義控件
- 高級用法
- 主題安全
- 數據消毒/逃避
- 數據驗證
- 使用隨機數
- 常見漏洞
- 高級主題
- 子主題
- UI最佳實踐
- JavaScript最佳做法
- 主題單元測試
- 驗證你的主題
- Plugin API Hooks
- 發布你的主題
- 所需的主題文件
- 測試
- 主題評論指南
- 寫文檔
- 提交你的主題到WordPress.org
- 參考文獻
- 模板標簽列表
- 條件標簽列表
- 編碼標準
- HTML編碼標準
- CSS編碼標準
- JavaScript編碼標準
- PHP編碼標準
- 插件開發
- 插件開發簡介
- 什么是插件
- 插件基礎
- 頭部要求
- 包括軟件許可證
- 啟用 / 停用 Hooks
- 卸載方法
- 最佳做法
- 插件安全
- 檢查用戶功能
- 數據驗證
- 保護輸入
- 保護輸出
- 隨機數
- Hooks
- Actions
- Filters
- 自定義Hooks
- 高級主題
- 管理菜單
- 頂級菜單
- 子菜單
- 短代碼
- 基本短碼
- 封閉短碼
- 帶參數的短代碼
- TinyMCE增強型短碼
- 設置
- 設置API
- 使用設置API
- 選項API
- 自定義設置頁面
- 元數據
- 管理帖子元數據
- 自定義元數據
- 渲染元數據
- 自定義文章類型
- 注冊自定義文章類型
- 使用自定義文章類型
- 分類
- 使用自定義分類
- 在WP 4.2+中使用“split術語”
- 用戶
- 創建和管理用戶
- 使用用戶元數據
- 角色和功能
- HTTP API
- JavaScript
- jQuery
- Ajax
- 服務器端PHP和入隊
- Heartbeat API
- 概要
- 計劃任務
- 了解WP-Cron計劃
- 安排WP-Cron 事件
- 將WP-Cron掛接到系統任務計劃程序中
- WP-Cron簡單測試
- 國際化
- 本地化
- 如何國際化您的插件
- 國際化安全
- WordPress.org
- 詳細插件指南
- 規劃您的插件
- 如何使用Subversion
- 插件開發者常見問題
- 開發工具
- Debug Bar 和附加組件
- 輔助插件
- REST API手冊
- 資源
- 文章
- 文章修訂
- 文章類型
- 文章狀態
- 類別
- 標簽
- 頁面
- 評論
- 分類
- 媒體
- 用戶
- 設置
- 使用REST API
- 全局參數
- 分頁
- 鏈接和嵌入
- 發現
- 認證
- 經常問的問題
- 骨干JavaScript客戶端
- 客戶端庫
- 擴展REST API
- 添加自定義端點
- 自定義內容類型
- 修改回應
- 模式
- 詞匯表
- 路由和端點
- 控制器類