在开辟中经常会在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