使用javascript/jQuery获取data-*属性列表

Sha*_*hin 145 javascript jquery html5 attributes

给定具有零个或多个data-*属性的任意HTML元素,如何检索数据的键值对列表.

如上:

<div id='prod' data-id='10' data-cat='toy' data-cid='42'>blah</div>
Run Code Online (Sandbox Code Playgroud)

我希望能够以编程方式检索此:

{ "id":10, "cat":"toy", "cid":42 }
Run Code Online (Sandbox Code Playgroud)

使用jQuery(v1.4.3),$.data()如果事先知道密钥,则使用单个数据位是很简单的,但是如何使用任意数据集来完成这一操作并不明显.

我正在寻找一个'简单'的jQuery解决方案,如果存在,但不会介意低级别的方法.我试图解析,$('#prod').attributes但我缺乏javascript-fu让我失望.

更新

customdata做我需要的.但是,包括一个jQuery插件只是为了它的一小部分功能似乎是一种矫枉过正.

眼球的源代码帮助我修复了自己的代码(并改进了我的javascript-fu).

这是我提出的解决方案:

function getDataAttributes(node) {
    var d = {}, 
        re_dataAttr = /^data\-(.+)$/;

    $.each(node.get(0).attributes, function(index, attr) {
        if (re_dataAttr.test(attr.nodeName)) {
            var key = attr.nodeName.match(re_dataAttr)[1];
            d[key] = attr.nodeValue;
        }
    });

    return d;
}
Run Code Online (Sandbox Code Playgroud)

更新2

正如在接受的答案中所证明的那样,使用jQuery(> = 1.4.4)解决方案是微不足道的.$('#prod').data()将返回所需的数据字典.

Yi *_*ang 94

实际上,如果您正在使用jQuery,那么从版本开始 1.4.31.4.4(由于下面评论中提到的错误),data-*通过以下方式支持属性.data():

从jQuery 1.4.3开始,HTML 5 data- 属性将自动引入jQuery的数据对象.

请注意,当JavaScript值转换为其关联值(包括布尔值,数字,对象,数组和null)时,字符串保持不变.的data- 属性在第一次拉动数据属性被访问,然后不再访问或突变的(所有数据值然后被存储在内部的jQuery).

jQuery.fn.data函数将data-对象内的所有属性作为键值对返回,其中键是后面的属性名称的一部分,data-值是按照上述规则转换后该属性的值.

我还创建了一个简单的演示,如果这不能说服你:http://jsfiddle.net/yijiang/WVfSg/

  • 请记住,`$ .data()`还会返回使用`$ .data(key,value)`存储的任何内容.如果您确实想要检查某些内容是否实际存储在标记中作为data-*属性,则此方法可能不是最佳选择. (7认同)
  • 不,这是[在1.4.3中打破](http://bugs.jquery.com/ticket/7222).明确要求至少1.4.4. (3认同)
  • @Isc:一件非常烦人的事情是jQuery尝试"反序列化"属性中的值(即[来自master](https://github.com/jquery/jquery/commit/8a5df39045292397a06d08b4fab2ad29819b5d44/):`!jQuery .isNaN(data)?parseFloat(data):...`).我的属性中有产品序列号,例如`data-serial ="00071134"`jQuery被输入一个数字`71134`,迫使我恢复到不太优雅的`.attr('data-serial')`(不是在你的情况下的一个选项).我已经看到SO上的问题表达了类似的挫折,`.data()`,会试着挖出一个...... (2认同)

gil*_*ly3 78

应该提供纯JavaScript解决方案,因为解决方案并不困难:

var a = [].filter.call(el.attributes, function(at) { return /^data-/.test(at.name); });
Run Code Online (Sandbox Code Playgroud)

这给出了属性对象,其具有的阵列namevalue属性:

if (a.length) {
    var firstAttributeName = a[0].name;
    var firstAttributeValue = a[0].value;
}
Run Code Online (Sandbox Code Playgroud)

编辑:为了更进一步,您可以通过迭代属性并填充数据对象来获取字典:

var data = {};
[].forEach.call(el.attributes, function(attr) {
    if (/^data-/.test(attr.name)) {
        var camelCaseName = attr.name.substr(5).replace(/-(.)/g, function ($0, $1) {
            return $1.toUpperCase();
        });
        data[camelCaseName] = attr.value;
    }
});
Run Code Online (Sandbox Code Playgroud)

然后,您可以访问,例如,data-my-value="2"as 的值data.myValue;

jsfiddle.net/3KFYf/33

编辑:如果要以编程方式从对象设置元素的数据属性,您可以:

Object.keys(data).forEach(function(key) {
    var attrName = "data-" + key.replace(/[A-Z]/g, function($0) {
        return "-" + $0.toLowerCase();
    });
    el.setAttribute(attrName, data[key]);
});
Run Code Online (Sandbox Code Playgroud)

jsfiddle.net/3KFYf/34

编辑:如果你使用babel或TypeScript,或只编码es6浏览器,这是一个使用es6箭头函数的好地方,并稍微缩短代码:

var a = [].filter.call(el.attributes, at => /^data-/.test(at.name));
Run Code Online (Sandbox Code Playgroud)


Fel*_*ing 21

看看这里:

如果浏览器还支持HTML5 JavaScript API,您应该能够获取数据:

var attributes = element.dataset
Run Code Online (Sandbox Code Playgroud)

要么

var cat = element.dataset.cat
Run Code Online (Sandbox Code Playgroud)

哦,但我也读过:

遗憾的是,新的数据集属性尚未在任何浏览器中实现,因此在此期间最好使用getAttribute并且setAttribute如前所述.

从2010年5月开始.


如果你还是使用jQuery,你可能想看一下customdata插件.我虽然没有经验.


Ser*_*gio 5

如上所述,现代浏览器具有HTMLElement.dataset API.
该API为您提供了DOMStringMap,您data-*只需执行以下操作即可检索属性列表:

var dataset = el.dataset; // as you asked in the question
Run Code Online (Sandbox Code Playgroud)

您还可以使用data-属性的键名来检索数组

var data = Object.keys(el.dataset);
Run Code Online (Sandbox Code Playgroud)

或通过映射其值

Object.keys(el.dataset).map(function(key){ return el.dataset[key];});
// or the ES6 way: Object.keys(el.dataset).map(key=>{ return el.dataset[key];});
Run Code Online (Sandbox Code Playgroud)

并且像这样你可以迭代它们并使用它们,而不需要像我们之前需要的那样在元素的所有属性之间进行过滤.