Обработка конфликтов jQuery-компонентов
При разработке плагинов, какие лучшие практики следует применять, чтобы избежать конфликтов jQuery-компонентов на фронтенде?
Например, допустим я включаю jQuery Apprise диалог в плагин, который загружает его на фронтенде, но другой плагин может делать то же самое. Поскольку компонент загружается и объявляется дважды, или возможно одна версия форкнута и изменена, а моя - нет, мы получаем ошибки JavaScript на фронтенде (как я предполагаю).
(Отмечу, что я использую лучшую практику - стратегию wp_register_script() и wp_enqueue_script() через событие действия wp_head() для загрузки jQuery-компонента на фронтенде.)

Моё предложение — использовать комбинацию изоляции кода в анонимной функции и проверки наличия jQuery.
Вот пример:
(function() {
var jQuery; // ваша переменная jQuery
// проверяем, есть ли jQuery и нужная ли версия
if (window.jQuery === undefined || window.jQuery.fn.jquery !== '1.8.3') {
// загружаем библиотеку jQuery из Google Hosted Libraries
var script_tag = document.createElement('script');
script_tag.setAttribute("type","text/javascript");
script_tag.setAttribute("src","http://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js");
// ждём загрузки библиотеки jQuery
if (script_tag.readyState) {
script_tag.onreadystatechange = function () { // старые версии IE
if (this.readyState == 'complete' || this.readyState == 'loaded') {
jqueryLoadHandler();
}
};
} else { // для других браузеров
script_tag.onload = jqueryLoadHandler;
}
// Пытаемся найти head, иначе используем documentElement
(document.getElementsByTagName("head")[0] || document.documentElement).appendChild(script_tag);
} else {
// На сайте уже используется нужная версия jQuery, просто присваиваем её нашей переменной
jQuery = window.jQuery;
main();
}
// как только jQuery загрузится
function jqueryLoadHandler() {
// Восстанавливаем $ и window.jQuery к их предыдущим значениям и сохраняем
// новую jQuery в нашей локальной переменной jQuery
jQuery = window.jQuery.noConflict(true);
// Вызываем основную функцию плагина
main();
}
// основная функция плагина
function main() {
jQuery(document).ready(function($) {
// Здесь можно безопасно использовать $
});
}
})(); // Немедленно вызываем нашу анонимную функцию
Таким образом, вы можете использовать jQuery в своём плагине без проблем, даже если другие плагины загружали jQuery без wp_enqueue_script. Все переменные и функции внутри этой анонимной функции не будут конфликтовать с остальной частью страницы.
Возможно, это будет работать ещё лучше, если интегрировать данный подход с wp_enqueue_script.
Подробнее об этом подходе загрузки jQuery внутри анонимной функции можно прочитать в http://alexmarandon.com/articles/web_widget_jquery/

Обратите внимание, что этот вопрос касается сторонних библиотек (плагинов и т.д.).

Проблема с jQuery core очень распространена, и многие плагины имеют множество способов предотвратить ее.
Когда мы говорим о плагинах для jQuery, есть еще одна проблема, но вы можете удалить ее аналогичным способом.
В вашей ситуации я предпочитаю общее решение - добавить переключатель включения на странице настроек вашего плагина - я думаю, это очень популярно для плагинов с jQuery core, но вы также можете использовать его для jQuery плагинов.
Другое решение - написать скрипт на js для проверки, определен ли дополнительный метод jQuery (из плагина), и если он не определен, вы можете подключить плагин в вашем скрипте. Это решение будет работать только если вы добавите хук для скриптов с очень низким приоритетом. Он будет выполняться после других плагинов, и это условие сработает.

Лучшей практикой для подключения или регистрации скриптов является использование wp_register_script
и wp_enqueue_script
. Плагины и темы, которые не используют эти функции для добавления своих скриптов, не должны использоваться.
Причина проста: с помощью wp_register_script()
мы можем получить много информации о зарегистрированных скриптах. Особенно важно, зарегистрирован ли уже определенный источник или нет.
Я написал простой класс для проверки, зарегистрирован ли источник. Класс может отменить регистрацию скрипта и зарегистрировать новый скрипт или пропустить новый скрипт. Этот класс должен стать отправной точкой для вашей собственной разработки. Он не предназначен для рабочей среды!
Как работает класс?
Класс получает массив со скриптами, которые должны быть зарегистрированы. Затем он сравнивает имена файлов (и только имена файлов) каждого зарегистрированного скрипта с именами файлов скриптов, которые должны быть зарегистрированы. Если скрипт/имя файла еще не зарегистрирован, его хэндл будет добавлен в массив и зарегистрирован позже.
Класс можно расширить, чтобы сравнивать полный путь к скрипту, версию или любые другие параметры, необходимые для принятия решения о регистрации скрипта.
Простой пример
$my_scripts = array(
'foo' => array(
'src' => 'external/ressource/foo.js',
'deps' => array( 'jquery' ),
'version' => false,
'in_footer' => true
),
'bar' => array(
'src' => home_url( '/wp-admin/js/common.min.js' ),
'deps' => false,
'version' => false,
'in_footer' => true
),
'jquery' => array(
'src' => '//ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js',
'deps' => false,
'version' => '1.8.3',
'in_footer' => true
),
);
$safe_register = new Safe_Registering_Scripts( $my_scripts, true );
global $wp_scripts;
var_dump( $wp_scripts->registered['jquery'] );
Сначала мы определяем массив со всеми нашими скриптами, которые нужно зарегистрировать. Класс проверит наши скрипты и сравнит, зарегистрирован ли источник.
- скрипт
foo
всегда будет зарегистрирован, потому что его источник не зарегистрирован. - скрипт
bar
никогда не будет зарегистрирован, потому что его источник уже зарегистрирован. - скрипт
jquery
— это особый случай. Хэндл с именемjquery
уже существует, но второй параметр в вызове класса указывает, что источник этого скрипта должен быть заменен новым источником.
Как видно в var_dump()
, источник скрипта jquery
был заменен классом. Если вы расширите класс и настроите проверку (источник, имя файла js, версию, подключенные скрипты и т. д.), это поможет минимизировать конфликты js.
