JQuery ловушек, чтобы избежать
Я начинаю проект с jQuery.
Какие подводные камни / ошибки / неправильные представления / злоупотребления / злоупотребления у вас были в вашем проекте jQuery?
27 ответов
Не знать о падении производительности и злоупотреблять селекторами вместо того, чтобы назначать их локальным переменным. Например:-
$('#button').click(function() {
$('#label').method();
$('#label').method2();
$('#label').css('background-color', 'red');
});
Скорее, чем:-
$('#button').click(function() {
var $label = $('#label');
$label.method();
$label.method2();
$label.css('background-color', 'red');
});
Или еще лучше с цепочкой: -
$('#button').click(function() {
$("#label").method().method2().css("background-color", "red");
});
Я нашел этот поучительный момент, когда понял, как работают стеки вызовов.
Редактировать: включены предложения в комментариях.
Понять, как использовать контекст. Обычно селектор jQuery будет искать весь документ:
// This will search whole doc for elements with class myClass
$('.myClass');
Но вы можете ускорить процесс поиска в контексте:
var ct = $('#myContainer');
// This will search for elements with class myClass within the myContainer child elements
$('.myClass', ct);
Не используйте голые селекторы классов, как это:
$('.button').click(function() { /* do something */ });
В конце концов, мы посмотрим на каждый элемент, чтобы увидеть, есть ли у него класс "кнопки".
Вместо этого вы можете помочь, например:
$('span.button').click(function() { /* do something */ });
$('#userform .button').click(function() { /* do something */ });
Я узнал об этом в прошлом году из блога Ребекки Мерфи.
Обновление - этот ответ был дан более 2 лет назад и не подходит для текущей версии jQuery. Один из комментариев включает в себя тест, чтобы доказать это. Существует также обновленная версия теста, которая включает версию jQuery на момент ответа.
Попробуйте разделить анонимные функции, чтобы вы могли использовать их повторно.
//Avoid
$('#div').click( function(){
//do something
});
//Do do
function divClickFn (){
//do something
}
$('#div').click( divClickFn );
При использовании $.ajax
функция для запросов Ajax к серверу, вы должны избегать использования complete
событие для обработки данных ответа. Он сработает независимо от того, был ли запрос успешным или нет.
Скорее, чем complete
использовать success
,
Смотрите Ajax Events в документации.
- Избегайте злоупотребления готовым документом.
- Держите документ готовым только для инициализации кода.
- Всегда извлекайте функции вне документа, чтобы их можно было использовать повторно.
Я видел сотни строк кода внутри инструкции doc ready. Уродливый, нечитаемый и невозможно поддерживать.
Если вы связываете одно и то же событие несколько раз, оно срабатывает несколько раз. Я обычно всегда хожу unbind('click').bind('click')
просто чтобы быть в безопасности
"Цепные" анимационные события с обратными вызовами.
Предположим, вы хотите анимировать абзац, исчезающий после щелчка по нему. Вы также хотели удалить элемент из DOM впоследствии. Вы можете подумать, что можете просто связать методы:
$("p").click(function(e) {
$(this).fadeOut("slow").remove();
});
В этом примере.remove() будет вызван до завершения.fadeOut(), уничтожая эффект постепенного затухания и просто заставляя элемент исчезать мгновенно. Вместо этого, когда вы хотите запустить команду только после завершения предыдущего, используйте функцию обратного вызова:
$("p").click(function(e){
$(this).fadeOut("slow", function(){
$(this).remove();
});
});
Второй параметр.fadeOut() - это анонимная функция, которая будет запускаться после завершения анимации.fadeOut(). Это способствует постепенному исчезновению и последующему удалению элемента.
Не злоупотребляйте плагинами.
В большинстве случаев вам понадобится только библиотека и, возможно, пользовательский интерфейс. Если вы сохраните это простым, ваш код будет поддерживать в долгосрочной перспективе. Не все плагины поддерживаются и поддерживаются, на самом деле большинство из них не поддерживаются. Если вы можете имитировать функциональность, используя основные элементы, я настоятельно рекомендую это сделать.
Плагины легко вставляются в ваш код, экономят ваше время, но когда вам понадобится что-то дополнительное, не рекомендуется изменять их, так как вы теряете возможные обновления. Время, которое вы сэкономите при запуске, вы потеряете позже, изменив устаревшие плагины.
Выберите плагин, который вы используете с умом. Помимо библиотеки и пользовательского интерфейса, я постоянно использую $.cookie, $.form, $.validate и Thickbox. В остальном я в основном разрабатываю свои собственные плагины.
Ловушка: использование петель вместо селекторов.
Если вы обнаружите, что пытаетесь перебрать элементы DOM для метода jQuery '.each', спросите себя, можно ли использовать селектор для получения элементов.
Больше информации о селекторах jQuery:
http://docs.jquery.com/Selectors
Ловушка: НЕ использовать такой инструмент, как Firebug
Firebug был практически сделан для такой отладки. Если вы собираетесь копаться в DOM с помощью Javascript, вам нужен хороший инструмент, такой как Firebug, чтобы сделать вас более наглядным.
Больше информации о Firebug: http://getfirebug.com/
Другие отличные идеи есть в этом эпизоде Полиморфного Подкаста: (jQuery Secrets with Dave Ward) http://polymorphicpodcast.com/shows/jquery/
Непонимание использования этого идентификатора в правильном контексте. Например:
$( "#first_element").click( function( event)
{
$(this).method( ); //referring to first_element
$(".listOfElements").each( function()
{
$(this).someMethod( ); // here 'this' is not referring first_element anymore.
})
});
И вот один из примеров, как вы можете решить это:
$( "#first_element").click( function( event)
{
$(this).method( ); //referring to first_element
var $that = this;
$(".listOfElements").each( function()
{
$that.someMethod( ); // here 'that' is referring to first_element still.
})
});
Избегайте поиска по всему DOM несколько раз. Это то, что действительно может задержать ваш сценарий.
Плохой:
$(".aclass").this();
$(".aclass").that();
...
Хорошо:
$(".aclass").this().that();
Плохой:
$("#form .text").this();
$("#form .int").that();
$("#form .choice").method();
Хорошо:
$("#form")
.find(".text").this().end()
.find(".int").that().end()
.find(".choice").method();
Всегда кэшируйте $(this) в значимую переменную, особенно в.each()
Как это
$(selector).each(function () {
var eachOf_X_loop = $(this);
})
События
$("selector").html($("another-selector").html());
не клонирует ни одно из событий - вы должны связать их все.
В соответствии с комментарием JP t - clone() перепривязывает события, если вы передаете true.
Подобно тому, что сказал Repo Man, но не совсем.
При разработке ASP.NET winforms я часто
$('<%= Label1.ClientID %>');
забыв знак #. Правильная форма
$('#<%= Label1.ClientID %>');
Избегайте многократного создания одних и тех же объектов jQuery
//Avoid
function someFunc(){
$(this).fadeIn();
$(this).fadeIn();
}
//Cache the obj
function someFunc(){
var $this = $(this).fadeIn();
$this.fadeIn();
}
Я говорю это и для JavaScript, но jQuery, JavaScript НИКОГДА не должен заменять CSS.
Кроме того, убедитесь, что сайт пригоден для использования тем, у кого отключен JavaScript (сегодня это не так актуально, как раньше, но всегда приятно иметь полностью работающий сайт).
Слишком много манипуляций с DOM. Несмотря на то, что методы.html(), .append(), .prepend() и т. Д. Хороши, из-за того, что браузеры отображают и перерисовывают страницы, слишком частое их использование приведет к замедлению работы. Часто лучше создать html в виде строки и включить его в DOM один раз, а не менять DOM несколько раз.
Вместо:
var $parent = $('#parent');
var iterations = 10;
for (var i = 0; i < iterations; i++){
var $div = $('<div class="foo-' + i + '" />');
$parent.append($div);
}
Попробуй это:
var $parent = $('#parent');
var iterations = 10;
var html = '';
for (var i = 0; i < iterations; i++){
html += '<div class="foo-' + i + '"></div>';
}
$parent.append(html);
Или даже это ($wrapper - это недавно созданный элемент, который еще не был внедрен в DOM. Присоединение узлов к этому div обертки не вызывает замедления, и в конце мы добавляем $ wrapper к $parent, используя только одну манипуляцию DOM):
var $parent = $('#parent');
var $wrapper = $('<div class="wrapper" />');
var iterations = 10;
for (var i = 0; i < iterations; i++){
var $div = $('<div class="foo-' + i + '" />');
$wrapper.append($div);
}
$parent.append($wrapper);
Использование ClientID для получения "реального" идентификатора элемента управления в проектах ASP.NET.
jQuery('#<%=myLabel.ClientID%>');
Кроме того, если вы используете jQuery внутри SharePoint, вы должны вызвать jQuery.noConflict().
Передача идентификаторов вместо объектов jQuery в функции:
myFunc = function(id) { // wrong!
var selector = $("#" + id);
selector.doStuff();
}
myFunc("someId");
Передача упакованного набора гораздо более гибкая:
myFunc = function(elements) {
elements.doStuff();
}
myFunc($("#someId")); // or myFunc($(".someClass")); etc.
Использовать строки в стиле аккумулятора
Используя оператор +, в памяти создается новая строка, которой присваивается объединенное значение. Только после этого результат присваивается переменной. Чтобы избежать промежуточной переменной для результата конкатенации, вы можете напрямую присвоить результат с помощью оператора +=. Медленный:
a += 'x' + 'y';
Быстрее:
a += 'x';
a += 'y';
Примитивные операции могут быть быстрее, чем вызовы функций
Рассмотрите возможность использования альтернативных примитивных операций над вызовами функций в циклах и функциях, критичных к производительности. Медленный:
var min = Math.min(a, b);
arr.push(val);
Быстрее:
var min = a < b ? a : b;
arr[arr.length] = val;
Подробнее читайте в разделе "Лучшие практики JavaScript"
Чрезмерное использование цепочки.
Видеть это:
this.buttonNext[n ? 'bind' : 'unbind'](this.options.buttonNextEvent, this.funcNext)[n ? 'removeClass' : 'addClass'](this.className('jcarousel-next-disabled')).attr('disabled', n ? false : true);
Мои два цента)
Обычно работа с jquery означает, что вам не нужно постоянно беспокоиться об актуальных элементах DOM. Вы можете написать что-то вроде этого - $('div.mine').addClass('someClass').bind('click', function(){alert('lalala')})
- и этот код будет выполняться без каких-либо ошибок.
В некоторых случаях это полезно, в некоторых случаях - совсем нет, но это факт, что jquery, как правило, дружественно к пустым совпадениям. Еще, replaceWith
выдаст ошибку, если попытается использовать ее с элементом, который не принадлежит документу. Я нахожу это довольно нелогичным.
Другой ловушкой является, на мой взгляд, порядок узлов, возвращаемых методом prevAll() - $('<div><span class="A"/><span class="B"/><span class="C"/><span class="D"/></div>').find('span:last-child').prevAll()
, На самом деле ничего страшного, но мы должны помнить об этом факте.
Если вы хотите, чтобы пользователи видели html-объекты в своем браузере, используйте "html" вместо "text" для вставки строки Unicode, например:
$('p').html("Your Unicode string")
Если вы планируете использовать Ajax с большим количеством данных, например, 1500 строк таблицы с 20 столбцами, даже не думайте использовать jQuery для вставки этих данных в ваш HTML. Используйте простой JavaScript. jQuery будет слишком медленным на медленных машинах.
Кроме того, половину времени jQuery будет выполнять вещи, которые будут замедлять его работу, например, пытаться анализировать теги скрипта во входящем HTML и устранять причуды браузера. Если вам нужна быстрая скорость вставки, придерживайтесь простого JavaScript.
Использование jQuery в небольшом проекте, который может быть завершен всего несколькими строками обычного JavaScript.
Не понимая привязка события. JavaScript и jQuery работают по-разному.
По многочисленным просьбам, пример:
В jQuery:
$("#someLink").click(function(){//do something});
Без jQuery:
<a id="someLink" href="page.html" onClick="SomeClickFunction(this)">Link</a>
<script type="text/javascript">
SomeClickFunction(item){
//do something
}
</script>
В основном, хуки, необходимые для JavaScript, больше не нужны. Т.е. используйте встроенную разметку (onClick и т. Д.), Потому что вы можете просто использовать идентификаторы и классы, которые разработчик обычно использует для целей CSS.