问题描述

在插件中注册/排队脚本和/或样式的想法是什么?

我最近做了一个插件 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 辅助翻译的英文资料结果。如果您对结果不满意,可以加入我们改善翻译效果:薇晓朵技术论坛。