Enqueue ScScript / Styles khi shortcode hiện diện


54

Cách ý tưởng để đăng ký / enqueue script và / hoặc style để sử dụng trong plugin là gì?

Gần đây tôi đã tạo một plugin đơn giản để thêm avatar / gravatar của người dùng bằng một shortcode. Tôi có các tùy chọn kiểu khác nhau để hiển thị hình đại diện (hình vuông, hình tròn, v.v.) và quyết định đặt css trực tiếp vào chính shortcode.

Tuy nhiên, tôi nhận ra rằng đây không phải là một cách tiếp cận tốt vì nó sẽ lặp lại css mỗi khi sử dụng shortcode trên một trang. Tôi đã thấy một số cách tiếp cận khác trên trang web này và codp wp thậm chí có hai ví dụ của riêng họ, vì vậy thật khó để biết cách tiếp cận nào phù hợp và nhanh nhất.

Dưới đây là các phương pháp tôi hiện đang biết:

Phương pháp 1: Bao gồm trực tiếp trong shortcode - Đây là những gì tôi hiện đang làm trong plugin, nhưng có vẻ không tốt vì nó lặp lại mã.

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

Phương pháp 2: Sử dụng lớp để xử lý các tập lệnh hoặc kiểu có điều kiện

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

Phương pháp 3: Sử dụng 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' );

Phương pháp 4: Sử dụng 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');

Tôi nghĩ Method 4: Using has_shortcode();là tốt nhất bởi vì nó sẽ đảm bảo rằng các tập lệnh và kiểu sẽ tải một lần nếu nội dung bài đăng có shortcode bất kể nhiều lần sử dụng shortcode. Mặc dù nó có thể không hoạt động để sử dụng shortcode trong các widget hoặc trong sidebar, nhưng không chắc chắn. Nếu đó là một plugin thì tôi không khuyên bạn nên buộc các tập lệnh bằng shortcode bởi vì một số có thể gọi hàm của bạn thay vì shortcode để có đầu ra mong muốn.
Robert hue

Câu trả lời:


45

Tôi tìm thấy một cách khác phù hợp với tôi:

Dưới đây là một plugin ví dụ sử dụng phương thức này cho phép bạn sử dụng get_avatar dưới dạng shortcode. Biểu định kiểu chỉ được xử lý khi có shortcode.

Cách sử dụng (id mặc định cho người dùng hiện tại):

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

Quên tôi đã hỏi câu hỏi này năm ngoái, nhưng tôi thực sự đã bắt đầu làm theo cách này cũng như trong rất nhiều trường hợp. Nó giống như kết hợp phương pháp 1 và 2.
Bryan Willis

4
Phương pháp này tải CSS ở chân trang, chắc chắn có hạn chế?
Jacob Raccuia

1
Đây hoàn toàn là cách đúng đắn để làm điều này. Sử dụng phương pháp này bất cứ khi nào bạn cần tải một cách có điều kiện một tập lệnh hoặc biểu định kiểu khi wp_enqueue_scriptshook đã xảy ra. (Mã ngắn được phân tích cú pháp trong the_contentđó là một phần của the_posthook, có nghĩa là việc xử lý khi nó được phân tích cú pháp là quá muộn trừ khi bạn đã đăng ký tập lệnh)
JRad the Bad

26

Trước khi bắt đầu trả lời tôi phải nói rằng về chủ đề này css và js không giống nhau.

Lý do rất đơn giản: trong khi thêm js vào phần thân của trang (ở chân trang) là một cách phổ biến và hợp lệ, css cần được đặt trong <head>phần của trang: ngay cả khi phần lớn các trình duyệt có thể hiển thị css trong trang cơ thể, đó không phải là mã HTML hợp lệ.

Khi một shortcode được hiển thị, <head>phần đã được in, điều đó có nghĩa là js có thể được thêm vào mà không có bất kỳ vấn đề nào trên footer, nhưng phải thêm css trước khi shortcode được hiển thị.

Chữ viết

Nếu shortcode của bạn chỉ cần js thì bạn may mắn và chỉ có thể sử dụng wp_enqueue_scripttrong phần thân của cuộc gọi lại shortcode:

add_shortcode( 'myshortcode', 'my_handle_shortcode' );

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

Làm như vậy tập lệnh của bạn được thêm vào chân trang và chỉ một lần, ngay cả khi shortcode được sử dụng nhiều lần trong trang.

Kiểu dáng

Nếu bạn mã cần các kiểu, thì bạn cần phải hành động trước khi shortcode thực sự được hiển thị.

Có nhiều cách khác nhau để làm điều này:

  1. nhìn vào tất cả các bài viết trong truy vấn hiện tại và thêm các kiểu shortcode nếu cần. Đây là những gì bạn làm trong cả phương pháp # 3 và # 4 trong OP. Trên thực tế, cả hai phương pháp đều làm cùng một thứ, nhưng has_shortcodeđã được thêm vào WP 3.6, trong khi get_shortcode_regexcó sẵn từ phiên bản 2.5, vì vậy get_shortcode_regexchỉ sử dụng nếu bạn muốn làm cho plugin của mình tương thích với các phiên bản cũ hơn.

  2. luôn luôn thêm kiểu shortcode, trong tất cả các trang

Các vấn đề

Vấn đề với # 1 là hiệu suất. Regex là các hoạt động khá chậm và khởi chạy regex trong một vòng lặp của tất cả các bài viết có thể làm chậm trang một cách nhất quán. Hơn nữa, đây là một nhiệm vụ khá phổ biến trong các chủ đề để chỉ hiển thị đoạn trích trong tài liệu lưu trữ và hiển thị nội dung đầy đủ với mã ngắn chỉ trong chế độ xem số ít. Nếu điều đó xảy ra, khi kho lưu trữ được hiển thị, plugin của bạn sẽ khởi chạy một kết hợp regex trong một vòng lặp với mục đích thêm một kiểu sẽ không bao giờ được sử dụng: tác động hiệu suất kép không cần thiết: làm chậm việc tạo trang + yêu cầu HTTP không cần thiết bổ sung

Vấn đề với # 2 là hiệu suất, một lần nữa. Thêm kiểu cho tất cả các trang có nghĩa là thêm một yêu cầu HTTP bổ sung cho tất cả các trang, ngay cả khi không cần thiết. Ngay cả khi thời gian tạo trang phía máy chủ không bị ảnh hưởng, tổng thời gian kết xuất trang sẽ và cho tất cả các trang của trang.

Vì vậy, một nhà phát triển plugin nên làm gì?

Tôi nghĩ rằng điều tốt nhất để làm là thêm một trang tùy chọn vào plugin, nơi người dùng có thể chọn nếu xử lý shortcode chỉ trong chế độ xem số ít hoặc thậm chí trong kho lưu trữ. Trong cả hai trường hợp, tốt hơn là cung cấp tùy chọn khác để chọn loại bài đăng nào kích hoạt shortcode.

Theo cách đó có thể móc "template_redirect"để kiểm tra xem truy vấn hiện tại có thỏa mãn yêu cầu hay không và trong trường hợp đó thêm kiểu.

Nếu người dùng chọn chỉ sử dụng shortcode trong chế độ xem bài đăng đơn lẻ, thì nên kiểm tra xem bài đăng có shortcode hay không: một khi chỉ cần một regex thì không nên làm chậm trang quá nhiều.

Nếu người dùng chọn sử dụng shortcode ngay cả trong kho lưu trữ, thì tôi sẽ tránh chạy regex cho tất cả các bài đăng nếu số lượng bài viết cao và chỉ cần ghi lại kiểu nếu yêu cầu phù hợp với truy vấn.

Những gì cần xem xét "cao" về vấn đề này nên được sử dụng một số bài kiểm tra hiệu suất hoặc, thay thế, thêm tùy chọn khác và đưa ra lựa chọn cho người dùng.


2
Điều đáng chú ý ở đây là <style>các thẻ trong phần thân tài liệu hiện có giá trị theo thông số W3C. w3.org/TR/html52/document-metadata.html#the-style-element
Isaac Lubow

5

Đối với plugin của tôi, tôi thấy rằng đôi khi người dùng có trình tạo chủ đề có mã ngắn được lưu trữ trong dữ liệu bài đăng . Đây là những gì tôi đang sử dụng để phát hiện xem shortcode plugin của tôi có trong dữ liệu meta bài đăng hoặc bài đăng hiện tại hay không :

function abcd_load_my_shorcode_resources() {
       global $post, $wpdb;

       // determine whether this page contains "my_shortcode" shortcode
       $shortcode_found = false;
       if ( has_shortcode($post->post_content, 'my_shortcode') ) {
          $shortcode_found = true;
       } else if ( isset($post->ID) ) {
          $result = $wpdb->get_var( $wpdb->prepare(
            "SELECT count(*) FROM $wpdb->postmeta " .
            "WHERE post_id = %d and meta_value LIKE '%%my_shortcode%%'", $post->ID ) );
          $shortcode_found = ! empty( $result );
       }

       if ( $shortcode_found ) {
          wp_enqueue_script(...);
          wp_enqueue_style(...);
       }
}
add_action( 'wp_enqueue_scripts', 'abcd_load_my_shorcode_resources' );

2

Tôi làm như vậy:

class My_Shortcode {

    function __construct() {
        do_action('my_start_shortcode'); // call
....

và bắt hook trong các chức năng khác (hoặc các plugin khác):

function wpse_3232_load_script(){
    wp_enqueue_script('js-myjs');
}
add_action('my_start_shortcode','wpse_3232_load_script',10);

1

Tôi đã tìm ra plugin của riêng mình, nếu shortcode có trong widget văn bản.

function check_shortcode($text) {

  $pattern = get_shortcode_regex();

   if (   preg_match_all( '/'. $pattern .'/s', $text, $matches )
        && array_key_exists( 2, $matches )
        && in_array( 'myshortcode', $matches[2] ) )
    {
        // myshortcode is being used

        // enque my css and js
        /****** Enqueu RFNB  ******/
        wp_enqueue_style('css-mycss');
        wp_enqueue_script('js-myjs');

        // OPTIONAL ALLOW SHORTCODE TO WORK IN TEXT WIDGET
        add_filter( 'widget_text', 'shortcode_unautop');
        add_filter( 'widget_text', 'do_shortcode'); 

    }

  return $text;

}
add_filter('widget_text', 'check_shortcode');

1

WordPress có một chức năng tích hợp để làm một cái gì đó dựa trên trạng thái trình bày Shortcode cụ thể. Tên chức năng là has_shortcode(). Bạn có thể sử dụng đoạn mã sau để thể hiện phong cách và kịch bản của mình.

Ở đây tôi đã sử dụng is_a( $post, 'WP_Post' )để kiểm tra xem $postđối tượng có thuộc WP_Postlớp không và tôi đã sử dụng $post->post_contentđể kiểm tra nội dung bài đăng.

if ( is_a( $post, 'WP_Post' ) && has_shortcode( $post->post_content, 'shortcode_tag') ) {
    wp_enqueue_style( 'handle', get_template_directory_uri() . '/your_file_filename.css' );
}

0

Tôi đã thực hiện kết hợp mã ví dụ từ trang Wordpress cho has_shortcode () và câu trả lời mà zndencka đã đưa ra. Tôi đã nhận thấy rằng hàm has_shortcode được thêm vào trong Wordpress 3.6, vì vậy đó là lý do đầu tiên tôi kiểm tra xem hàm có tồn tại không. Có lẽ kiểm tra đó là một chút lỗi thời, vì không còn nhiều người dùng từ bên dưới wordpress 3.6 nữa theo thống kê riêng của họ.

// This makes sure the styling is already enqueued in the header, so before the shortcode loads in the page/post
function enqueue_shortcode_header_script() {
    global $post;
    if ( function_exists( 'has_shortcode' ) ){  // is added in wordpress 3.6
        // Source: https://codex.wordpress.org/Function_Reference/has_shortcode
        if( is_a( $post, 'WP_Post' ) && has_shortcode( $post->post_content, 'my_shortcode') ) {
            wp_enqueue_style( 'shortcode-css' );
        }
    }
    else if ( isset($post->ID) ) { // Small percentage wordpress users are below 3.6 https://wordpress.org/about/stats/
        global $wpdb;
        $result = $wpdb->get_var(
          $wpdb->prepare(
              "SELECT count(*) FROM $wpdb->postmeta " .
              "WHERE post_id = %d and meta_value LIKE '%%my_shortcode%%'",
               $post->ID )
        );
        if (!empty( $result )) { wp_enqueue_style( 'shortcode-css' ); }
    }
}
add_action( 'wp_enqueue_scripts', 'enqueue_shortcode_header_script');

0

Chúng tôi thực sự có thể tải các tệp CSS và JS một cách có điều kiện thông qua shortcode mà không cần sử dụng bất kỳ hàm quá phức tạp nào :

Trước tiên, giả sử chúng tôi đã đăng ký tất cả các tệp CSS / JS trước đây (có thể khi wp_enqueue_scriptschạy)

function prep_css_and_js() {
     wp_register_style('my-css', $_css_url);
     wp_register_script('my-js', $_js_url);
}
add_action( 'wp_enqueue_scripts', 'prep_css_and_js', 5 );

Tiếp theo, hãy kiểm tra chức năng shortcode của chúng tôi:

function my_shortcode_func( $atts, $content = null ) {
  if( ! wp_style_is( "my-css", $list = 'enqueued' ) ) { wp_enqueue_style('my-css'); }
  if( ! wp_script_is( "my-js", $list = 'enqueued' ) ) { wp_enqueue_script('my-js'); }
  ...
}

Đơn giản. Làm xong. Ergo: chúng tôi có thể "tải điều kiện" các tệp css / js, (chỉ khi [shortcode] chạy).

Hãy xem xét các ý thức hệ sau:

  • Chúng tôi muốn tải một số tệp CSS / JS nhất định (nhưng chỉ khi kích hoạt shortcode)
  • Có thể chúng tôi không muốn các tệp đó tải trên mỗi trang hoặc hoàn toàn nếu shortcode không được sử dụng trên một trang / bài đăng. (trọng lượng nhẹ)
  • Chúng ta có thể thực hiện điều này bằng cách đảm bảo WP đăng ký TẤT CẢ các tệp css / js trước khi gọi shortcode và trước khi đăng ký.
  • IE: Có thể trong prep_css_and_js()chức năng của mình, tôi tải TẤT CẢ các tệp .css / .js trong các thư mục nhất định ...

Bây giờ WP xem chúng là các tập lệnh đã đăng ký, chúng tôi thực sự có thể gọi chúng, theo điều kiện, dựa trên tính xác thực của các tình huống, bao gồm nhưng không giới hạn ở my_shortcode_func()

Lợi ích: (không có MySQL, không có chức năng nâng cao và không cần bộ lọc)

  • đây là "WP orthodix", thanh lịch, tải nhanh, dễ dàng và đơn giản
  • cho phép trình biên dịch / trình khai thác phát hiện các tập lệnh như vậy
  • sử dụng các hàm WP (wp_register_style / wp_register_script)
  • tương thích với nhiều chủ đề / plugin có thể muốn hủy đăng ký các tập lệnh đó vì lý do chính đáng.
  • sẽ không kích hoạt nhiều lần
  • rất ít xử lý hoặc mã có liên quan

Người giới thiệu:

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.