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");

Я надеюсь, что это помогает. Приветствую всех!