原生JS实现data方法

首先需要一段HTML片段:

<div id="test-data"></div>
<p class="test-data-list"></p>
<p class="test-data-list"></p>
<p class="test-data-list"></p>
<p class="test-data-list"></p>

在开发中经常会在DOM上存储一些自定义数据,我们可以通过setAttribute方法来实现。但是当数据为引用类型时,存储后的数据却无效。

var testData = document.querySeletor('#test-data');
testData.setAttribute('baukh', {a:1,b:2})// 执行后DOM节点变化为<div baukh="[object Object]"></div>
testData.getAttribute('baukh'); // => "[object Object]"

可以从上面的代码中看出,存进去的是个Object,取出来的是Object.toString()所产出的字符串。

在JS经典类库-jQuery中存在data方法是通过jQuery.cache的方式进行数据存储,那么还有没有其它方法可以实现?
由于使用场景不同,我想实现的方式是将数据直接存储到DOM节点上,以达到使用时更方便简捷的目的。
那如何存储? 变量testData存储的是通过document.querySeletor('#test-data')获取到的Element,而Element是Object的一个实例。通过[testData instanceof Object]可以进行验证。
那么一切都简易了,即然是Object类型,那么就可以随意的增删自定义属性。

通过在Element的原型上增加data方法来实现DOM扩展

Element.prototype.data = function(key, value){
    var _this = this,
        _dataName = 'testData',  // 存储至DOM上的对象标记, 这里只是测试用名
        _data = {};
    // 未指定参数,返回全部
    if(typeof key === 'undefined' && typeof value === 'undefined'){
        return _this[_dataName];
    }
    // setter
    if(typeof(value) !== 'undefined'){
        // 存储值类型为字符或数字时, 使用attr执行
        var _type = typeof(value);
        if(_type === 'string' || _type === 'number'){
            _this.setAttribute(key, value);
        }
        _data = _this[_dataName] || {};
        _data[key] = value;
        _this[_dataName] = _data;
        return this;
    }
    // getter
    else{
        _data = _this[_dataName] || {};
        return _data[key] || _this.getAttribute(key);
    }
};

这里来试一下:

var testData = document.querySelector('#test-data');
// 字符串类型测试
testData.data('name', 'baukh');
console.log(testData.data('name'));  // => 'baukh'
// 对象类型测试
testData.data('info', {'name': 'baukh', 'age': 27});
console.log(testData.data('info'));  // => Object {name: "baukh", age: 27}

现在还有一个问题, 通过Element.prototype绑定的方法只支持Element类生效,而对NodeList类并无效果.
可以通过下面这些代码进行效果测试:

var testDataList = document.querySelectorAll('.test-data-list');  // 获取的为NodeList 而非 Element
testDataList.data('name', 'baukh');  // Uncaught TypeError: testDataList.data is not a function

这肯定不是想要的结果, 那么NodeList类就需要如下处理:

NodeList.prototype.data = function (key, value) {
    // setter
    if(typeof(value) !== 'undefined'){
        [].forEach.call(this, function (element, index) {
            element.data(key, value);
        });
        return this;
    }
    // getter
    else{
        return this[0].data(key, value); // getter 将返回第一个
    }
};

来测试下NodeList类的data实现:

var testDataList = document.querySelectorAll('.test-data-list');  // 获取的为NodeList 而非 Element
testDataList.data('name', 'baukh');  // Uncaught TypeError: testDataList.data is not a function
// 字符串类型测试
testDataList.data('name', 'baukh');
console.log(testDataList.data('name'));  // => 'baukh'
// 对象类型测试
testDataList.data('info', {'name': 'baukh', 'age': 27});
console.log(testDataList.data('info'));  // => Object {name: "baukh", age: 27}

这样就功能上就完成了
当然也可以将NodeList与Element进行互换, 具体情况具体考虑.

很简单不是吗?

顺带说一下,Array类型的数据,也可以增加自定义属性。

var ar = [1,2,3];
console.log(ar instanceof Object); //true 能添加自定义属性的原因就在这里,Array也是Object的实例。
ar.test1 = {a:1,b:2};
console.log(ar);  //[1, 2, 3, test1: Object]
console.log(ar.test1); //Object {a: 1, b: 2}

@拭目以待

个人站点:www.lovejavascript.com
表格管理插件:gridmanager.lovejavascript.com && github地址
QQ交流群 (452781895):How To Make Love

《野生前端工程师》专辑中所有文章均为@拭目以待 原创,转载请注明出处。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,736评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,167评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,442评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,902评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,302评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,573评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,847评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,562评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,260评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,531评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,021评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,367评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,016评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,068评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,827评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,610评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,514评论 2 269

推荐阅读更多精彩内容