Javascript / jQuery kullanarak veri- * özniteliklerinin listesini alma


150

Sıfır veya daha fazla data-*özniteliğe sahip rastgele bir HTML öğesi verildiğinde , veriler için anahtar / değer çiftlerinin bir listesi nasıl alınabilir.

Örneğin, bu verilen:

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

Programlı olarak bu almak mümkün olmak istiyorum:

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

$.data()Anahtarlar önceden biliniyorsa , jQuery (v1.4.3) kullanarak , tek tek veri bitlerine erişmek basittir, ancak rastgele veri kümeleriyle bunu nasıl yapabileceğiniz açık değildir.

Ben varsa 'basit' bir jQuery çözüm arıyorum, ama aksi takdirde daha düşük düzeyli bir yaklaşım sakıncası olmaz. Ayrıştırmaya çalışırken bir gitmek vardı $('#prod').attributesama javascript-fu eksikliği beni hayal kırıklığına uğratmak.

Güncelleme

customdata ihtiyacım olanı yapar. Bununla birlikte, işlevselliğinin sadece bir kısmı için bir jQuery eklentisi dahil olmak aşırıya kaçmış gibi görünüyordu.

Kaynağa göz atmak, kendi kodumu düzeltmeme yardımcı oldu (ve javascript-fu'yu geliştirdi).

İşte geldiğim çözüm:

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

güncelleme 2

Kabul edilen cevapta gösterildiği gibi, çözüm jQuery ile önemsizdir (> = 1.4.4). $('#prod').data()gerekli veri kararını döndürür.


Addresing "update 2" jquery verilerinin farkında olun () bazı dahili önbellek kullanın ve veriler (anahtar, değer) DOM'a yayılmaz, bu da çok fazla baş ağrısına neden olabilir. Ayrıca jquery 3 data (), data-some-thing = "test" özniteliğini {someThing: "test"} 'e dönüştürdüğü için
ETNyx

Yanıtlar:


96

Aslında, jQuery ile çalışıyorsanız, sürüm olarak 1.4.31.4.4 (aşağıdaki yorumlarda belirtildiği gibi hata nedeniyle), data-*özellikler şu şekilde desteklenir .data():

JQuery 1.4.3'ten itibaren HTML 5 data- öznitelikleri otomatik olarak jQuery'nin veri nesnesine aktarılacaktır.

JavaScript değerleri ilişkili değerlerine dönüştürülürken dizelerin bozulmadan kaldığına dikkat edin (booleans, sayı, nesne, diziler ve null değerlerini içerir). data- Özellikler artık erişilebilir veya (bütün veri değerleri jQuery dahili olarak saklanır) mutasyona uğratılır sonra veri özellik erişilen ilk kez çekilen ve.

jQuery.fn.dataFonksiyon tüm dönecektirdata- anahtar sonra özellik adının bir parçası olmak üzere, anahtar değer çiftleri olarak, nesnenin içindeki nitelik data-ve yukarıda daha önce belirtildiği gibi aşağıdaki kurallara göre dönüştürülmüş sonra değeri bu özelliğin değerini.

Sizi ikna etmeyen basit bir demo da hazırladım: http://jsfiddle.net/yijiang/WVfSg/


3
Hayır, bu 1.4.3'te kırılmıştır . Asgari 1.4.4 açıkça gereklidir.
Crescent Fresh

Teşekkürler. Tam da aradığım şey buydu. Daha önce 1.4.3 ile denedim ve çok ileri gitmedim. jsfiddle demo da yardımcı oldu.
Shawn Chin

2
@Isc: Çok sinir bozucu bir şey "deserializing" değerde jQuery'nin girişimi özelliğinde bulunan (yani ustadan : !jQuery.isNaN( data ) ? parseFloat( data ) : ...). data-serial="00071134"Özelliğimde jQuery'nin bir sayıya girmesi gibi ürün seri numaraları vardı 71134, beni daha az zarif olana geri döndürmeye zorladı .attr('data-serial')(sizin durumunuzda bir seçenek değil). Ben benzer hayal kırıklıkları wrt dile SO, sorular gördüm .data(), bir kazmaya çalışacağız ...
Crescent Fresh

@CrescentFresh: İyi nokta. Kesinlikle dikkat etmem gereken bir şey. Benim çözümümde ( gist.github.com/701652 ) jQuery <1.4.3; bu sorunu göz önünde bulundurarak, belki sadece özellikleri elle ayrıştırma ile sopa gerekir.
Shawn Chin

7
$.data()Ayrıca, sakladığınız her şeyi döndüren öğelerin bulunduğunu unutmayın $.data(key, value). İşaretlemede gerçekten bir şeyin veri- * özelliği olarak depolanıp depolanmadığını gerçekten kontrol etmek istiyorsanız, bu yöntem en iyi seçim olmayabilir.
Philip Walton

81

Çözüm zor olmadığı için saf bir JavaScript çözümü de sunulmalıdır:

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

Bu özellik nameve valueözelliklere sahip bir dizi öznitelik nesnesi verir :

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

Düzenleme: Bir adım daha ileri gitmek için, öznitelikleri yineleyerek ve bir veri nesnesini doldurarak bir sözlük alabilirsiniz:

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

Daha sonra, örneğin, değerini erişebilir data-my-value="2"olarakdata.myValue ;

jsfiddle.net/3KFYf/33

Düzenleme: Öğenizdeki veri niteliklerini bir nesneden programlı olarak ayarlamak istiyorsanız, şunları yapabilirsiniz:

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

DÜZENLEME: babel veya TypeScript kullanıyorsanız veya yalnızca es6 tarayıcıları için kodlama yapıyorsanız, bu es6 ok işlevlerini kullanmak ve kodu biraz kısaltmak için iyi bir yerdir:

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

İyi cevap! İlk satır, -jQuery gibi karakterin yerini almaz ancak düzenlenen yanıtın yerini alır .
Timo Huovinen

@ gilly3 jsfiddle'ınız çalışmıyor gibi görünüyor. Bir bakabilir misin?
Ethan

1
@Ethan - Sabit. Bilmeme izin verdiğin için teşekkürler. JSON güzel yazdırmak için jsbeautifier.org beautify.js kullanıyordum . Görünüşe göre bu bağlantı şimdi kopmuş. Ancak, JSON.stringify()JSON biçimlendirmesi yerleşik olduğundan beri aşırıya
kaçmıştı

@ gilly3 Harika, rutininiz her şeyi almak için harika. Belirli bir anahtar için getirme verisi eklemek ve anahtar (lar) için değiştirilmiş verileri güncellemek kolay mıdır? Paylaşabiliyorsanız, bu harika olurdu.
Ethan

@Ethan - Tek değer elde için, bunu overthink yoktur: el.getAttribute("data-foo"). Cevabımı, bir nesneye dayalı veri özelliklerini nasıl ayarlayabileceğinizi göstermek için güncelledim.
gilly3

22

Buraya bir göz atın :

Tarayıcı HTML5 JavaScript API'sını da destekliyorsa, verileri aşağıdakilerle alabilmeniz gerekir:

var attributes = element.dataset

veya

var cat = element.dataset.cat

Oh, ama ben de okudum:

Ne yazık ki, yeni veri kümesi özelliği henüz hiçbir tarayıcıda uygulanmadığından, bu arada en iyi şekilde kullanmak getAttributeve setAttributedaha önce gösterildiği gibi.

Mayıs 2010'dan.


Yine de jQuery kullanıyorsanız, customdata eklentisine bir göz atmak isteyebilirsiniz . Bununla ilgili hiçbir deneyimim yok.


Ayrıca ilgi, ppk
Sivri

Teşekkürler Felix. Özel verilere rastlamıştım. Ne yazık ki, ihtiyacım olanı yapmaz - yani tuşları önceden bilinmeyen verilen tüm verileri almak.
Shawn Chin

@lsc: Belgeler bunun $("#my").customdata()size vermesi gerektiğini söylüyor {method: "delete", remote: "true"}... bu yüzden çalışması gerekiyor.
Felix Kling

Ayrı bir jQuery eklentisi kullanmak bir overkill gibi görünüyor, ancak customdata kaynağına bakmak kendi çözümlerimi düzeltmeme yardımcı oldu! Cevabınızı kabul edecek ve Q'yu çalışma fonksiyonu ile güncelleyecektir.
Shawn Chin

1
@lsc: Tamamen iyi, dahili çözümler her zaman imo tercih edilmelidir. Ne yazık ki en son jQuery gelişimi ile güncel değilim;) Sadece birinin neden bana oy verdiğini merak ediyorum ...
Felix Kling

5

Yukarıda belirtildiği gibi modern tarayıcılarda var HTMLElement.dataset API.
Bu API size bir DOMStringMap verir ve data-*basitçe şunları yapan özelliklerin listesini alabilirsiniz :

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

Ayrıca, data-mülkün anahtar adlarını içeren bir diziyi

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

veya değerlerini şu şekilde eşleyin:

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

ve bunun gibi bunları tekrarlayabilir ve daha önce yapmamız gereken gibi öğenin tüm nitelikleri arasında filtreleme yapmaya gerek kalmadan kullanabilirsiniz .


3

veya gilly3jQuery yöntemine mükemmel cevabı dönüştürün :

$.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;
}

Kullanma $('.foo').info():;


2

Verileri veri kümesi öznitelikleri aracılığıyla almalısınız

var data = element.dataset;

veri kümesi , data niteliğini almak için yararlı bir araçtır


IIRC, this.datasethenüz tüm tarayıcılarda çalışmaz. Ancak bu özelliği sağlayan bir jquery eklentisi var.
Shawn Chin

1

Anahtarları ve değerleri almak için herhangi bir nesne gibi veri özniteliklerini tekrarlayabilirsiniz, bunu şu şekilde yapabilirsiniz $.each:

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

1

Ben iç içe kullanmak her - Benim için bu en kolay çözümdür (eğer değerlerle ne kontrol / değişime kolay" - Benim örnek çıktı olduğu gibi veri-niteliklerini ul-list) (jQuery Kodu)

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>

Kod açıklığı: https://codepen.io/ezra_siton/pen/GRgRwNw?editors=1111


0

Tüm veri özelliklerini bulmanın bir yolu kullanmaktır element.attributes. Düğmesini kullanarak .attributes, "data-" dizesini içeren öğeleri filtreleyerek tüm öğe nitelikleri arasında geçiş yapabilirsiniz.

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;

}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.