WP_Dependencies类中存在一个名为add_data的方法。此函数将数据添加到WordPress加载期间已排队的脚本/样式。该功能通常被引用的用途是在添加针对IE的不同版本的样式表时添加条件。例如,要定位IE8和更低版本:

function test_wp_print_styles() {
    global $wp_styles;

    wp_enqueue_style( 'test-style', get_template_directory_uri() . '/css/test.css', array(), 1, 'all' );
    $wp_styles->add_data( 'test-style', 'conditional', 'lte ie8' );
}
add_action( 'wp_print_styles', 'test_wp_print_styles' );


这将呈现为:

<!--[if lte ie8]>
<link rel='stylesheet' id='test-style-css'  href='http://trunkosaurus.dev/wp-content/themes/twentyeleven/css/test.css?ver=1' type='text/css' media='all' />
<![endif]--> 


当我通过Core查看,我看到了使用此方法的少数地方:


WP_Styles->add_inline_style():在引用的样式表之后添加内联样式(通过WP_Styles->print_inline_style()完成)
WP_Scripts->localize():为“ wp-plupload”添加json编码的对象(由
更多“公共” wp_localize_script()函数包装)
wp_plupload_default_settings():添加json编码的对象(由
多维数组创建)脚本(请注意,
这将在3.4中推出)
注册/排队脚本和样式时
为默认脚本添加数据
wp-includes/script-loader.php

从通读该方法的用法,它似乎没有特定的用例。在wp_plupload_default_settings中,似乎允许任意数据注入。在wp_register_script中,它似乎用于区分页眉和页脚脚本。在add_inline_style中,它用于表示应在指定样式表入队后添加的内联样式。

此功能的出色用法将类似于以下代码,在其中将外部脚本加入队列,但需要向其发送一些配置变量,其中一些来自数据库:

function zdt_enqueue_add_this() {
    global $wp_scripts;

    wp_enqueue_script( 'zdt-add-this', 'http://s7.addthis.com/js/250/addthis_widget.js#pubid=myidhere' );

    // Contrived example of database call to get a twitter handle stored in the db
    $author_twitter_handle = zdt_get_twitter_handle();

    $js = "var addthis_share = { templates : { twitter: '{{title}} {{url}} (by @" . sanitize_key( $author_twitter_handle ) . "' } };\n";
    $js .= 'var addthis_config = { ui_header_color: "#FFFFFF", ui_header_background: "#FA9628", ui_cobrand: "My Site" };';

    $wp_scripts->add_data( 'zdt-add-this', 'data', $js );
}
add_action( 'wp_enqueue_scripts', 'zdt_enqueue_add_this' );


这将导致:

<script type='text/javascript'>
/* <![CDATA[ */
var addthis_share = { templates : { twitter: '{{title}} {{url}} (by @tollmanz' } };
var addthis_config = { ui_header_color: "#FFFFFF", ui_header_background: "#FA9628", ui_cobrand: "My Site" };
/* ]]> */
</script>
<script type='text/javascript' src='http://s7.addthis.com/js/250/addthis_widget.js?ver=3.4-beta4-20731#pubid=myidhere'></script>


请注意,这不能用wp_localize_script来完成,因为addthis_share对象在属性内具有属性(之前我确实写过一些有点怪异的方法。)

编辑:我在陈述这一点上是错误的。 wp_localize_script可以很好地处理多维数组。

由于以下原因,该方法似乎非常有效:


它使您可以将数据附加到脚本句柄,以便始终将其与脚本正确地排队。此外,它将使脚本的出队,脚本顺序和脚本放置变得更聪明。
它使您可以使用PHP将vars发送给JS。
它看起来比使用wp_print_styles来打印一些任意文本更为井井有条。脚本由排队的脚本执行。

有些事情无法按预期工作,这让我感到担忧。这样的问题之一是,如果将wp_localize_script$wp_scripts->add_data一起使用,则会得到意想不到的结果。例如:

// Contrived example of database call to get a twitter handle stored in the db
$author_twitter_handle = zdt_get_twitter_handle();

$js = "var addthis_share = { templates : { twitter: '{{title}} {{url}} (by @" . sanitize_key( $author_twitter_handle ) . "' } };\n";
$js .= 'var addthis_config = { ui_header_color: "#FFFFFF", ui_header_background: "#FA9628", ui_cobrand: "My Site" };';

$wp_scripts->add_data( 'zdt-add-this', 'data', $js );
wp_localize_script( 'zdt-add-this', 'addthis_share', array( 'var' => 'val' ) );


产品:

<script type='text/javascript'>
/* <![CDATA[ */
var addthis_share = { templates : { twitter: '{{title}} {{url}} (by @tollmanz' } };
var addthis_config = { ui_header_color: "#FFFFFF", ui_header_background: "#FA9628", ui_cobrand: "My Site" };
var addthis_share = {"var":"val"};
/* ]]> */
</script>
<script type='text/javascript' src='http://s7.addthis.com/js/250/addthis_widget.js?ver=3.4-beta4-20731#pubid=myidhere'></script>


而此脚本:

// Contrived example of database call to get a twitter handle stored in the db
$author_twitter_handle = zdt_get_twitter_handle();

$js = "var addthis_share = { templates : { twitter: '{{title}} {{url}} (by @" . sanitize_key( $author_twitter_handle ) . "' } };\n";
$js .= 'var addthis_config = { ui_header_color: "#FFFFFF", ui_header_background: "#FA9628", ui_cobrand: "My Site" };';

wp_localize_script( 'zdt-add-this', 'addthis_share', array( 'var' => 'val' ) );
$wp_scripts->add_data( 'zdt-add-this', 'data', $js );


结果:

<script type='text/javascript'>
/* <![CDATA[ */
var addthis_share = { templates : { twitter: '{{title}} {{url}} (by @tollmanz' } };
var addthis_config = { ui_header_color: "#FFFFFF", ui_header_background: "#FA9628", ui_cobrand: "My Site" };
/* ]]> */
</script>
<script type='text/javascript' src='http://s7.addthis.com/js/250/addthis_widget.js?ver=3.4-beta4-20731#pubid=myidhere'></script>


data设置的wp_localize_script密钥最终被$wp_scripts->add_data的调用覆盖,而如果调用wp_localize_script对于相同的脚本两次,该字符串将被正确地连接。

尽管这是一种打印任意脚本以用于排队脚本的非常方便的方法,但我认为它不应该由于潜在的冲突而被广泛使用。我当然可以看到在个人项目中使用此参数的论点,其中在社区插件/主题中不会使用该代码。

我还查看了Core Trac,以查看是否有任何有关此功能目的的线索。我发现了一张票证(http://core.trac.wordpress.org/ticket/11520)(当时是史诗级票证),探讨了添加任意JS的其他方法。因此,似乎有兴趣创建一种更好的方法来添加任意JS,但不确定add_data是否应作为该过程的一部分。

我的主要问题是:开发人员应该使用此功能吗?在某些情况下(例如wp_register_script),似乎第三方不应使用“私有”功能;但是,在其他情况下(例如wp_plupload_default_settings),这似乎是在排队的脚本之前注入任意JS的一种完全合理的方法。

我不认为对此有“正确”的答案,但很想听听其他开发者的想法。我也想像这个难题中有一些我完全忽略的部分,很想听听其他人对此有何评论。

#1 楼


此功能将数据添加到WordPress加载期间已排队的脚本/样式。


并非如此。它将数据添加到已经是registered的脚本/样式中。


wp_localize_script设置的数据键最终会被对$wp_scripts->add_data的调用覆盖,而如果您为wp_localize_script两次调用$this->get_data( $handle, 'data' );相同的脚本,字符串将被正确连接。


对。它们都调用底层的(不可访问的,内部的)API,因此它会被覆盖(如您所述)。当调用json2/jquery时会发生这种情况。

问题


我的主要问题是:开发人员应该使用此功能吗?


答案

简单地说:是的,当您没有其他机会去做您需要的事情时。

另一个例子:检查脚本是否已注册(例如extra['group'])并将其移至页脚(检查extra)。

// Move scripts to the footer - in case it isn't already there
if ( ! $wp_scripts->get_data( 'json2', 'group' ) )
    $wp_scripts->add_data( 'json2', 'group', 1 );

if ( ! $wp_scripts->get_data( 'jquery', 'group' ) )
    $wp_scripts->add_data( 'jquery', 'group', 1 );


注意:此↑仅适用于JSON2下提交的数据!

其他说明

反问:您是否曾经尝试过向内核注册的脚本添加依赖项?例如:尝试根据需要将jQuery添加到global $wp_scripts。不拦截->add_data()是不可能的:

global $wp_scripts;

$scripts = array( 
     'jquery'      => array( 'json2' )
    ,'jquery-form' => array( 'json2' ) 
);

foreach ( $scripts as $handle => $deps )
{
    // Ugly hack: Intercept the global to force the "natural"/needed order: JSON2 » jQuery
    $deps_default =& $wp_scripts->registered[ $handle ]->deps;
    $wp_scripts->registered[ $handle ]->deps = array_merge( $deps_default, $deps );
}


有很多事情是类无法完成的。因此,使用类似q4312079q之类的内容imo完全有效。只需使用您得到的东西,因为它仍然比缺少核心类的人更好。

评论


“等到core添加了向默认和内置脚本添加依赖项的可能性之后,”您是否在追踪中打开了票证?

–抄写员
2012年5月17日下午14:42

@scribu谢谢,但是不,我没有,不,我不会。我的所有门票都只是在那儿腐烂了,所以我从投入精力撤回了追踪门票。这不是冒犯,只是我到目前为止所获得的结论。但是,为了不与您争论,我将其删除,因为这只是从我的一个插件的简单复制/粘贴操作中获得的。

– kaiser
2012年5月17日15:35



好吧,那么我想我不得不在这里问:在jQuery之前加载JSON2有什么好处?

–抄写员
2012年5月17日在21:18

没什么,因为这是一个抽象的例子。如果您想找到一个更详细的示例,那么您可以想象一个需要JSON2,但也需要在jQuery之前加载的库:让我们将其命名为UberjQuery。顺便说一句:由于您在“挖掘核心”方面做得很好,所以为什么不花时间写答案呢?我想值得一读。

– kaiser
2012年5月17日在22:47



感谢您的想法Kaiser!我绝对在寻找添加“ API”支持的JS的方法。虽然我知道我可以弯腰去做各种各样的事情,但这可能会导致代码不稳定。很高兴知道它的目的而不是它可以做什么,当然,可以做很多事情。

– tollmanz
2012年5月18日下午2:58

#2 楼

WP 3.3中有一个关于如何处理脚本数据的大辩论:

http://core.trac.wordpress.org/ticket/11520

请注意,您可以现在将嵌套数组传递给wp_localize_data()

wp_localize_script( 'jquery', 'jQueryL10n', array(
    'foo' => array(
        'bar' => array( 'apple', 'orange' )
    ),
) );


因此,如果没有需要执行的更高级别的API,我将使用add_data(),但前提是它是在某些极端情况下(例如涉及串联时),行为可能会发生变化。

评论


感谢您对Scribu的投入!有趣的是,您链接到该票证!我在我的文章中链接了它,但是由于发生了太多事情,以至于我没有意识到现在支持多维数组。

– tollmanz
2012年5月18日在2:53

哈...好编辑!那张票没有让我感到困惑。

– tollmanz
2012年5月18日下午2:55

@tollmanz是的,这非常令人困惑,尤其是如果您当时不在IRC中时。

–抄写员
2012年5月18日,下午2:56

@ungestaltbar先生在一个月前向我展示了一种添加多维数组的方法。不知道,这已经是核心。

– kaiser
2012年5月18日在9:03

@scribu-是否已经不支持多维数组? -至少我使用它们没有任何问题...

–斯蒂芬·哈里斯(Stephen Harris)
2012年5月18日在11:44