使用vanilla JavaScript,如何访问jQuery的.data()方法存储的数据?

时间:2014-08-13 12:42:27

标签: javascript jquery

在有人说:

之前
document.querySelector('.myElem').getAttribute('data-*')

不,不是我想要的。 jQuery' s data()具有双重功能。 1)它查询HTML5 data attribute,可以在HTML代码中看到,如下所示:

<div data-role="page" data-last-value="43" data-hidden="true" data-options='{"name":"John"}'></div>
$( "div" ).data( "role" ) === "page";
$( "div" ).data( "lastValue" ) === 43;
$( "div" ).data( "hidden" ) === true;
$( "div" ).data( "options" ).name === "John";

和2)由.data(name, value)设置的隐藏在jQuery内部对象中的对象,文档仅说明&#34;以名称&#39;事件&#39;来保存信息。并且&#39;处理&#39;&#34;但我还没有找到一种方法来访问它们或实际创建它们的方式。

所以,我的问题是,如何从纯JavaScript中访问jQuery数据值?

就这样,它非常清楚......让我更加强调:我不想要data- HTML属性,而是jQuery对象数据

2 个答案:

答案 0 :(得分:11)

jQuery使用名为$.cache的内部对象来存储事件处理程序和数据值。 $.cache是一个简单的字典,可以看起来像这样:

{ 1: { data: { role: "page"}, events: { click: ...} }, 2: { ... }}

密钥都是与某些DOM节点对应的唯一索引。如果您的DOM元素之前被jQuery(附加事件或某些数据)触及,您将看到它具有类似于下面的奇怪属性:

jQuery17108624803440179676: 2

此处jQuery17108624803440179676是jQuery在页面上加载时生成的唯一字符串。此唯一标识符称为“expando”,存储为

$.expando

现在您已经知道如何通过绕过jQuery的数据API来访问单个元素的内部数据......

$.cache[element[$.expando]]

...您可能会问为什么jQuery使用中间对象来存储所有DOM数据和事件。原因是它是一种避免内存泄漏的方法,如果data和事件处理程序直接存储在DOM元素属性中(由于循环引用),就会出现这种情况。

说了这么多,我想强调你应该通过jQuery Data API处理除此之外的节点数据对象,原因很简单,因为它处理幕后所有复杂的东西

答案 1 :(得分:6)

根据评论,您绕过$(...).data的动机似乎是基于它导致性能问题的事实。

我完全同意@meagar的观点,$(...).data不应该足够昂贵而导致瓶颈。但是,如果您不断重新查询并重新包装DOM元素作为jQuery元素(例如$('#someEl').data(...)多次而不是缓存$('#someEl')并执行$someEl.data(...),那么它可能是一个问题。< / p>

请注意,如果您发现自己将大量数据附加到DOM元素,那么您的设计可能会出错。您的数据不应该存在于表示层中,您不必查询DOM或获取对DOM元素的引用来访问您的数据。显然,你可能在某些情况下,但这些不应该是常态。

如果您仍想构建自己的data功能,那么这是一个示例。它没有优化,但你应该明白这个想法:

请注意,WeakMap仅在现代浏览器中可用,但如果没有它,我们就会泄漏内存,除非您提供一种机制来在关联的DOM元素被销毁时销毁缓存属性expenseo对象。 < / p>

JSFIDDLE

JSPERF (测试可能不公平,因为我不确定我的实施是否完成$(...).data

var data = (function () {
    var attributes = new WeakMap();

    return function (el, attr, val) {
        var elAttrs = attributes.get(el),
            isSetOperation = arguments.length > 2;

        if (isSetOperation) {
            if (!elAttrs) attributes.set(el, elAttrs = {});
            elAttrs[attr] = val;
        } else {
            return datasetOrCachedAttrsValue();
        }

        function datasetOrCachedAttrsValue() {
            var attrVal = el.dataset[attr];

            return typeof attrVal !== 'undefined'?
                attrVal: 
                elAttrs && elAttrs[attr];
        }
    };
})();

var div = document.querySelector('div');

console.log(data(div, 'test')); //test
console.log(data(div, 'notexisting')); //undefined
data(div, 'exists', true);
console.log(data(div, 'exists')); //true
  

&#34;会泄漏内存,除非你提供一种破坏机制的机制   缓存&#34; - plalx 。即使使用WeakMap,它仍然会因为同样的原因而泄漏   jQuery可能会导致泄漏。见demo。 - dfsq

这是@dfsq的一个很好的关注点,但是 here's a demo 实际上显示了WeakMap如何在密钥无法访问时允许垃圾收集,而不是jQuery的实现。保持数据(除非使用$().remove我相信)。

随着时间的推移使用探查器和记录堆分配并比较结果。这是我从每个按钮点击6次后得到的结果(每个快照有一种按钮)。我们可以清楚地看到$().data在使用data的自定义WeakMap实施不会泄露时出现泄漏。

  1. 尝试与$().data泄漏。

    enter image description here

  2. 尝试泄漏数据

    enter image description here