รับรายการคุณลักษณะ data- * โดยใช้ javascript / jQuery


150

กำหนดองค์ประกอบ HTML โดยพลการพร้อมคุณสมบัติศูนย์หรือมากกว่าdata-*นั้นเราจะเรียกรายการคู่คีย์ - ค่าสำหรับข้อมูลได้อย่างไร

เช่นได้รับสิ่งนี้:

<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 สำหรับฟังก์ชั่นการใช้งานบางส่วนนั้นดูเหมือนว่าเป็นการ overkill

การมองแหล่งที่มาช่วยให้ฉันแก้ไขรหัสของตัวเอง (และปรับปรุงจาวาสคริปต์ของฉัน)

นี่คือวิธีแก้ปัญหาที่ฉันได้รับ:

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()จะส่งคืนข้อมูล dict ที่ต้องการ


การเพิ่ม "update 2" ให้ระวังข้อมูล jquery () ใช้แคชภายในและข้อมูล (คีย์, ค่า) บางอย่างไม่แพร่กระจายไปยัง DOM ซึ่งอาจทำให้เกิดอาการปวดหัวเป็นจำนวนมาก เนื่องจากข้อมูล jquery 3 () แปลง data data-some-thing = "test" เป็น {someThing: "test"}
ETNyx

คำตอบ:


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
Crescent Fresh

ขอบคุณ นั่นคือสิ่งที่ฉันกำลังมองหา ก่อนหน้านี้ฉันลองด้วย 1.4.3 และไม่ไปไกลมาก การสาธิต jsfiddle ก็ช่วยได้เช่นกัน
Shawn Chin

2
@Isc: สิ่งหนึ่งที่เป็นที่น่ารำคาญมากคือความพยายามของ jQuery ที่ "deserializing" ค่าที่พบในแอตทริบิวต์ (เช่นจากต้นแบบ : !jQuery.isNaN( data ) ? parseFloat( data ) : ...) ฉันมีหมายเลขซีเรียลของผลิตภัณฑ์ในคุณสมบัติของฉันเช่นdata-serial="00071134"jQuery ที่ munged เป็นตัวเลข71134บังคับให้ฉันเปลี่ยนกลับไปใช้ความหรูหราน้อยกว่า.attr('data-serial')(ไม่ใช่ตัวเลือกในกรณีของคุณ) ผมเคยเห็นคำถามเกี่ยวกับเพื่อให้มีความผิดหวังที่คล้ายกันเปล่งเสียง WRT .data()จะพยายามที่จะขุดออก ...
Crescent สด

@CrescentFresh: จุดดี แน่นอนสิ่งที่ฉันควรระวัง ในโซลูชันของฉัน ( gist.github.com/701652 ) ฉันกลับไปที่การแยกวิเคราะห์ node.attributes เมื่อ jQuery <1.4.3; เมื่อคำนึงถึงปัญหานี้บางทีฉันควรจะแยกวิเคราะห์แอตทริบิวต์ด้วยตนเอง
Shawn Chin

7
โปรดทราบว่ายังมีผลตอบแทนอะไรคุณได้เก็บไว้ใช้$.data() $.data(key, value)หากคุณต้องการตรวจสอบว่ามีบางสิ่งถูกจัดเก็บจริงในมาร์กอัปเป็นแอตทริบิวต์ data- * วิธีนี้อาจไม่ใช่ตัวเลือกที่ดีที่สุด
Philip Walton

81

ควรใช้โซลูชัน JavaScript ที่บริสุทธิ์เช่นกันเนื่องจากโซลูชันไม่ยาก:

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

สิ่งนี้ให้อาร์เรย์ของวัตถุคุณลักษณะซึ่งมีnameและvalueคุณสมบัติ:

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

@ gilly3 jsfiddle ของคุณดูเหมือนจะไม่ทำงาน คุณได้ดูไหม
อีธาน

1
@Ethan - แก้ไขแล้ว ขอบคุณสำหรับการให้ฉันรู้ว่า. ฉันใช้ beautify.js จากjsbeautifier.orgเพื่อพิมพ์ JSON เห็นได้ชัดว่าลิงก์นั้นใช้งานไม่ได้ในขณะนี้ แต่นั่นเป็นสิ่งที่เกินความจำเป็นเนื่องจากJSON.stringify()มีการจัดรูปแบบ JSON ในตัว
gilly3

@ gilly3 เยี่ยมยอดกิจวัตรประจำวันของคุณยอดเยี่ยมในการรับทั้งหมด มันจะง่ายกว่าในการเพิ่มข้อมูลการดึงข้อมูลสำหรับคีย์ที่กำหนดรวมถึงการอัปเดตข้อมูลที่แก้ไขสำหรับคีย์ หากคุณสามารถแบ่งปันนั่นก็จะดี
อีธาน

@Ethan - ให้ได้รับค่าเดียวไม่ overthink el.getAttribute("data-foo")มัน ฉันได้อัปเดตคำตอบของฉันเพื่อแสดงว่าคุณสามารถตั้งค่าคุณลักษณะข้อมูลตามวัตถุได้อย่างไร
gilly3

22

ดูที่นี่ :

หากเบราว์เซอร์รองรับ HTML5 JavaScript API คุณควรจะสามารถรับข้อมูลด้วย:

var attributes = element.dataset

หรือ

var cat = element.dataset.cat

โอ้ แต่ฉันก็อ่านด้วย:

น่าเสียดายที่คุณสมบัติของชุดข้อมูลใหม่ยังไม่ได้รับการติดตั้งในเบราว์เซอร์ใด ๆ ดังนั้นในระหว่างนี้จึงเป็นการดีที่สุดที่จะใช้getAttributeและsetAttributeดังที่แสดงไว้ก่อนหน้านี้

ตั้งแต่เดือนพฤษภาคม 2010


ถ้าคุณใช้ jQuery อย่างไรก็ตามคุณอาจต้องการที่จะมีลักษณะที่เป็นCustomDataปลั๊กอิน ฉันไม่มีประสบการณ์กับมัน


นอกจากนี้ที่น่าสนใจจาก ppk: quirksmode.org/dom/w3c_core.html#attributes
Pointy

ขอบคุณเฟลิกซ์ ฉันเจอข้อมูลที่กำหนดเอง น่าเสียดายที่มันไม่ได้ทำในสิ่งที่ฉันต้องการ - คือรับข้อมูลทั้งหมดเนื่องจากไม่ทราบว่ามีกุญแจล่วงหน้า
Shawn Chin

@lsc: เอกสารบอกว่า$("#my").customdata()ควรให้คุณ{method: "delete", remote: "true"}... ดังนั้นจึงควรใช้งานได้
เฟลิกซ์ลิ่ง

การใช้ปลั๊กอิน jQuery แยกต่างหากดูเหมือนว่า overkill แต่การดูแหล่งข้อมูลสำหรับ customdata ช่วยแก้ไขปัญหาของฉันเอง! จะยอมรับคำตอบของคุณและอัปเดต Q ด้วยฟังก์ชั่นการทำงาน
Shawn Chin

1
@lsc: ปรับทั้งหมดสร้างในโซลูชันควรเป็นที่ต้องการ imo น่าเสียดายที่ฉันไม่ทันสมัยกับการพัฒนา jQuery ล่าสุด;) เพียงแค่สงสัยว่าทำไมบางคนโหวตให้ฉันลง ...
Felix Kling

5

ตามที่กล่าวถึงข้างต้นเบราว์เซอร์ที่ทันสมัยมี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];});

และเช่นนี้คุณสามารถย้ำสิ่งเหล่านั้นและใช้มันได้โดยไม่จำเป็นต้องกรองระหว่างคุณลักษณะทั้งหมดขององค์ประกอบเช่นที่เราต้องทำก่อนหน้านี้


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;

ชุดข้อมูลเป็นเครื่องมือที่มีประโยชน์สำหรับรับ data-attribute


IIRC this.datasetไม่สามารถใช้ได้กับเบราว์เซอร์ทั้งหมด อย่างไรก็ตามมีปลั๊กอิน jqueryที่ให้คุณสมบัตินี้
Shawn Chin

1

คุณสามารถทำซ้ำแอตทริบิวต์ข้อมูลเช่นวัตถุอื่น ๆ เพื่อรับคีย์และค่าต่อไปนี้เป็นวิธีดำเนินการกับ$.each:

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

1

ฉันใช้ซ้อนกันแต่ละ - สำหรับฉันนี้เป็นวิธีที่ง่าย (ง่ายต่อการควบคุม / การเปลี่ยนแปลง "สิ่งที่คุณทำด้วยค่า - ในการส่งออกตัวอย่างของฉันข้อมูลแอตทริบิวต์เป็นul-list) (Jquery Code)

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;

}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.