香草替代jQuery $ .data()函数:任何原生的javascript替代品?

时间:2015-03-23 23:01:29

标签: javascript jquery

我通常避免在我的脚本中包含jQuery库,但是我最近才遇到jQuery $ .data()的函数关联数据的功能,以键值对,对象和放大器的形式。甚至功能,任何元素。

根据我的阅读,jQuery的$ .data()函数还内置了保护措施,可防止与此类实践相关的内存泄漏,但为单个函数包含整个JQ库是过分的。

有没有人知道原生替代品?

修改 为了让自己更清楚,我不是在寻找原生函数来检索元素属性。 jQuery的$ .data()API远远超出了这种用途,扩展到了它关联javascript对象的能力。使用jQuery元素节点的函数。

本文(http://tutorialzine.com/2010/11/jquery-data-method/)触及了这种用法,但作为一个例子,我目前正在使用它将GSAP时间轴动画与一个对象相关联,这样我就可以访问并调用GSAP Timeline的.reverse()动画在创建它的函数之外的函数。例如:

function doAnimation(){
    var element = document.createElement('div'),
        timeline = new TimelineMax({....GSAP related fns...}),
        options = {
            ....
            timeline: timeline
        };
   $(element).data('options', options);
}


function reverseAnimation($element){
    var options = $element.data('options'),
        previouslyCreatedTimeline = options.timeline;

    previouslyCreatedTimeline.reverse();
}

如果您不是GSAP的用户,也许不是最清楚的示例,但实质上,$ .data()方法允许我将javascript对象与元素相关联,以便我可以在函数中访问它的方法超出其原始范围。

6 个答案:

答案 0 :(得分:7)

我已经编写了一个围绕WeakMap和Map的包装器,应该可以完成这项工作。 关于WeakMap的好处是,一旦元素被删除,该值就会变为GarbageCollected。这应该避免内存泄漏。

/** A storage solution aimed at replacing jQuerys data function.
 * Implementation Note: Elements are stored in a (WeakMap)[https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakMap].
 * This makes sure the data is garbage collected when the node is removed.
 */
window.dataStorage = {
    _storage: new WeakMap(),
    put: function (element, key, obj) {
        if (!this._storage.has(element)) {
            this._storage.set(element, new Map());
        }
        this._storage.get(element).set(key, obj);
    },
    get: function (element, key) {
        return this._storage.get(element).get(key);
    },
    has: function (element, key) {
        return this._storage.has(element) && this._storage.get(element).has(key);
    },
    remove: function (element, key) {
        var ret = this._storage.get(element).delete(key);
        if (!this._storage.get(key).size === 0) {
            this._storage.delete(element);
        }
        return ret;
    }
}

像这样使用:

var myElement = document.getElementById("myId");
dataStorage.put(myElement, "myKey", "myValue");

这比$ .data()快得多,但仍比将信息存储为元素的属性慢一点。

答案 1 :(得分:4)

您可以在任何DOM元素上存储任何内容:

// store data:
document.body.data = {a:1, b:2};

// retrieve data:
console.log(document.body.data);

我在这里使用data字作为自定义DOM属性,但它可以是任何尚未使用的单词。

jQuery不会将内容存储在元素本身上,因为它可能会导致内存泄漏,但由于您需要将其用于非常特定的任务,因此这将起作用。在尝试此操作之前,请确保知道内存泄漏的工作原理。

其他答案提到了data HTML属性。这与jQuery data无关。绝对没有,它还要求你解析和字符串化你的数据(如果它不是一个字符串)。

答案 2 :(得分:4)

对于jquery的$ .data(),请使用.dataset

<div class='info' data-some-data='12' />
// jQuery
var info = $('.info').data('some-data'); // 12

// vanilla
const info = document.querySelector('.info').dataset.someData; // 12

来源:

https://www.jamesbaum.co.uk/blether/vanilla-js-equivalent-jquery-find-parent-data-remove-class-empty-append/#data

答案 3 :(得分:2)

请参阅以下通用数据功能。使用$.data(obj)获取归因于任何对象的所有元数据$.data(obj, key)以获取具有归属于对象的给定键的元数据,并$.data(obj, key, val)使用给定键将元数据设置为对象。可能存在本机对象属性冲突的问题,例如使用'toString''hasOwnProperty'键设置某些内容。

window.$ = {
    data: function(obj, key, val) {
        if(!obj) {
            return this._data;
        } else if(!key) {
            if(!(obj in this._data)) {
                return {};
            }
            return this._data[obj];
        } else if(arguments.length < 3) {
            if(!(obj in this._data)) {
                return undefined;
            }
            return this._data[obj][key];
        } else {
            if(!(obj in this._data)) {
                this._data[obj] = {};
            }
            this._data[obj][key] = val;
        }
    },
    _data: {}
};

以下是如何使用它的示例:

$.data(document.body); // Returns {} because no data has been set for this object
$.data(document.body, 'lastUpdate', new Date());//Sets 'lastUpdate' of obj to current time
$.data(document.body, 'lastUpdate'); // Gets previously set time
$.data(document.body); // Gets object of all data, including 'lastUpdate' time
$.data(document.body, 'nonexistant'); // Returns undefined because property was never set
$.data(); // Returns all metadata

答案 4 :(得分:1)

使用setAttribute方法:

document.getElementById('item1').setAttribute('data', "icon: 'base2.gif', url: 'output.htm', target: 'AccessPage', output: '1'");

但是你真的应该使用数据跟随破折号及其属性,例如:

<li ... data-icon="base.gif" ...>

要在JS中使用数据集属性:

document.getElementById('item1').dataset.icon = "base.gif";

答案 5 :(得分:1)

对于简单的键值存储,请使用.dataset,它反映了元素的data-*属性。但它仅限于字符串值,因此您需要序列化复合值(例如,使用JSON)。

要存储对象和函数的引用,我建议使用WeakMap。它会注意避免任何内存泄漏。在不支持此功能的浏览器中,只需将它们存储为html元素的直接属性,但要注意选择无冲突的属性名称。