繁体   English   中英

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

[英]Vanilla alternative to jQuery $.data() function: any native javascript alternative?

我通常避免在我的脚本中包含 jQuery 库,但是我最近才发现 jQuery $.data() 的函数能够以键值对、对象甚至函数的形式将数据与任何元素相关联。

根据我的阅读,jQuery 的 $.data() function 还内置了防止与此类做法相关的 memory 泄漏的保护措施,但是为单个 ZC1C125268E6AB7A94D 包含整个 JQ 库是过度的。

有人知道本地替代品吗?

编辑为了让自己更清楚,我不是在寻找本机 function 来检索元素属性。 jQuery 的 $.data() API 远远超出了这种用途,扩展到它能够将 javascript 对象和函数与 jQuery 元素节点相关联。

这篇文章( http://tutorialzine.com/2010/11/jquery-data-method/ )涉及到这种用法,但作为一个例子,我目前正在使用它来将 GSAP 时间线 animation 与 ZA2AC696CFDE6311ICB496668CFDE6319在它创建的 function 之外访问并调用 GSAP Timeline's.reverse() animation function。 例如:

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 object 与元素相关联,这样我就可以在 ZC1C425268E68385D1AB507 外部的 ZC1C425268E68385D1AB507 中访问它的方法原装 scope。

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

/** 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(element).size === 0) {
            this._storage.delete(element);
        }
        return ret;
    }
}

像这样使用它:

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

这比 $.data() 快得多,但仍然比将信息作为属性存储在元素上要慢一些。

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

// store data:
document.body.data = {a:1, b:2};
    
// retrieve data:
console.log(document.body.data);

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

或者您可以简单地在您希望连接到某些数据的每个 DOM 元素上创建一个唯一标识符,并使用 map 将实际数据全局存储在其他地方,例如:

// Naïve global "store" (can also use Map to generate it):
window._data = {
  "abc123": {a:1, b:2} // "abc123" is a random ID assigned to a DOM node
}

// so to automatically generate that, we can enhance all elements:
window._data = {}; // or Map
HTMLElement.prototype.setData = data => {
  // create ID if does not already exists
  this._dataId = this._dataId || generateUID() // implement your own generator

  window._data[this._dataId] = data
}

HTMLElement.prototype.getData = () => window?._data[this._dataId];

// some HTML element with data (`<body>` in this simplified example)
document.body.setData({a:1}) // setter
document.body.getData() // {a:1} (getter)

上面的代码没有经过你的测试


jQuery 不会在元素本身上存储东西,因为它可能导致 memory 泄漏,但是由于您需要它来执行非常特定的任务,因此这将起作用。 在尝试之前,请确保您了解 memory 泄漏的工作原理。

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

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

<div class='info' data-some-data='12' />
// jQuery
var info = $('.info').data('someData'); // 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

请参阅以下通用数据 function。 使用$.data(obj)获取归于任何 object 的所有元数据,使用$.data(obj, key)获取具有归于 object 的给定键的元数据,并使用$.data(obj, key, val)设置object 的给定密钥的元数据。 原生 object 属性的冲突可能存在问题,例如使用'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

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

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

使用 setAttribute 方法:

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

但是您确实应该使用 data 后跟破折号及其属性,例如:

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

并在 JS 中使用 dataset 属性:

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM