原生JS实现data方法
栏目: JavaScript · 发布时间: 6年前
内容简介:在开发中经常会在DOM上存储一些自定义数据,我们可以通过setAttribute方法来实现。但是当数据为引用类型时,存储后的数据却无效。这里将用原生的JS对data方法进行实现。可以从上面的代码中看出,存进去的是个Object,取出来的是Object.toString()所产出的字符串。在JS经典类库-jQuery中存在data方法是通过jQuery.cache的方式进行数据存储,那么还有没有其它方法可以实现?
在开发中经常会在DOM上存储一些自定义数据,我们可以通过setAttribute方法来实现。但是当数据为引用类型时,存储后的数据却无效。这里将用原生的JS对data方法进行实现。
使用setAttribute:
<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>
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}
解决NodeList存储
现在还有一个问题, 通过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}
随笔一行
这是前端最好的时代, 这也是前端最坏的时代。 众多前端框架满天飞,随着 jQuery 在前端行业的慢慢弱化,总是会有一种斯人远去,何者慰籍的感觉。互勉吧,各位。
另推荐个表格组件 gridManager
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Beautiful Code
Greg Wilson、Andy Oram / O'Reilly Media / 2007-7-6 / GBP 35.99
In this unique work, leading computer scientists discuss how they found unusual, carefully designed solutions to difficult problems. This book lets the reader look over the shoulder of major coding an......一起来看看 《Beautiful Code》 这本书的介绍吧!