問題描述

在外掛中註冊/排隊指令碼和/或樣式的想法是什麼?

我最近做了一個外掛 simple plugin 新增使用者頭像/ gravatar 與一個短碼。我有不同的風格選項,用於顯示頭像 (平方,圓形等),並決定將 CSS 直接放入短碼本身。

然而,我意識到現在這不是一個好的方法,因為它會重複 CSS 每次在一個頁面上使用短程式碼。我在這個網站上看到過其他幾種方法,而 wp codex 甚至有兩個自己的例子,所以很難知道什麼方法是最一致和最快速的。

以下是我目前所知道的方法:

方法 1:直接包含在短碼中 – 這正是我目前在外掛中所做的,但似乎不重要,因為它重複了程式碼。

class My_Shortcode {
function handle_shortcode( $atts, $content="" ) {
/* simply enqueue or print the scripts/styles in the shortcode itself */
?>
<style type="text/css">

</style>
<?php
    return "$content";
     }
}
add_shortcode( 'myshortcode', array( 'My_Shortcode', 'handle_shortcode' ) );

方法 2:使用類有條件地排列指令碼或樣式

class My_Shortcode {
    static $add_script;
    static function init() {
        add_shortcode('myshortcode', array(__CLASS__, 'handle_shortcode'));
        add_action('init', array(__CLASS__, 'register_script'));
        add_action('wp_footer', array(__CLASS__, 'print_script'));
    }
    static function handle_shortcode($atts) {
        self::$add_script = true;
        // shortcode handling here
    }
    static function register_script() {
        wp_register_script('my-script', plugins_url('my-script.js', __FILE__), array('jquery'), '1.0', true);
    }
    static function print_script() {
        if ( ! self::$add_script )
            return;
        wp_print_scripts('my-script');
    }
}
My_Shortcode::init();

方法 3:使用 get_shortcode_regex();

function your_prefix_detect_shortcode() {

    global $wp_query;
    $posts = $wp_query->posts;
    $pattern = get_shortcode_regex();

    foreach ($posts as $post){
        if (   preg_match_all( '/'. $pattern .'/s', $post->post_content, $matches )
            && array_key_exists( 2, $matches )
            && in_array( 'myshortcode', $matches[2] ) )
        {
            // css/js
            break;
        }
    }
}
add_action( 'wp', 'your_prefix_detect_shortcode' );

方法 4:使用 has_shortcode();

function custom_shortcode_scripts() {
    global $post;
    if( is_a( $post, 'WP_Post' ) && has_shortcode( $post->post_content, 'myshortcode') ) {
        wp_enqueue_script( 'my-script');
    }
}
add_action( 'wp_enqueue_scripts', 'custom_shortcode_scripts');

最佳解決方案

我找到了另一種對我有用的方式:

  • 初始化外掛時,不要排列指令碼和樣式,而是使用 wp_register_stylewp_register_script 註冊。

  • 接下來,您可以根據需要載入指令碼/樣式。例如,當您使用 wp_enqueue_style("your_style")wp_enqueue_script("your_script")呈現短碼時。

這是一個使用此方法的示例外掛,可以將 get_avatar 用作短碼。當短碼存在時,樣式表才會排隊。

用法 (id 預設為當前使用者):

 [get_avatar id="" size="32" default="mystery" alt="Profile Photo" class="round"]

function wpse_165754_avatar_shortcode_wp_enqueue_scripts() {
    wp_register_style( 'get-avatar-style', plugins_url( '/css/style.css', __FILE__ ), array(), '1.0.0', 'all' );
}

add_action( 'wp_enqueue_scripts', 'wpse_165754_avatar_shortcode_wp_enqueue_scripts' );
if ( function_exists( 'get_avatar' ) ) {
    function wpse_165754_user_avatar_shortcode( $attributes ) {

        global $current_user;
        get_currentuserinfo();

        extract( shortcode_atts(
                     array(
                         "id"      => $current_user->ID,
                         "size"    => 32,
                         "default" => 'mystery',
                         "alt"     => '',
                         "class"   => '',
                     ), $attributes, 'get_avatar' ) );

        $get_avatar = get_avatar( $id, $size, $default, $alt );

        wp_enqueue_style( 'get-avatar-style' );

        return '<span class="get_avatar ' . $class . '">' . $get_avatar . '</span>';
    }

    add_shortcode( 'get_avatar', wpse_165754_user_avatar_shortcode' );
}

次佳解決方案

在開始回答之前,我不得不說,關於這個話題,css 和 js 是不一樣的。

原因很簡單:將 js 新增到頁面的主體 (頁尾) 是一個常見且有效的方法,css 需要放置在頁面的<head> 部分:即使大多數瀏覽器都可以正確地呈現 CSS 頁面正文,這是無效的 HTML 程式碼。

當一個短程式碼被渲染時,<head> 部分已經被列印了,這意味著可以在頁尾上新增沒有任何問題的 js,但是在渲染短程式碼之前必須新增 CSS 。

Scripts

如果您的短程式碼只需要 js,那麼您很幸運,可以使用 wp_enqueue_script 進行短程式碼回撥:

add_shortcode( 'myshortcode', 'my_handle_shortcode' );

function my_handle_shortcode() {
  wp_enqueue_script( 'myshortcodejs', '/path/to/js/file.js' );
  // rest of code here...
}

這樣做你的指令碼被新增到頁尾,只有一次,即使短碼在頁面中多次使用。

Styles

如果您編碼需要樣式,那麼您需要在執行短程式碼實際呈現之前執行操作。

有不同的方式來做到這一點:

  1. 檢視當前查詢中的所有帖子,如果需要,新增短程式碼樣式。這是您在 OP 中的方法#3 和#4 中所做的。事實上,兩種方法都做同樣的事情,但是 WP 3.6 中新增了 has_shortcode,而 get_shortcode_regex 是從 2.5 版本開始使用的,所以只有在要使外掛與舊版本相容時才使用 get_shortcode_regex

  2. 總是新增短程式碼樣式,在所有頁面

Issues

#1 的問題是效能。正規表示式運算速度非常慢,並且在所有帖子的迴圈中啟動正規表示式可能會一直拖慢頁面。此外,在主題中只顯示檔案中的摘錄並僅以奇異檢視顯示具有短碼的完整內容是一個非常常見的任務。如果發生這種情況,當顯示存檔時,您的外掛將在迴圈中啟動正規表示式匹配,目的是新增永遠不會使用的樣式:不必要的雙重效能影響:減慢頁面生成+附加不必要的 HTTP 請求

#2 的問題是效能,再次。向所有頁面新增樣式意味著為所有頁面新增一個額外的 HTTP 請求,即使不需要。即使伺服器端頁面生成時間不受影響,總頁面呈現時間也將用於所有站點頁面。

那麼外掛開發人員應該做什麼呢?

我認為最好的做法是向外掛新增一個選項頁面,使用者可以選擇是否應該在單個檢視中處理短程式碼,甚至在檔案中進行處理。在這兩種情況下,最好提供另一個選項來選擇哪個型別啟用短碼。

以這種方式可以鉤住"template_redirect"來檢查當前查詢是否滿足要求,在這種情況下新增樣式。

如果使用者選擇使用短碼僅在單個的檢視中,是一個好主意,檢查 post 是否有短碼或不需要:只需要一個正規表示式,它不應該減慢頁面這麼多。

如果使用者選擇在檔案中使用短碼,那麼如果帖子數量很多,我會避免為所有帖子執行正規表示式,如果查詢符合要求,則只需排入該樣式。

在這方面應該考慮什麼”high” 應該使用一些效能測試,或者作為替代,新增另一個選項並給使用者選擇。

參考文獻

注:本文內容整合自 Google/Baidu/Bing 輔助翻譯的英文資料結果。如果您對結果不滿意,可以加入我們改善翻譯效果:薇曉朵技術論壇。