Должны ли третьи стороны использовать $ wp_scripts / $ wp_styles-> add_data?

31

Внутри 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(): добавляет json-кодированный объект (обёрнутый более «публичной» wp_localize_script()функцией)

  • wp_plupload_default_settings() : добавляет закодированный в json объект (созданный из многомерного массива) для сценария 'wp-plupload' (обратите внимание, что это ожидается в 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отлично справляется с многомерными массивами.

Этот метод, кажется, работает очень хорошо по следующим причинам:

  1. Это позволяет вам прикреплять данные к дескриптору сценария, чтобы он всегда был правильно помещен в сценарий. Кроме того, будет разумно удалить сценарий из очереди, порядок и размещение сценария.
  2. Это позволяет использовать PHP для отправки переменных в JS.
  3. Это кажется более организованным, чем использование 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 перед сценарием в очереди.

Я не думаю, что есть «правильный» ответ на этот вопрос, но хотел бы услышать, что думают другие разработчики. Я также представляю, что в этой головоломке есть кусочки, которыми я полностью пренебрегал и хотел бы услышать, что другие скажут об этом.

tollmanz
источник

Ответы:

4

Эта функция добавляет данные в скрипты / стили, которые были поставлены в очередь во время загрузки WordPress.

На самом деле, нет. Он добавляет данные в сценарии / стили, которые были registered.

Ключ данных, который устанавливается, wp_localize_scriptв конечном итоге перезаписывается вызовом $wp_scripts->add_data, тогда как если вы wp_localize_scriptдважды вызываете один и тот же сценарий, строка будет правильно объединена.

Правильно. Они оба вызывают базовый (недоступный, внутренний) API, поэтому он перезаписывается (как вы заявили). Это происходит, когда он звонит $this->get_data( $handle, 'data' );.

Вопрос

Мой главный вопрос: должны ли разработчики использовать эту функцию?

Ответ

Проще говоря: да, когда у тебя нет другого шанса сделать то, что тебе нужно.

Другой пример: проверьте, был ли зарегистрирован скрипт (например, json2/jquery) и переместите его в нижний колонтитул (проверьте extra['group']).

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

Примечание: это ↑ работает только для данных, поданных в extra!

Дополнительные замечания

Встречный вопрос: Вы когда-нибудь пытались добавить зависимости в скрипты, зарегистрированные ядром? Например: попробуйте добавить JSON2при необходимости deps в jQuery. Это невозможно без перехвата global $wp_scripts:

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

Есть целый ряд вещей, которые класс не может сделать. Таким образом , используя что - то вроде ->add_data()это имо полноценными. Просто используйте то, что у вас есть, потому что это все же лучше, чем жить без базовых классов.

кайзер
источник
«Подождите, пока ядро ​​не добавит возможность добавлять зависимости в стандартные и встроенные скрипты». Вы открывали тикет в trac?
scribu
@scribu Спасибо, но нет, нет и не буду. Все мои билеты там просто гниют, поэтому я отступил от усилий, направленных на приобретение билетов. Это не оскорбление, просто вывод из того, что я испытал до сих пор. Но чтобы не начинать спорить с вами, я удалю его, так как это просто осталось от простого копирования / вставки из одного из моих плагинов.
Кайзер
Ну, тогда, я думаю, мне придется спросить здесь: какая польза от загрузки JSON2 перед jQuery?
scribu
Ничего, так как это абстрактный пример. Если вы попытаетесь найти более подробный пример, вы можете представить одну библиотеку, которая нуждается JSON2, но также должна быть загружена раньше jQuery: давайте назовем ее UberjQuery. Кстати: поскольку вы хорошо справляетесь с diggin 'в ядро, почему бы вам не выделить время и написать ответ? Я думаю, это стоило бы времени на чтение.
Кайзер
Спасибо за ваши мысли, Кайзер! Я определенно ищу методы для добавления JS, который поддерживается "API". Хотя я знаю, что могу согнуть его, чтобы делать все что угодно, это может привести к нестабильному коду. Приятно знать, для чего он предназначен, а не что он может сделать, и, конечно, с этим можно многое сделать.
Tollmanz
1

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

Итак, я бы использовал, add_data()если бы не было высокоуровневого API для того, что мне нужно было сделать, с пониманием того, что его поведение может измениться в некоторых крайних случаях, например, когда используется конкатенация.

scribu
источник
Спасибо за ваш вклад Scribu! Забавно, что вы ссылаетесь на этот билет! Я ссылался на это в своем посте, но в нем так много всего происходило, что я не понял, что теперь поддерживаются многомерные массивы.
Tollmanz
Ха ... приятно редактировать! Этот билет меня не смутил так, как я думал.
Tollmanz
@ tollmanz Да, это довольно странно, особенно если вы не были в IRC в то время.
scribu
Мистер @ungestaltbar показал мне способ добавления многомерных массивов несколько месяцев назад. Не знал, что это уже в ядре.
Кайзер
@scribu - разве нет поддержки многомерных массивов? - по крайней мере, я использую их без проблем ...
Стивен Харрис