jQuery .data () не работает, но .attr () работает - PullRequest
95 голосов
/ 03 января 2012

Простите, что не уточнил это. У меня такой странный баг. После загрузки документа я зацикливаю некоторые элементы, которые изначально имеют data-itemname="", и устанавливаю эти значения, используя .attr("data-itemname", "someValue").

Проблема: Когда я позже повторяю цикл по этим элементам, если я делаю elem.data().itemname, я получаю "", но если я делаю elem.attr("data-itemname"), я получаю "someValue". Это похоже на то, что .data() метод получения jQuery получает только те элементы, для которых изначально установлено, что они содержат какое-то значение, но если они изначально пусты, а затем установлены, то .data() не получит значение позже.

Я пытался воссоздать эту ошибку, но не смог.

Редактировать

Я воссоздал ошибку! 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>

Ответы [ 7 ]

184 голосов
/ 03 января 2012

Я столкнулся с подобной «ошибкой» несколько дней назад при работе с .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() вызовы. Используйте один или другой.

9 голосов
/ 17 июля 2017

Это результат недоразумения: data НЕ является средством доступа для data-* атрибутов .И больше, и меньше.

data - это средство доступа к кэшу данных jQuery на элементе.Этот кэш инициализируется из data-* атрибутов, если они есть, но data никогда не записывает в атрибуты, а изменение атрибута не изменяет кэш данных после инициализации:

const div = $("[data-example]");
console.log('div.data("example"):', div.data("example"));
console.log('div.attr("data-example"):', div.attr("data-example"));
console.log('Using div.data("example", "updated")');
div.data("example", "updated");
console.log('div.data("example"):', div.data("example"));
console.log('div.attr("data-example"):', div.attr("data-example"));
<div data-example="initial value"></div>

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

data также массирует то, что находит, различными способами, угадывая типы данных, делая data("answer") для элемента с data-answer="42" числом, а нестрока или даже синтаксический анализ JSON, если они выглядят как JSON:

console.log(typeof $("[data-answer]").data("answer"));
console.log(typeof $("[data-json]").data("json"));
console.log(typeof $("[data-str]").data("str"));
<div data-answer="42"></div>
<div data-json='{"answer":42}'></div>
<div data-str="example"></div>

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

Если вы хотите использовать атрибуты (как их чтение, так и настройку), используйте attr, а не data.attr является средством доступа к атрибутам.

5 голосов
/ 03 января 2012

Это потому, что имя атрибута data-itemname.Вы не можете использовать - в сокращенной записи obj.attribute (obj.data-itemname будет интерпретироваться как "obj.data минус itemname").

4 голосов
/ 03 января 2012

Почему бы вам просто не использовать .data() везде?

Вы также можете объявить значения по умолчанию встроенными в HTML, что тоже хорошо.

<span data-code="pony">text</span>

и

$("span").data("code") == "pony" // true

если вы хотите изменить его, просто сделайте

$("span").data("code", "not-a-pony");

и удалить его в целом вы можете вызвать

$("span").removeData("code");

вам действительно следует избегать использования .attr("data-*"), я не знаю, почему вы все равно захотите это сделать.

3 голосов
/ 23 июля 2018

.attr("data-itemname", "someValue") изменяет DOM.

.data("itemname", "someValue") изменяет кэш jQuery.

Чтобы это работало в следующем Javascript и, кроме того, в CSS, вы должны установить оба.

theaterA.find(".someLink").attr("data-itemname", "someValue");
theaterA.find(".someLink").data("itemname", "someValue");
1 голос
/ 03 января 2012

Вы должны установить данные, используя .data('itemname', 'someValue');.Использование .attr() для установки атрибутов данных не будет работать: http://jsfiddle.net/ThiefMaster/YHsKx/

Однако вы можете предоставить встроенные значения, используя, например, <div data-key="value"> в разметке.

0 голосов
/ 17 января 2019

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

Я тоже столкнулся с этой проблемой и обнаружил, что проблема, похоже, заключается в форматировании имени атрибута данных .

По моему опыту, вам следует избегать использования дефисов в переменной данных (имя переменной, которое следует после " 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");

Надеюсь, это поможет. Приветствую всех!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...