jQuery .prop() 返回 undefined,而 .attr() 对于 data-* 的属性却能正常工作

8

我只是想从两个元素中获取一些属性。从input元素中获取value属性可以按预期工作。问题在于从button元素中获取data-detail属性。使用.prop()会返回undefined,但使用.attr()则按预期工作。

有人能解释一下我所观察到的这种奇怪行为吗?

HTML

<div class="formRow">
    <label for="firstName">First name</label>
    <div class="detailsControlBtns">
        <button id="editFirstName" class="btn ctaBtn greenBtn editBtn">Edit</button>
        <button class="btn ctaBtn greenBtn saveBtn" data-detail="firstName">Save</button>
        <button id="closeFirstName" class="btn ctaBtn greyBtn closeBtn">Close</button>
    </div>
    <input type="text" id="firstName" name="firstName" value="[+firstName+]" readonly>
</div>

JS

$(".saveBtn").on("click", function() {
    var saveBtn = $(this);
    // The following statement yields undefined. When using .attr() it works as expected.
    var detail = saveBtn.prop("data-detail");
    var relevantInput = saveBtn.parent().next();
    // The following statement works as expected.
    var value = relevantInput.prop("value");
    // ...
});

你正在使用哪个版本的jQuery? - LearningPhase
@LearningPhase jquery-1.11.3.min.js - Liran H
2
建议使用数据属性,saveBtn.data("detail")。 - kolodi
@misher 我不知道那个,谢谢 - 它确实像预期的那样工作。 - Liran H
@LearningPhase,我的data-detail不被视为属性吗?如果不是,为什么呢? - Liran H
1个回答

28

那是因为 HTML 元素上没有 data-detail 属性

这里有一个关于.data().prop().attr()的简要说明:

DOM元素是一个对象,它具有来自DOM方法属性以及渲染HTML属性。其中一些属性通过attributes获取它们的初始值
例如:id -> id,class -> className,title -> title,style -> style等等。

考虑这个元素: <input type="checkbox" checked data-detail="somedata" >

以下操作的结果将是:

$('input').prop('id'); // => " "-empty string, property id exist on the element (defined by DOM) , but is not set.
$('input').attr('id');// => undefined - doesn't exist.


如果您执行以下操作:

$('input').attr('id',"someID");
$('input').prop('id'); // =>  "someID"
$('input').attr('id'); // =>  "someID"

并且:

还有:

$('input').prop('id',"someOtherID");
$('input').prop('id');// =>  "someOtherID"
$('input').attr('id');// =>  "someOtherID"

因此,一些属性和属性值具有1:1映射(更改属性的结果会更改属性值,反之亦然)。
考虑以下内容:<input type="text" data-detail="somedata" value="someValue">
$('input').prop('value'); // =>  "someValue"
$('input').val();         // =>  "someValue"
$('input').attr('value'); // =>  "someValue"

如果你这样做:

$('input').prop('value','newVal');

// or

$('input').val('newVal');

$('input').prop('value'); // => "newVal"    -value of the property
$('input').val();         // => "newVal"    -value of the property
$('input').attr('value'); // => "someValue" -value of the attr didn't change, since in this case it is not 1:1 mapping (change of the prop value doesn't reflect to the attribute value).

使用 .data() 方法的案例

1) 如何获取:

- 请注意,属性名称data-*,而属性值dataset,因此:

<input type="checkbox" data-detail="somedata" > 

 

 $('input')[0].dataset; //=> [object DOMStringMap] { detail: "somedata"}
 $('input')[0].dataset.detail; // => "somedata"
 $('input').prop('dataset'); //=>[object DOMStringMap] { detail: "somedata"}
 $('input').prop('dataset').detail; // => "somedata"
 $('input').data('detail'); // => "somedata"
 $('input').attr('data-detail');  //  => "somedata"

2) 如何设置:

I) $('input').prop('dataset').detail='新数据';

 $('input').prop('dataset');  //=> [object DOMStringMap] { detail: "newData"}
 $('input').prop('dataset').detail; // => "newData"
 $('input').attr('data-detail'); // => "newData"
 $('input').data('detail'); // => "newData"

II) $('input').attr('data-detail','新数据');

 $('input').prop('dataset');  //=> [object DOMStringMap] { detail: "newData"}
 $('input').prop('dataset').detail; // => "newData"
 $('input').attr('data-detail'); // => "newData"
 $('input').data('detail'); // => "newData"

因此,您可以看到这里有1:1映射,属性更改反映在属性上,反之亦然。

但请注意第三种方式:

III) $('input').data('detail','newData');

 $('input').prop('dataset'); // =>  [object DOMStringMap] { detail: "somedata"}
 $('input').prop('dataset').detail; // => "somedata"
 $('input').attr('data-detail'); // => "somedata"
 $('input').data('detail');  // => "newData"    <-----******

那么,这里发生了什么?

$(elem).data(key, value) 不会更改元素的 HTML5 data-* 属性。它在内部将其值存储在 $.cache 中。

因此,如果要获取 data-*,使用 .data() 永远不会出错:

$(".saveBtn").on("click", function() {
    var saveBtn = $(this);
    var detail = saveBtn.data("detail");
    var relevantInput = saveBtn.parent().next();
    var value = relevantInput.prop("value");

});

2
哇!非常感谢您提供如此详细的答案,我受益良多。 - Liran H
1
谢谢,这比API文档更有帮助。 - Arash Ghasemi Rad

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接