Pull to refresh

Comments 82

А на счет JSON это вы зря, вполне удобно, и jQuery автоматом это преобразует из строки в JSON
Попробую, как наберусь смелости)
Этот подход использует KnockoutJS. Есть свои противники среди сторонников unobstructive подхода
Ну кто классы раньше использовал, а кто писал myattr=«N», что вообщем-то также работало.
Если я не ошибаюсь, $.data не имеет ничего общего с тегами data-*
Хм, я почему то думал что этот метод аттачит данные к дом элементу не при помощи data-* аттрибутов.
Так и есть, но с 1.4.3 jQuery умеет их считывать из атрибутов. В общем то, я писал об этом в статье.
Теперь пришла моя очередь извиняться. Как обычно я был невнимателен.

Да, действительно функция jQuery.data(obj, key, [value]) не знает об атрибутах.

Но вот другая функция, та, о которой я писал в статье, $(selector).data(key, [value]) — прекрасно их запоминает.
>>и если мы изменим значение атрибута, например, через .attr(‘email-id’, 90)
— .attr('data-email-id', 90)
Забыли упомянуть один очень важный момент!
В местах, критичных к скорости, ни в коем случае нельзя использовать $(selector).data(...);. Такая конструкция крайне тормознутая. Лучше всегда использовать data через функцию jQuery.data().

Пример:
jQuery.data(document.body, 'foo', 52);

Пруф (jsperf)
Это как раз ньюансы. Если их перечислить в статье, то вся её суть утонет.
Мне трудно представить задачу когда работа с data станет критичной, ну разве что сортировка таблицы, но и там использовать надо будет лишь get

P.S. Ссылайтесь на последнюю версию документа — jsperf.com/jquery-data-vs-jqueryselection-data/22
Тогда уж надо добавить, что функции jQuery.data нет никакого дела до атрибутов data-*, про которые, собственно, в статье и речь. Она выдаёт значения атрибутов, только если selector.data была вызвана раньше.
Можете уточнить?
$(selector).data('name') берет значение «явного» атрибута data-name либо присвоенного в чере $(selector).data('name','value') значения… что не так?
$.data() и $(selector).data() — разные функции. Первая — низкоуровневая, прописывает свойства; вторая — высокоуровневая, к чтению-записи свойств добавляет взаимодействие с атрибутами data-* (только на чтение, кэшируются при первом обращении). Вторая, соответственно, значительно тормознее первой. Причём, что интересно, по результатам тестов — даже при повторном чтении свойств после кэширования.
Почему $(selector).data() тормознее, чем $.data(), если $(selector).data() вызывает ту же самую функцию jQuery.data внутри себя для нахождения данных?
Если только, что $(selector).data() при отсутствии кешированного атрибута парсит значение этого тега и засовывает его в кеш, а $.data() просто пошлет нафиг при отстутствии элемента в кеше.

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

При повторном вызове $(selector).data() мы вызываем $.data(), тот находит нужный элемент в кеше и никакого парсинга. Откуда «значительно тормознее первой»?
Откуда я знаю? Я сорцы не читал, бенчмарки не запускал. Вон сверху ссылку дали, там смотрите. А я почём купил — потом продал.
Видимо я не очень понятно написал, хотя старался.
.data(name) получит только начальное значение из html атрибута.
Но если мы его изменим через .attr или .prop, то значение .data(name) останется старым.
Не совсем так.

<a href="" id="foo" data-foo="buzz">click</a>


var foo = document.getElementById('foo');

console.log($.data(foo, 'foo'));


> undefined
jQuery.data работает абсолютно с любыми объектами, а не с DOM-элементами.
Внутри jQuery есть некое хранилище, которое хранит сам элемент и все его ключи-значения. Оно никак не связано с data-атрибутами, $().data-функция сама проверяет элемент на data-атрибуты.
Вот для справки аналог:
var store = [];
function getData(obj, key){
 for(var i = 0, l = store.length; i < l; i++){
  if(store[i].obj === obj) return store[i].values[key];
 }
}
function setData(obj, key, val){
 var str = { obj:obj, values:{} }, is = 0;
 for(var i = 0, l = store.length; i < l; i++){
  if(store[i].obj === obj) is = str = store[i].values;
 }
 if(!is) store.push(str);
 store.values[key] = val;
}
Да, я сегодня уже почитал исходники, поэтому и написал такой пример, что никакое начальное значение атрибутов data мы не получаем :) И при загрузке страницы хранилище пусто, пока мы сами туда не запишем что-то с помощью $.data или неявно скопируем атрибут через $().data при чтении.
Какую цель вы преследуете используя два типа записи: «data-email-id, emailId» одновременно? Не исключено (никогда не приходило в голову так делать и не тестировал соответственно) что именно из-за этого вы сталкиваетесь с проблемой: "… Один минус (а может и не минус) — это то, что в data() сохранится только изначальное значение, и если мы изменим значение атрибута (например, через .attr(‘data-email-id’, 90)), то получая .data(‘emailId’) увидим наше старое значение..."

Далее: одно из ключевых преимуществ data атрибутов это нативное: хранение типизированных данных(массивов, объектов и тд) и соответственно json
dev.w3.org/html5/spec/global-attributes.html#embedding-custom-non-visible-data-with-the-data-attributes
«Hyphenated names become camel-cased. For example, data-foo-bar= „“ becomes element.dataset.fooBar.»

«Написанные через дефис имена превращаются в camel-cased. Например, data-foo-bar=»" станет element.dataset.fooBar."

Это для нативного js. Но это же правило работает и в jQuery.

Пример:

console.log($('#superid').data('fooBar')); // выведет 123. До этого разумеется мы ничего не записывали в data('fooBar')
Слушалась строка:

<div id="superid" data-foo-bar="123"></div>
Я храню в обычных аттрибутах.
Например
<div class=«item» item_id=«15»>..
Чем это чревато?
Вроде ничем, кроме ошибки валидации.
Которая при необходимости вроде как обходится своей схемой.
Я тоже так временами делаю, ибо офигенно удобно. Но это это чревато тем что никто не гарантирует что всегда и везде будет стабильно работать, ибо не совсем по стандарту. К примеру разработчик какого-нибудь браузера может взять и придумать свой собственный атрибут, который совпадет по имени.
Для этого существуют пространства имён.
для этого существуют data- атрибуты
… и пространства имён
Что вы имеете ввиду? Пространства имен которые решили взять себе разработчики браузеров? Ну так ничего не мешает кому-нибудь создать свой браузер со своим пространством имен которое совпадет с именем моих атрибутов. Никто не помешает кому-нибудь просто вырезать мои невалидные атрибуты. Я это все как гипотетический пример привел, чем может грозить несоблюдение стандартов.
Я имею ввиду пространства имён XML:
<tag prefix:name="value" />

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

При использовании атрибутов data-* небольшая вероятность конфликтов всё-таки есть. Когда несколько независимых модулей используют одинаковые имена — 2 одинаковых атрибута тег не может иметь.
С пространством имён этого в принципе не может быть, если за каждым модулем будет закреплено своё пространство имён, которое так же может быть изменено в любом месте разметки (xmlns). И с валидацией не будет проблем, нужно только составить DTD.

Собственно, ничего нового нет в атрибутах data-* нет.

Что касается «новых браузеров». Ни один браузер не использует пространства имён, кроме старых версий IE. Они используют префикс xml (это зарезервированный префикс в xhtml), но такие теги вырезаются движком и в DOM их уже нет.
Оно только для xhtml или в html тоже работает?
Работает в каком плане?
Конечно, есть различия между text/html и application/xml+xhtml, но только на уровне DOM.
К примеру, каждый узел тега и атрибута имеет свойства prefix и localName.
В режиме text/html свойство prefix равено null, а localName равен nodeName, т.е. 'prefix:name'.
В режиме application/xml+xhtml, соответственно, всё на своих местах.
Так же в любом режиме доступны методы для работы с такими узлами, например getElementsByTagNameNS.

Старые ишаки официально не поддерживают xhtml (включая mime-type application/xml+xhtml), но поддерживают пространства имён.

Если говорить только о атрибутах, то с ними проблем нет вообще. С тегами не так всё гладко, но решаемо без костылей и ограничений для всех браузеров.
Я просто не разбирался так глубоко в DTD и подобном, практической пользы не видел.
Надо будет почитать, спасибо.
UFO just landed and posted this here
Не совсем. В text/html работает как надо — не распознаются префиксы и всё воспринимается как одно имя тега (или локальное имя, в терминах xhtml).
Соответственно и метод, например, getElementsByTagName возвращает разный набор узлов. Всё в порядке.
В осле, конечно, всё веселее…
UFO just landed and posted this here
Ослиные приколы касаются практически всего, вы ещё не привыкли?
UFO just landed and posted this here
Действительно интересно. Правда ни разу в живую не видел.

Но это XML фитча, вот что думает w3.org по поводу namespaces in html5

я бы опасался этого способа с не XHTML.
Ну да, всё верно, в html не распознаётся отдельно префикс и локальное имя на уровне DOM, но нам этого и не надо.
Если используется DTD XHTML. Проблем нигде не возникает.
Чревато тем, что в дальнейшем в стандартах могут появиться такие атрибуты, которые вы уже используете для своих целей.
Кроме Twitter Bootstrap и jQuery Mobile, уже давно используется в ASP.Net MVC3 для Unobtrusive Client Validation.
Это даже не столько MVC3 сколько jquery.validate и плагин написанный для него MS. То есть использовать можно везде, главное аттрибуты прописать
UFO just landed and posted this here
Да никто и не предлагает использовать для отображения. Почему у вас возникло такое ощущение? Где нужно перефразировать статью?
UFO just landed and posted this here
Необходимость именно в получении номера. Просто это самый простой вариант.
Для начала. Для блоков кода используйте конструкцию <source lang=«javascript»>… код...> (для jQuery) и с lang=«html» для html.
Укажу на несколько неточностей.

>> А если нам нужно добавить еще один класс для каждого элемента?
Можно писать несколько классов через пробел: <div class=«first second third»>

>> Иногда используют атрибут ‘rel’, но его можно использовать только для ссылок, хотя я видел и у других элементов.
Атрибут rel ещё чаще используют у тегов link. А вообще браузеры поддерживают абсолютно кастомные атрибуты, включая работу с ними через getAttribute и setAttribute (именно поэтому старые браузеры поддерживают data-*), просто rel валидный.

>> Она позволяет привязывать данные к DOM-элементам, а не к jQuery объектам.
Функция jQuery.data работает не с DOM-элементами, а с абсолютно любыми объектами.
var obj = {};
$.data(obj, 'key', 'val');
$.data(obj, 'key'); // 'val'

И ещё. Данное замечание в корне неверно, т.к. внутри jQuery-объекта лежит как раз DOM-элемент (или несколько). Его легко можно получить так: $('#element')[0] (соответственно, получит первый элемент). И $().data работает, если не ошибаюсь, именно с $.data.
* Парсер съел начало. Для блоков кода с jQuery юзайте конструкцию:
<source lang="javascript">...код...</source>

Для html поменяйте здесь javascript на html соответственно.
Спасибо за подсказку. Поправил в статье.

1. Да, через пробел, но тогда это значение очень сложно выдрать.

2. В a и link атрибут rel разрешен. Но я видел его и у дивов.
Поддерживают, но это невалидно. И что вы будете делать если браузер вдруг добавит параметр, такой же как у вас, но со своим функционалом?

3. Поправил в статье. Но только $.data() все равно не получает data-* атрибутов.
Про валидность. Для этого и введены префиксы (и не только css, например в хроме у форм есть атрибут -webkit-text-speech). Просто придумываем свой префикс и делаем свой атрибут.
И от этого оно станет валидным? И -webkit-text-speech тоже валидный? Пруф пожалуйста.
Нет, но вряд ли браузеры украдут у вас префикс. Так что бояться аналогичных атрибутов в браузере уже можно не бояться.

P.S. Про классы. В jQuery для проверки существования класса есть hasClass.
Я раньше не парился и писал
<tagname unexistent_attrname="value"></tagname>

и получал значение
$('tagname').attr('unexistent_attrname');

не валидно, но
Лучший валидатор — это браузер

Самизнаетекто
:)
Писал выше.
Будет беда, если браузер вдруг добавит параметр, такой же как у вас, но со своим функционалом.
Отсюда и вся необходимость в валидности. И из-за этого в HTML5 внесли эти атрибуты.
В старых браузерах аттрибуты data-blablabla тоже невалидные, но jQuery с ними работает, браузеру пофиг, можно юзать:)
В старых то ничего и не добавится, а вот в новых — может.
UFO just landed and posted this here
Не понимаю. Статья про `data-*`, а про `element.dataset` ни слова.

element.dataset.foo;

Для совместимости IE6+ эмулируется достаточно тривиально
Не упомянуто что $(selector).data() — вернет объект со всеми data-* свойствами элемента.
Круто, но я не стал бы использовать такой подход, если понадобится массовая агрегация данных. Все же чтение/запись DOM медленнее простого объекта в памяти.
Чтение происходит 1 раз (через $().data), потом сбрасывается в кеш, последующее чтение только из него

Запись в DOM через data в любой вариации вообще не происходит.
Осторожно, не все data-методы работают в Zepto.js.
Вот я тормоз-то, а! Вот буквально на днях надо было передать id объекта, его порядковый номер и порядковый номер родительского элемента. И получается в результате
<div class="printGroup" printgroup="1">
<div class="printItem" printitem="1"></div>
</div>

И ведь мелькала где-то на краю сознания мысль «все уже придумано» — не обратил внимания. Теперь переписывать буду.
>Интересно, кто нибудь пробовал хранить в атрибутах json? :)
В рельсах видел такое использовали.
data это круто, но причина использования «А если нам нужно добавить еще один класс для каждого элемента?» не вполне корректна. Классов у элемента может быть несколько через пробел и в том же jQuery есть удобные средства добавления-удаления-проверки классов.
А как вы получите значение name из классов если будет так: div class=«red big name-vasya»
(кроме регулярки, разумеется).
Просто, это сложнее чем из одного единственного класса вытаскивать.
А, да. Окей. Я в аналогичной ситуации ставил id с номером, но это тоже не очень-то удобно.
В FF $(selector).data() лажает как-то. Часть атрибутов остаются строками, а часть приводит насильно к number.
Sign up to leave a comment.

Articles