Пользователь
0,0
рейтинг
5 мая 2011 в 01:14

Разработка → Нововведения в jQuery 1.6

jquery
Совсем недавно (3 мая) был зарелизен jQuery 1.6 и вот что нового появилось в этой js-библиотеке давайте и посмотрим.

Самое «веселое» то, что в новом релизе есть важные изменения, которые несовместимы с предыдущими версиями jQuery. И в результате при переходе на новую версию, вполне возможно, что придётся просматривать и изменять уже существующий код.

Критические изменения


Ниже описаны как раз те изменения, которые могут обрушить код для старых версий.

Доступ к данным в data-атрибутах

Теперь доступ к значениям в этих атрибутах соответствует спецификации W3C HTML5 spec, т.е. ключи надо передавать в camel-case формате.
<div id="div1" data-test-value="123"></div>

Для jQuery 1.5 писали так:
var tv = $('#div1').data('test-value'); // => 123
// или так
var d = $('#div1').data(); // => { "test-value": 123 }
tv = d['test-value']; // => 123

Теперь для jQuery 1.6 надо писать так:
var tv = $('#div1').data('testValue'); // => 123
// или так
var d = $('#div1').data(); // => { "testValue": 123 }
tv = d.testValue; // => 123


.prop(), .removeProp() и .attr()

Также теперь отделены свойства элементов от их атрибутов. Для доступа к атрибутам остался метод .attr(), а для доступа к свойствам элемента, которые могут меняться динамически (значения атрибутов при этом не меняются), теперь нужно делать через .prop(). Самым простым примером может быть поведение <input type="checkbox" />: в 1.5 вызов .attr('checked') возвращал true/false в зависимости от установки флага, в версии же 1.6 .attr('checked') вернёт строковое значение, записанное в атрибут, или undefined, если атрибут отсутствует, а состояние флага нужно получать через .prop('checked').
Поиграться с примерами можно тут: на 1.5 jsfiddle.net/dV27a/1, на 1.6 jsfiddle.net/9zEC9/1
.removeProp() следует использовать с особой осторожностью, т.к. чревато глюками в некоторых браузерах.
Во втором примере можно наблюдать глюк в Google Chrome, и это глюк именно браузера — воспроизводится и без jQuery. Глюк в следующем: если у элемента <input type="checkbox" /> через его js-объектную модель устанавливать свойство checked — то флаг изначально меняется, но если удалить это свойство так delete cb.checked, то после этого изменение свойства не приводит к изменению состояния флага.

В связи с описанным выше, появились некоторые изменения для булевых атрибутов (таких как checked, selected и подобных), теперь .attr('checked', true/false) добавляет или удаляет указанный атрибут (а мы помним, что теперь эта функция работает именно с атрибутом, а не со свойством объекта).

Некритические изменения


Расширяемость .attr() и .val()


В новой версии была добавлена возможность влиять на работу функций .attr() через объект jQuery.attrHooks и на функцию .val() через объект jQuery.valHooks. Например:
jQuery.attrHooks.selected = {
    set: function( elem, value ) {
        if ( value === false ) {
            jQuery.removeAttr(elem, “selected”);
            return value;
        }
    }
};


jQuery.map(Object)


Теперь функция jQuery.map() может принимать первым аргументом не только массив, но и объект, однако возвращать будет массив значений в любом случае.
$.map({ f: 1, s: 2 }, function(v, k) { return ++v; }); // => [ 2, 3 ]


Зависимое изменение CSS


Разработчики добавили возможность изменения css-свойств элементов функцией .css() в зависимости от их значения с помощью инструкций "+=" и "-=", как это сделано в .animate().
$("#item").css("left", "+=10px");


Deferred-объекты


Были внесены улучшения и в deferred-объекты, которые добавлены в 1.5 (тем, кто про них ещё не знает, советую почитать jQuery Deferred Object (подробное описание))

deferred.always()

Когда нужно, чтобы некоторый обработчик вызывался при любом исходе раньше приходилось писать deferred.then(handler, handler), а теперь можно написать deferred.always(handler)

deferred.pipe()

Это новый метод и решает сразу несколько проблем, во-первых с помощью него можно создавать фильтры значений, передаваемых в обработчики параметрами, во-вторых можно строить цепочки из отложенных-заданий (например, асинхронных запросов — эта тема поднималась в комментариях к моей предыдущей статье и вот разработчики предоставили решение этой проблемы).
Пример фильтра (для deferred.reject — аналогично), во второй обработчик первым и единственным параметром попадает значение, которое вернёт первый обработчик.
var defer = $.Deferred(),
    filtered = defer.pipe(function( value ) {
        return value * 2;
    });
defer.resolve( 5 );
filtered.done(function( value ) {
    alert( "Value is ( 2*5 = ) 10: " + value ); // value = 10
});

Запустить: jsfiddle.net/txzPj

Пример цепочки асинхронных запросов, во второй обработчик будут переданы параметры, с которыми будет завершен второй deferred-объект.
var request = $.ajax( '/echo/json/', { dataType: "json", type: 'post', data: { json: '{ "test": 8 }' }, delay: 3 } ),
    chained = request.pipe(function( data ) {
        console.log(data);
        alert('first response');
        return $.ajax( '/echo/json/', { type: 'post', data: { delay: 3, json: '' + data.test } } );
    });

chained.done(function( data ) {
    console.log(data);
    alert('second response');
});

Запустить: jsfiddle.net/5gfS8

Анимация


Кроме улучшения в самом процессе анимирования, в версии 1.6 можно использовать deferred-объекты, завязанные на анимацию. Нет, метод .animate() (и его сокращения .fadeOut(), slideUp() и пр.) не стали возвращать deferred, вместо этого появилась возможность использовать любой jquery-объект в качестве параметра функции $.when(), и если среди выбранных элементов есть какие-то с анимацией, то полученный deferred-объект будет завершён после завершения всей анимации.
$(".elements").fadeOut();

$.when($(".elements")).done(function(elements) {
    // здесь для всех ".elements" анимация завершена
});


jQuery.holdReady()


Этот метод позволяет приостановить выполнение обработчиков события ready, использоваться он будет преимущественно разработчиками плагинов (по крайней мере, так планируют авторы jQuery).
jQuery.holdReady( true ); // приостановили выполнение обработчиков
// запустили какой-то код, например асинхронный запрос
// и когда наш асинхронный запрос выполнился, можем разрешить выполнение остальных обработчиков
jQuery.holdReady( false );


Селектор ":focus"


Теперь стало совсем просто найти в документе элемент, на котором установлен фокус.

Дополнительные возможности в функциях обхода DOM


В новой версии добавили возможность передавать аргументом в функции .find(), .closest() и .is() ещё и jquery-объекты, наконец-то…



Текст этой статьи — это вольный пересказ blog.jquery.com/2011/05/03/jquery-16-released (не перевод, хотя и очень близко к тексту).
Зайцев Андрей @zandroid
карма
57,0
рейтинг 0,0
Реклама помогает поддерживать и развивать наши сервисы

Подробнее
Спецпроект

Самое читаемое Разработка

Комментарии (46)

  • +4
    Забыли еще одно важное изменение — скорость выполнения .data() наконец-то сопоставима со скоростью выполнения .attr(). При тысячах вызовов разница в скорости была довольно весомой и приходилось использовать второе.
  • +3
    Мде… а я еще с 1.5 не успел наиграться…
  • +1
    Кстати, по непонятным причинам CDN от гугла до сих пор не имеет 1.6 ( docs.jquery.com/Downloading_jQuery и code.google.com/intl/uk-UA/apis/libraries/devguide.html#jquery — только 1.5.2)

    Хотя Micrsoft уже CDN-ят… странно как-то.
    • +1
      главное что это работает.
  • +64
    Хороший топик. Именно так должны выглядеть топики про новый релиз jQuery, а не «Вышел jQuery 1.6»
  • +3
    Капец, как же быстро она развивается!
    • +1
      И это хорошо.
  • +2
    tv = ['test-value'];

    видимо имелось в виду

    tv = d['test-value'];
    • 0
      абсолютно верно, спасибо.
      • 0
        id=«div1» data-test-value=«0»
        видимо имелось ввиду
        id=«div1» data-test-value=«123»
        • +1
          Простите меня, ночь уже была… :)
  • +6
    Разработчики добавили возможность изменения css-свойств элементов функцией .css() в зависимости от их значения с помощью инструкций "+=" и "-="

    Как же я рад! Спасибо!
    • 0
      Эх, еще бы в сам CSS такую фичу! Мечты-мечты…
  • 0
    а есть что то типа visualjquery, но посвежей ?) а то больно хороший ман был
  • 0
    C каждой версией всё лучше и лучше, и нет ощущения «нагроможденности» )
  • +4
    ого, jqapi.com/ уже для 1.6
    Шустро, молодцы.
  • 0
    «ключи надо передавать в camel-case формате» — насколько я знаю camelcase — это записьТакогоФормата, а в примере идет разделение дефисом.
    • +1
      Читайте внимательнее, пример есть и для версии 1.5 — там-дефисом, есть и для 1.6 — тамCamelCase
      • +1
        Простите, был напуган, все верно.
    • +2
      Ну, формально, записьТакогоФормата — это camelBack :)
      CamelCase — это ЗаписьТакогоФормата.
      • +1
        Не согласен. Есть lowerCamelCase & UpperCamelCase.
        • 0
          Понапридумывают терминов…
          • 0
            Термины не новые и давно известные.
        • 0
          встречал то, что второе называется PascalCase
  • 0
    Интересно зачем было ломать старый attr, а не ввести просто новый метод attr2?
    Возможно это проблема авторов плагинов, но вот у меня 7 из 9 сторонних плагинов из нового attr отвалились.
    • +2
      Очень часто авторы библиотек и фреймворков становятся перед выбором: новые костыли для обратной совместимости или изменение интерфейса. Как правило, первый подход сильно усложняет код и в конечном итоге ведет к удорожанию поддержки и снижению эффективности, а второй может вызвать неприятие сообщества. Как правило фреймворки идут по первому пути и в итоге задыхаются под собственной тяжестью, вытесняемые молодыми конкурентами. Второй путь требует определенного мужества и сопряжен с риском. Но я рад, что ребята из jQuery выбрали именно его
    • 0
      Старый attr() работает отлично. Мне лично код для совместимости с новым его поведением править не пришлось. Просто не надо было делать вот так:
      var a = $('input').attr('value');
      var b = $('[type=checkbox]').attr('checked')

      Это мало того что некрасиво, так теперь еще и неправильно.
      • 0
        Вот здесь я, кстати, наврал. Обратите внимание на
        $('.mycheckbox').attr('checked', true);
        $('.mycheckbox').attr('checked', false);

        Не самый красивый код для временной совместимости 1.5 и 1.6
        $('.mycheckbox:not(:checked)').click();
        $('.mycheckbox:checked').click();


        Код работает только в базовых случаях, на практике все может пройти не так гладко.
        • 0
          Для совместимости проще, наверное, работать напрямую со свойствами, а не с атрибутами:
          var a = ($('.mycheckbox')[0] || {}).checked; // чтение
          $('.mycheckbox').each(function() { this.checked = true; }); // запись
          

          По сути, именно так и работает .prop()
  • 0
    Для тех кто не очень глубоко в теме — это сильно страшно, нет?
  • +3
    Не забудьте о найденном неприятном баге — jQuery 1.6 отправляет IE6 в бесконечный цикл. Исправление будет в 1.6.1 в конце недели. Если прямо так уж не терпится выпустить 1.6 в продакшн — ручки в помощь. Мне вот, например, не терпится, поскольку data наконец соответсвует спецификации и ей можно пользоваться.
  • 0
    о. теперь понятно, что изза attr у меня был баг на одном сайте (:
  • 0
    Подскажите где почитать подробнее про data (желательно на русском)?
  • 0
    А вот только что вышел jQuery 1.6.1 RC1
  • 0
    Давайте на чистоту, что-то перемудрили
  • 0
    $("#id INPUT, #id SELECT").attr(«disabled»,""); — не пашет (работало в 1.5 )

    $("#id INPUT, #id SELECT").attr(«disabled»,false); — пашет (работает в 1.6)

    мне кажется это противоречит их нововведениям: «в 1.5 вызов .attr('checked') возвращал true/false в зависимости от установки флага, в версии же 1.6 .attr('checked') вернёт строковое значение, записанное в атрибут»

    а вы как считаете?

    извините, предыдущий коммент сам запостился при вставке строк через (Ctrl + V) удалять или исправлять свои комменты похоже нельзя
    • 0
      Если исходить из того, что было в 1.5 и что стало в 1.6, то может быть и перемудрили, но вот если бы они так делали изначально — то это было бы правильнее, на мой взгляд, чем было в 1.5. Поэтому они внесли нужные изменения, которые да, вызвали проблемы с переходом на сл. версию, но, ИМХО, изменения нужные.
      • 0
        мне кажется вы недопоняли мой пост, в 1.6 они сделали:
        $("#id").attr(«checked»,«checked»)
        а было:
        $("#id").attr(«checked»,true)
        и я согласен, правильно сделали, но зачем менять
  • 0
    … продолжаю (у хабра проблемы с сочетаниями клавишь в ФФ):
    но зачем менять
    $("#id").attr(«disabled»,false);
    когда было
  • 0
    $("#id").attr(«disabled»,""); — это ведь правильней, они же так поступили с «checked», зачем менять на противоположный для «disabled»?
  • 0
    извините за комментарий который получился по кусочкам, хабр реально глючит, пришлось это сообщения сначала набрать в блокноте )))

Только зарегистрированные пользователи могут оставлять комментарии. Войдите, пожалуйста.