利用原生JS实现data方法示例代码


Posted in Javascript onMay 28, 2019

前言

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

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对三水点靠木的支持。

Javascript 相关文章推荐
拖动一个HTML元素
Dec 22 Javascript
JavaScript调用客户端的可执行文件(示例代码)
Nov 28 Javascript
jQuery控制的不同方向的滑动(向左、向右滑动等)
Jul 18 Javascript
Jquery $.getJSON 在IE下的缓存问题解决方法
Oct 10 Javascript
JavaScript使用Math.Min返回两个数中较小数的方法
Apr 06 Javascript
javascript实现支持移动设备画廊
Aug 24 Javascript
jQuery滚动加载图片实现原理
Dec 14 Javascript
Node.js Stream ondata触发时机与顺序的探索
Mar 08 Javascript
详解vue更改头像功能实现
Apr 28 Javascript
深入理解 JS 垃圾回收
Jun 03 Javascript
解决vue watch数据的方法被调用了两次的问题
Nov 07 Javascript
vue el-upload上传文件的示例代码
Dec 21 Vue.js
php结合js实现多条件组合查询
May 28 #Javascript
vue实现前台列表数据过滤搜索、分页效果
May 28 #Javascript
js 将线性数据转为树形的示例代码
May 28 #Javascript
React中使用外部样式的3种方式(小结)
May 28 #Javascript
vue实现多条件和模糊搜索功能
May 28 #Javascript
vue实现路由切换改变title功能
May 28 #Javascript
Vue 无限滚动加载指令实现方法
May 28 #Javascript
You might like
20个PHP常用类库小结
2011/09/11 PHP
完整删除ecshop中获取店铺信息的API
2014/12/24 PHP
使用swoole 定时器变更超时未支付订单状态的解决方案
2019/07/24 PHP
jquery 分页控件实现代码
2009/11/30 Javascript
IE6、IE7中获取Button元素的值的bug说明
2011/08/28 Javascript
jQuery移动web开发中的页面初始化与加载事件
2015/12/03 Javascript
浅析函数声明和函数表达式——函数声明的声明提前
2016/05/03 Javascript
浅谈bootstrap源码分析之tab(选项卡)
2016/06/06 Javascript
微信小程序 向左滑动删除功能的实现
2017/03/10 Javascript
原生JS实现N级菜单的代码
2017/05/21 Javascript
基于 webpack2 实现的多入口项目脚手架详解
2017/06/26 Javascript
基于js中document.cookie全面解析
2017/09/14 Javascript
Bootstrap实现的表格合并单元格示例
2018/02/06 Javascript
Nodejs对postgresql基本操作的封装方法
2019/02/20 NodeJs
如何基于vue-cli3.0构建功能完善的移动端架子
2019/04/24 Javascript
vue滚动tab跟随切换效果
2020/06/29 Javascript
详解ES6数组方法find()、findIndex()的总结
2020/05/12 Javascript
axios解决高并发的方法:axios.all()与axios.spread()的操作
2020/11/09 Javascript
原生JavaScript实现轮播图
2021/01/10 Javascript
[02:07]TI9显影之尘系列 - Vici Gaming
2019/08/20 DOTA
Python实现监控程序执行时间并将其写入日志的方法
2015/06/30 Python
Python读取本地文件并解析网页元素的方法
2018/05/21 Python
python使用matplotlib画饼状图
2018/09/25 Python
Django ORM 聚合查询和分组查询实现详解
2019/08/09 Python
pytorch实现用Resnet提取特征并保存为txt文件的方法
2019/08/20 Python
使用matplotlib绘制图例标签中带有公式的图
2019/12/13 Python
对pytorch中x = x.view(x.size(0), -1) 的理解说明
2021/03/03 Python
JAVA和C++区别都有哪些
2015/03/30 面试题
《美丽的公鸡》教学反思
2014/02/25 职场文书
2014年五一活动策划方案
2014/03/15 职场文书
群众路线教育实践活动的心得体会
2014/09/03 职场文书
2015年服务员工作总结
2015/04/08 职场文书
2015年普法依法治理工作总结
2015/05/26 职场文书
关于幸福的感言
2015/08/03 职场文书
勤俭节约主题班会
2015/08/13 职场文书
只需要12页,掌握撰写一流商业计划书的技巧
2019/05/07 职场文书