利用原生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 相关文章推荐
借助script进行Http跨域请求:JSONP实现原理及代码
Mar 19 Javascript
Jquery显示和隐藏元素或设为只读(含Ligerui的控件禁用,实例说明介绍)
Jul 09 Javascript
实例讲解jquery中mouseleave和mouseout的区别
Feb 17 Javascript
Function.prototype.apply()与Function.prototype.call()小结
Apr 27 Javascript
原生JS封装ajax 传json,str,excel文件上传提交表单(推荐)
Jun 21 Javascript
Angular2内置指令NgFor和NgIf详解
Aug 03 Javascript
JavaScript实现多栏目切换效果
Dec 12 Javascript
BootStrap modal实现拖拽功能
Dec 01 Javascript
angular4+百分比进度显示插件用法示例
May 05 Javascript
vue将后台数据时间戳转换成日期格式
Jul 31 Javascript
详解在Vue.js编写更好的v-for循环的6种技巧
Apr 14 Javascript
angular8.5集成TinyMce5的使用和详细配置(推荐)
Nov 16 Javascript
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
建立文件交换功能的脚本(二)
2006/10/09 PHP
解析在PHP中使用mysqli扩展库对mysql的操作
2013/07/03 PHP
PHP编程中的常见漏洞和代码实例
2014/08/06 PHP
php清除和销毁session的方法分析
2015/03/19 PHP
Laravel 5 框架入门(三)
2015/04/09 PHP
PHP中的表达式简述
2016/05/29 PHP
PHP面向对象程序设计之接口的继承定义与用法详解
2018/12/20 PHP
laravel框架分组控制器和分组路由实现方法示例
2020/01/25 PHP
JavaScript Event事件学习第一章 Event介绍
2010/02/07 Javascript
JS时间选择器 兼容IE6,7,8,9
2012/06/26 Javascript
js语法学习之判断一个对象是否为数组
2014/05/13 Javascript
javascript设计模式之中介者模式Mediator
2014/12/30 Javascript
jQuery替换节点用法示例(使用replaceWith方法)
2016/09/08 Javascript
jQuery.Validate表单验证插件的使用示例详解
2017/01/04 Javascript
React Native预设占位placeholder的使用
2017/09/28 Javascript
js中bool值的转换及“&amp;&amp;”、“||”、 “!!”详解
2017/12/21 Javascript
使用webpack打包后的vue项目如何正确运行(express)
2018/10/26 Javascript
微信小程序学习笔记之登录API与获取用户信息操作图文详解
2019/03/29 Javascript
[47:45]Liquid vs OG 2018国际邀请赛小组赛BO2 第二场 8.16
2018/08/17 DOTA
20个常用Python运维库和模块
2018/02/12 Python
利用python修改json文件的value方法
2018/12/31 Python
Tensorflow使用Anaconda、pycharm安装记录
2020/07/29 Python
PyTorch如何搭建一个简单的网络
2020/08/24 Python
解决Pycharm 运行后没有输出的问题
2021/02/05 Python
高级3D打印市场:Gambody
2019/12/26 全球购物
简述数组与指针的区别
2014/01/02 面试题
小型女装店的创业计划书
2014/01/09 职场文书
给老婆的搞笑检讨书
2014/01/12 职场文书
个人委托书怎么写
2014/04/04 职场文书
优秀班主任经验交流材料
2014/06/02 职场文书
湖南省召开党的群众路线教育实践活动总结大会报告
2014/10/21 职场文书
群众路线教育实践活动学习心得体会
2014/10/30 职场文书
2015元旦感言
2015/12/09 职场文书
2016年“12.3”国际残疾人日活动总结
2016/04/01 职场文书
倡议书怎么写?
2019/04/11 职场文书
GoLang中生成UUID唯一标识的实现
2021/05/08 Golang