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

IT技术 javascript jquery html attributes
2021-01-31 05:44:26

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

6个回答

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

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

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

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

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

不,这在 1.4.3 中破坏了明确要求至少 1.4.4。
2021-03-14 05:44:26
请记住,它$.data()还会返回您使用$.data(key, value). 如果您真的想检查某些内容是否实际作为 data-* 属性存储在标记中,则此方法可能不是最佳选择。
2021-03-21 05:44:26
@CrescentFresh:好点。绝对是我应该注意的事情。在我的解决方案 ( gist.github.com/701652 ) 中,当 jQuery<1.4.3 时,我回退到解析 node.attributes ;考虑到这个问题,也许我应该坚持手动解析属性。
2021-04-10 05:44:26
@Isc:一件非常烦人的事情是 jQuery 试图“反序列化”在属性中找到的值(即来自 master : !jQuery.isNaN( data ) ? parseFloat( data ) : ...)。我的属性中有产品序列号,例如data-serial="00071134"which jQuery munged into a number 71134,迫使我恢复到不太优雅的.attr('data-serial')(不是您的情况的选项)。我已经看到关于 SO 的问题表达了类似的挫败感.data(),将尝试找出一个...
2021-04-11 05:44:26
谢谢。这正是我正在寻找的。我之前在 1.4.3 中尝试过,并没有走多远。jsfiddle 演示也有帮助。
2021-04-12 05:44:26

还应该提供纯 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));
@Ethan - 固定。谢谢你让我知道。我一直在使用jsbeautifier.org 中的 beautify.js来漂亮地打印 JSON。显然,该链接现在已断开。但是,由于JSON.stringify()内置了 JSON 格式,所以这太过分了。
2021-03-17 05:44:26
@gilly3 太棒了,你的日常工作非常适合获取所有内容。为给定的键添加获取数据以及更新键的修改数据是否容易?如果你能分享,那就太好了。
2021-03-21 05:44:26
@Ethan - 要获得单个值,请不要想太多: el.getAttribute("data-foo")我已经更新了我的答案,以展示如何基于对象设置数据属性。
2021-03-27 05:44:26
好答案!第一行不会-像 jQuery 那样替换字符,但编辑后的答案会替换
2021-04-03 05:44:26
@gilly3 您的 jsfiddle 似乎不起作用。你能看看吗?
2021-04-10 05:44:26

看看这里

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

var attributes = element.dataset

或者

var cat = element.dataset.cat

哦,但我也读到:

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

这是从 2010 年 5 月开始的。


如果您无论如何都使用 jQuery,您可能需要查看customdata插件。我没有这方面的经验。

@lsc:完全没问题,内置解决方案应该始终是 imo 的首选。不幸的是,我没有跟上最新的 jQuery 开发;) 只是想知道为什么有人投票给我拒绝...
2021-03-15 05:44:26
2021-03-17 05:44:26
谢谢菲利克斯。我遇到了自定义数据。不幸的是,它没有做我需要的——即获取所有数据,因为事先不知道密钥。
2021-03-24 05:44:26
@lsc:文档说$("#my").customdata()应该给你{method: "delete", remote: "true"}......所以它应该可以工作。
2021-03-29 05:44:26
使用单独的 jQuery 插件似乎有点矫枉过正,但查看 customdata 的来源帮助我修复了自己的解决方案!将接受您的答案并使用工作功能更新 Q。
2021-04-12 05:44:26

如上所述,现代浏览器具有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];});

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

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