JQuery.data() не работает, но .attr() делает
Прости меня за то, что я не был более конкретным. У меня такая странная ошибка. После загрузки doc я зацикливаю некоторые элементы, которые изначально имеют data-itemname=""
, и я устанавливаю эти значения с помощью .attr("data-itemname", "someValue")
.
Проблема. Когда я позже прохожу через эти элементы, если я делаю elem.data().itemname
, я получаю ""
, но если я делаю elem.attr("data-itemname")
, я получаю "someValue"
. Это как jQuery .data()
getter получает только элементы, которые изначально устанавливаются для некоторого значения, но если они изначально пусты и позже установлены, то .data()
не получает значение позже.
Я пытался воссоздать эту ошибку, но не смог.
Edit
Я воссоздал ошибку! http://jsbin.com/ihuhep/edit#javascript,html,live
Кроме того, фрагменты из ссылки выше...
JS:
var theaters = [
{ name: "theater A", theaterId: 5 },
{ name: "theater B", theaterId: 17 }
];
$("#theaters").html(
$("#theaterTmpl").render(theaters)
);
// DOES NOT WORK - .data("name", "val") does NOT set the val
var theaterA = $("[data-theaterid='5']");
theaterA.find(".someLink").data("tofilllater", "theater5link"); // this does NOT set data-tofilllater
$(".someLink[data-tofilllater='theater5link']").html("changed link text"); // never gets changed
// WORKS - .attr("data-name", "val") DOES set val
var theaterB = $("[data-theaterid='17']");
theaterB.find(".someLink").attr("data-tofilllater", "theater17link"); // this does set data-tofilllater
$(".someLink[data-tofilllater='theater17link']").html("changed link text");
HTML:
<body>
<div id="theaters"></div>
</body>
<script id="theaterTmpl" type="text/x-jquery-tmpl">
<div class="theater" data-theaterid="{{=theaterId}}">
<h2>{{=name}}</h2>
<a href="#" class="someLink" data-tofilllater="">need to change this text</a>
</div>
</script>
Ответы
Ответ 1
Я столкнулся с подобной "ошибкой" несколько дней назад при работе с .data()
и .attr('data-name')
для атрибутов данных HTML5.
Поведение, которое вы описываете, не является ошибкой, но по дизайну.
Вызов .data()
является особенным - он не только извлекает атрибуты данных HTML5, но и пытается оценить/проанализировать атрибуты. Таким образом, с атрибутом типа data-myjson='{"hello":"world"}'
при извлечении через .data()
возвращается Object
, а поиск через .attr()
вернет строку. См. пример jsfiddle.
Поскольку .data()
выполняет дополнительную обработку jQuery сохраняет результаты оценки атрибутов в $.cache
- в конце концов, как только атрибут данных был оценен, было бы расточительно переоценивать при каждом вызове .data()
- тем более, что данные переменные могут содержать сложные строки JSON.
Я сказал все, чтобы сказать следующее: После получения атрибута через .data()
любые изменения, сделанные .attr('data-myvar', '')
, не будут видны последующими вызовами .data()
. Проверьте это на jsfiddle.
Чтобы избежать этой проблемы, не смешивайте вызовы .data
и .attr()
. Используйте один или другой.
Ответ 2
Это потому, что имя атрибута data-itemname
. Вы не можете использовать -
в сокращенном обозначении obj.attribute
(obj.data-itemname будет intepreted как "obj.data минус itemname" ).
Ответ 3
Почему бы вам просто не использовать .data()
везде?
Вы также можете объявить значения по умолчанию inline в HTML, что тоже хорошо.
<span data-code="pony">text</span>
и
$("span").data("code") == "pony" // true
если вы хотите изменить его, просто выполните
$("span").data("code", "not-a-pony");
и вообще удалить его, вы можете вызвать
$("span").removeData("code");
вы действительно должны стараться избегать использования .attr("data-*")
, я не знаю, почему вы все равно хотите сделать это.
Ответ 4
Это результат недоразумения: data
НЕ является аксессуаром для атрибутов data-*
, Это и больше, и меньше.
data
является аксессуаром для кеша данных jQuery для элемента. Этот кеш инициализируется из атрибутов data-*
, если они есть, но data
никогда не записывает в атрибуты, а также не меняет атрибут изменения кэша данных после инициализации.
data
также массирует то, что он находит различными способами, угадывая типы данных, делая data("foo")
для элемента с data-foo="1"
числом, а не строкой, или даже разбирать вещи как JSON, если они выглядят правильно:/p >
console.log(typeof $("[data-foo]").data("foo"));
console.log(typeof $("[data-bar]").data("bar"));
<div data-foo="1"></div>
<div data-bar='{"answer":42}'></div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Ответ 5
.attr("data-itemname", "someValue")
изменяет DOM.
.data("itemname", "someValue")
изменяет кэш jQuery.
Чтобы это работало в следующем Javascript и, кроме того, в CSS, вы должны установить оба.
theaterA.find(".someLink").attr("data-itemname", "someValue");
theaterA.find(".someLink").data("itemname", "someValue");
Ответ 6
Вы должны установить данные с помощью .data('itemname', 'someValue');
. Использование .attr()
для установки атрибутов данных не будет работать: http://jsfiddle.net/ThiefMaster/YHsKx/
Однако вы можете предоставить встроенные значения, используя, например, <div data-key="value">
в разметке.
Ответ 7
Я вижу, что это привело к некоторому разделению того, как подходить к настройке атрибута данных.
Я тоже столкнулся с этой проблемой и обнаружил, что проблема заключается в простом форматировании имени атрибута данных.
По моему опыту, вам следует избегать использования дефисов в переменной данных (имя переменной, которое следует после "data-").
Это не сработало для меня:
[Разметка]
<div class="list" id="myElement1" data-item-order="some-value"> .... </div>
[JQuery]
jQuery("#myElement1").data("item-order", "my-new-value");
Но следующее работало просто отлично! :)
(При необходимости я использую подчеркивание вместо дефиса)
[Разметка]
<div class="list" id="myElement1" data-item_order="some-value"> .... </div>
[JQuery]
jQuery("#myElement1").data("item_order", "my-new-value");
Я надеюсь, что это помогает. Приветствую всех!