【问题标题】:Get list of data-* attributes using javascript / jQuery使用 javascript / jQuery 获取 data-* 属性列表
【发布时间】:2011-05-10 09:04:31
【问题描述】:

给定一个具有零个或多个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() 将返回所需的数据字典。

【问题讨论】:

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

标签: javascript jquery html attributes


【解决方案1】:

实际上,如果您使用 jQuery,从版本 1.4.3 1.4.4 开始(因为下面的 cmets 中提到的错误),data-* 属性通过 @ 支持987654321@:

截至 jQuery 1.4.3 HTML 5 data- 属性会自动 拉入到 jQuery 的数据对象中。

请注意,字符串保持不变 而 JavaScript 值被转换 到它们的相关值(这 包括布尔值、数字、对象、 数组和空)。 data- 属性被拉到第一个 访问数据属性的时间和 然后不再被访问或变异 (然后存储所有数据值 在 jQuery 内部)。

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

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

【讨论】:

  • 不,这是broken in 1.4.3。明确要求至少 1.4.4。
  • 谢谢。这正是我一直在寻找的。我之前用 1.4.3 尝试过,但并没有走得太远。 jsfiddle 演示也有帮助。
  • @Isc:一件非常烦人的事情是 jQuery 试图“反序列化”属性中的值(即from master:!jQuery.isNaN( data ) ? parseFloat( data ) : ...)。我的属性中有产品序列号,例如data-serial="00071134",jQuery 将其转换为数字71134,迫使我恢复到不太优雅的.attr('data-serial')(在您的情况下不是一个选项)。我已经看到关于 SO 的问题在.data() 上表达了类似的挫败感,我会尝试挖掘一个......
  • @CrescentFresh:好点。绝对是我应该注意的事情。在我的解决方案(gist.github.com/701652)中,当 jQuery
  • 请记住,$.data() 还会返回您使用 $.data(key, value) 存储的任何内容。如果您确实想检查某些内容是否作为 data-* 属性实际存储在标记中,则此方法可能不是最佳选择。
【解决方案2】:

还应该提供纯 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" 的值作为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 那样替换 - 字符,但编辑后的答案会。
  • @gilly3 您的 jsfiddle 似乎不起作用。可以看看吗?
  • @Ethan - 已修复。谢谢你让我知道。我一直在使用来自 jsbeautifier.org 的 beautify.js 来漂亮地打印 JSON。显然,该链接现在已断开。但是,因为JSON.stringify() 内置了 JSON 格式,所以这太过分了。
  • @gilly3 太棒了,你的例程非常适合获取所有内容。为给定键添加获取数据以及更新键的修改数据是否容易?如果你能分享,那就太好了。
  • @Ethan - 要获得单个值,请不要想太多:el.getAttribute("data-foo")。我已经更新了我的答案,以展示如何根据对象设置数据属性。
【解决方案3】:

Have a look here:

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

var attributes = element.dataset

var cat = element.dataset.cat

哦,但我也读到了:

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

从 2010 年 5 月开始。


如果你仍然使用 jQuery,你可能想看看customdata 插件。不过我没有这方面的经验。

【讨论】:

  • 也感兴趣,来自 ppk:quirksmode.org/dom/w3c_core.html#attributes
  • 谢谢菲利克斯。我遇到了customdata。不幸的是,它不能满足我的需要——即在事先不知道密钥的情况下获取所有数据。
  • @lsc:文档说$("#my").customdata() 应该给你{method: "delete", remote: "true"}...所以它应该可以工作。
  • 使用单独的 jQuery 插件似乎有点过头了,但是查看 customdata 的源代码帮助我修复了自己的解决方案!将接受您的回答并使用工作功能更新 Q。
  • @lsc:完全没问题,内置解决方案应该始终是 imo 的首选。不幸的是,我不了解最新的 jQuery 开发;)只是想知道为什么有人投票反对我......
【解决方案4】:

如上所述,modern browsers 具有 The 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];});

这样,您可以迭代并使用它们,而无需在元素 like we needed to do before 的所有属性之间进行过滤。

【讨论】:

    【解决方案5】:

    或将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();

    【讨论】:

      【解决方案6】:

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

      var data = element.dataset;
      

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

      【讨论】:

      • IIRC, this.dataset 尚不适用于所有浏览器。然而,有一个 jquery plugin 提供了这个功能。
      【解决方案7】:

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

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

      【讨论】:

        【解决方案8】:

        我使用嵌套的each - 对我来说这是最简单的解决方案(易于控制/更改“您对值的操作 - 在我的示例中,输出数据属性为 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

        【讨论】:

          【解决方案9】:

          查找所有数据属性的一种方法是使用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;
          
          }
          

          【讨论】:

            【解决方案10】:

            您可以使用 $('#prod')[0].dataset 访问数据

            【讨论】:

            • 这个问题的许多答案已经描述了使用dataset 属性。
            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2013-02-17
            • 1970-01-01
            • 2013-12-17
            • 1970-01-01
            • 2020-12-27
            • 1970-01-01
            • 2013-01-09
            相关资源
            最近更新 更多