如何在入队脚本之后立即回显JS,以将其置于无冲突模式?

时间:2013-12-01 作者:Rarst

我想包括并使用第三方JavaScript文件(Bootstrap Tooltip) 在我的插件中。因为Bootstrap是非常流行的框架tooltip() 是我想使用的相当通用的名称noConflict() 在我自己的变量中隔离工具提示实例的功能。

如果我完全理解时间安排,则需要在加载脚本文件后立即执行此操作,这样就不会有任何其他操作有机会弄乱实例(它刚刚设置好)或被它弄乱。

然而,队列功能中似乎没有约定在这种情况下回显JS。$wp_scripts->print_extra_script() 在脚本之前调用。

使用当前队列实现是否可以实现这一点?

3 个回复
最合适的回答,由SO网友:Rarst 整理而成

WordPress>=4.1script_loader_tag 筛选排队脚本的完整HTML。非常适合在其后面添加内容。

WordPress<;4.1我最终与wp_print_footer_scripts 优先考虑11 (队列结束后)并调用wp_print_scripts() 显式地在脚本的句柄上,然后响应我需要的内容。

我会犹豫是否将它用于一些重要的事情,但对于小的包含脚本来说,它似乎是可以接受的。

SO网友:fuxia

你必须过滤script_loader_src, 检查脚本是否正确,并为添加一次性筛选器clean_url. 然后添加额外的脚本,并确保输出在语法上有效。

很简单,尽管有点老套。

class Extra_Script
{
    private $extra = [];
    private $handle;
    private $url;
    private $versioned_url;

    public function __construct( $handle, $url )
    {
        $this->handle = $handle;
        $this->url    = $url;
        add_filter( \'script_loader_src\', array( $this, \'filter_script_src\' ), 10, 2 );
    }

    public function add_script( $script )
    {
        $this->extra[] = $script;
    }

    public function filter_script_src( $src, $handle )
    {
        if ( empty ( $this->extra ) )
            return $src;

        if ( $this->handle !== $handle )
            return $src;

        if ( 0 !== strpos( $src, $this->url ) )
            return $src;

        $this->versioned_url = $src;

        add_filter( \'clean_url\', array( $this, \'filter_esc_url\' ) );
        remove_filter( current_filter(), array( $this, __FUNCTION__ ) );

        return $src;
    }

    public function filter_esc_url( $url )
    {
        if ( $url !== $this->versioned_url )
            return $url;

        remove_filter( current_filter(), array( $this, __FUNCTION__ ) );

        $scripts = join( "\\n", $this->extra );

        return "$url\'></script><script>$scripts</script><script class=\'";
    }
}
用法
add_action( \'wp_enqueue_scripts\', function()
{
    $handle = \'foo\';
    $url    = plugins_url( \'/foo.js\', __FILE__ );

    wp_enqueue_script( $handle, $url );

    $extra = new Extra_Script( $handle, $url );
    $extra->add_script( "alert(\'bar!\');" );
});
这将在您的排队脚本之后添加一个内联脚本。

另一种选择可能是Patchwork. 你可以用它在运行时重新定义WordPress的代码。但这也同样令人讨厌。

SO网友:gmazzap

今天,我需要做或多或少相同的事情,最终找到另一种解决方案,我想与大家分享,以防它对别人有用。

我编写了一个自定义类扩展WP_Script, 类似这样:

class GM_Scripts extends WP_Scripts {

    static function buildFromWp( WP_Scripts $scripts ) {
        $class = get_called_class();
        $obj = new $class;
        foreach ( get_object_vars( $scripts ) as $n => $v ) {
            $obj->$n = $v;
        }
        return $obj;
    }

    public function do_item( $handle, $group = false ) {
        $done = parent::do_item( $handle, $group );
        do_action( \'after_script_done\', $handle, $done );
    }

}
该类继承父WP类的所有方法,除了一个,do_item 这是用于在标记上有效打印脚本的方法。

GM_Scripts::do_item() 对调用相同的方法WP_Script 在触发自定义操作之后\'after_script_done\' 将脚本句柄和布尔值作为参数传递,如果脚本有效地打印在页面上,则布尔值为true。

在那之后,我上钩了wp_print_scripts 覆盖全局$wp_scripts 对象的实例,使用静态方法构建buildFromWp 继承WP_Scripts 作为参数传递。

add_action( \'wp_print_scripts\', function() {

  if ( is_admin() || did_action(\'login_head\') || ! isset($GLOBALS[\'wp_scripts\']) ) {
    return;
  }

  $GLOBALS[ \'wp_scripts\' ] = GM_Scripts::buildFromWp( $GLOBALS[ \'wp_scripts\' ] );

}, 0 );
一旦我的实例继承了原始WP类的状态、类型和方法,就不会导致WordPress或第三方代码出现任何问题。

此外,这只会发生在前线,以进一步减少任何冲突的机会。

最后,我添加了响应我需要的操作:

add_action( \'after_script_done\', function( $handle, $done ) {

  if ( $handle === \'myscript\' && $done ) {
     // echo what needed
  }

}, 0, 2 );
并像往常一样将我的脚本排入队列:

add_action( \'wp_enqueue_script\', function() {

  wp_enqueue_script( \'myscript\', $script_url );

} );
与公认的方法相比,这种方法有什么好处?

首先,它是一种更通用的方法,可用于每个脚本,更重要的是,对我的脚本的任何依赖都得到了正确的解决。

例如,另一段代码可以使用

add_action( \'wp_enqueue_script\', function() {

  wp_enqueue_script( \'another-script\', $another_url, array( \'myscript\' ) );

} );
在这种情况下,使用公认的方法

如果我的脚本之前已注册\'wp_head\' 它将被插入到页面中,没有冲突或任何我想打印的内容

如果未注册\'another-script\' 不会插入,因为WordPress无法解决依赖关系

结束

相关推荐

Newest version of javascript

对我的网站进行更新,除了javascript文件外,所有文件似乎都更新正常。我认为这与版本有关,但尽我所能,我无法获得版本编号。 wp_register_script (\'headjq\', get_bloginfo(\'template_directory\') . \"/js/headjq.js\"); wp_enqueue_script(\'headjq\'); 是否有一种方法可以自动将版本号附加到末尾,以强制客户端更新脚本?