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


150

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

例如:

<div id='prod' data-id='10' data-cat='toy' data-cid='42'>blah</div>

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

{ "id":10, "cat":"toy", "cid":42 }

使用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;
}

更新2

如公认的答案所示,该解决方案对于jQuery(> = 1.4.4)而言是微不足道的。$('#prod').data()将返回所需的数据字典。


另外,“更新2”要注意jquery data()使用一些内部缓存,并且data(key,value)不会传播到DOM,这可能会引起很多麻烦。同样由于jquery 3 data()将data-some-thing =“ test”属性转换为{someThing:“ test”}
ETNyx

Answers:


96

实际上,如果您使用的是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/


3
不,这在1.4.3中已被打破。明确要求至少为1.4.4。
新月新鲜

谢谢。那正是我想要的。我以前用1.4.3尝试过,但并没有走的太远。jsfiddle演示也提供了帮助。
肖恩·钦

2
@Isc:一件事情是很烦人的是jQuery的在“反序列化”值尝试在属性中找到(即从主!jQuery.isNaN( data ) ? parseFloat( data ) : ...)。我在属性中有产品序列号,例如data-serial="00071134"哪个jQuery合并成一个数字71134,迫使我恢复到不太优雅的样式.attr('data-serial')(在您的情况下不是一个选择)。我已经看到关于SO的问题曾表达过类似的挫败感.data(),他们将尝试从中挖掘出来……
Crescent Fresh

@CrescentFresh:好点。绝对是我应该注意的事情。在我的解决方案(gist.github.com/701652)中,当jQuery <1.4.3时,我会回到解析node.attributes;考虑到这个问题,也许我应该坚持手动解析属性。
肖恩·钱

7
请记住,它$.data()还会返回您使用所存储的任何内容$.data(key, value)。如果您确实要检查是否确实将某些内容作为data- *属性存储在标记中,则此方法可能不是最佳选择。
菲利普·沃尔顿

81

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

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

这给出了一个属性对象数组,这些对象具有namevalue属性:

if (a.length) {
    var firstAttributeName = a[0].name;
    var firstAttributeValue = a[0].value;
}

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

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

然后,您可以访问例如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]);
});

jsfiddle.net/3KFYf/34

编辑:如果您使用babel或TypeScript,或仅为es6浏览器编码,这是使用es6箭头功能的好地方,并缩短了代码一点:

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

好答案!第一行不会-像jQuery那样替换字符,但编辑后的答案会替换。
Timo Huovinen 2014年

@ gilly3您的jsfiddle似乎不起作用。你可以看看吗?
伊桑(Ethan)

1
@Ethan-固定。谢谢你让我知道。我一直在使用jsbeautifier.org的beautify.js来漂亮地打印JSON。显然该链接现在已断开。但是,这是矫枉过正,因为JSON.stringify()已经JSON格式化内置的。
gilly3

@ gilly3太棒了,您的例行程序非常有用。为给定密钥添加获取数据以及为密钥更新修改后的数据是否容易?如果可以分享,那就太好了。
伊桑(Ethan)

@Ethan-要获取单个值,请不要考虑过多: el.getAttribute("data-foo")。我已经更新了答案,以显示如何根据对象设置数据属性。
gilly3

22

在这里看看

如果浏览器还支持HTML5 JavaScript API,则应该能够通过以下方式获取数据:

var attributes = element.dataset

要么

var cat = element.dataset.cat

哦,但我也读到:

不幸的是,新的数据集属性尚未在任何浏览器中实现,因此最好同时使用getAttributesetAttribute如前所述。

从2010年5月开始。


如果仍然使用jQuery,则可能需要看一下customdata插件。我没有经验。



谢谢菲利克斯。我遇到过customdata。不幸的是,它不能满足我的需要-即在事先不知道密钥的情况下获取所有数据。
肖恩·钱

@lsc:文档说$("#my").customdata()应该可以给您{method: "delete", remote: "true"}...所以它应该可以工作。
Felix Kling

使用单独的jQuery插件似乎有些过头,但是查看customdata的源代码有助于我解决自己的解决方案!将接受您的答案并使用工作功能更新Q。
肖恩·钦

1
@lsc:完全可以,内置解决方案应始终是imo首选。不幸的是,我还没有掌握最新的jQuery开发;)只是想知道为什么有人对我投了反对票...
Felix Kling 2010年

5

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

var dataset = el.dataset; // as you asked in the question

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

var data = Object.keys(el.dataset);

或通过以下方式映射其值

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];});

这样,您就可以迭代并使用它们,而无需像我们之前需要做的那样在元素的所有属性之间进行过滤。


3

或将gilly3极好的答案转换为jQuery方法:

$.fn.info = function () {
    var data = {};
    [].forEach.call(this.get(0).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;
        }
    });
    return data;
}

使用:$('.foo').info();


2

您应该通过数据集属性获取数据

var data = element.dataset;

数据集是获取数据属性的有用工具


IIRC,this.dataset不适用于所有浏览器。但是,有一个提供此功能的jquery插件
肖恩·钱

1

您可以像访问任何其他对象一样遍历数据属性以获取键和值,这是使用以下方法$.each

    $.each($('#myEl').data(), function(key, value) {
        console.log(key);
        console.log(value);
    });

1

我使用嵌套的每个 -对我来说,这是最简单的解决方案(易于控制/更改“对值的处理方式-在我的示例中,输出数据属性为ul-list)(jQuery代码)

var model = $(".model");

var ul = $("<ul>").appendTo("body");

$(model).each(function(index, item) {
  ul.append($(document.createElement("li")).text($(this).text()));
  $.each($(this).data(), function(key, value) {
    ul.append($(document.createElement("strong")).text(key + ": " + value));
    ul.append($(document.createElement("br")));
  }); //inner each
  ul.append($(document.createElement("hr")));
}); // outer each

/*print html*/
var htmlString = $("ul").html();
$("code").text(htmlString);
<script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.17.1/prism.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/prism/1.17.1/themes/prism-okaidia.min.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<h1 id="demo"></h1>

<ul>
  <li class="model" data-price="45$" data-location="Italy" data-id="1234">Model 1</li>
  <li class="model" data-price="75$" data-location="Israel" data-id="4321">Model 2</li> 
  <li class="model" data-price="99$" data-location="France" data-id="1212">Model 3</li> 
</ul>

<pre>
<code class="language-html">
  
</code>
</pre>

<h2>Generate list by code</h2>
<br>

Codepen:https://codepen.io/ezra_siton/pen/GRgRwNw editors = 1111


0

查找所有数据属性的一种方法是使用element.attributes。使用.attributes,您可以遍历所有元素属性,过滤掉包含字符串“ data-”的项目。

let element = document.getElementById("element");

function getDataAttributes(element){
    let elementAttributes = {},
        i = 0;

    while(i < element.attributes.length){
        if(element.attributes[i].name.includes("data-")){
            elementAttributes[element.attributes[i].name] = element.attributes[i].value
        }
        i++;
    }

    return elementAttributes;

}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.