资讯专栏INFORMATION COLUMN

原生JS实现data方法

wenyiweb / 2118人阅读

摘要:在开发中经常会在上存储一些自定义数据,我们可以通过方法来实现。这里将用原生的对方法进行实现。能添加自定义属性的原因就在这里,也是的实例。

在开发中经常会在DOM上存储一些自定义数据,我们可以通过setAttribute方法来实现。但是当数据为引用类型时,存储后的数据却无效。这里将用原生的JS对data方法进行实现。
使用setAttribute:

var testData = document.querySeletor("#test-data");
testData.setAttribute("baukh", {a:1,b:2})// 执行后DOM节点变化为
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

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/109887.html

相关文章

  • 原生App与javascript交互之JSBridge接口原理、设计与实现

    摘要:相关参考中与之间相互调用的实现实现了与相同的机制的对象注入漏洞解决方案存在的意义 前期调研 调研对象:支付宝,微信,云之家 调研文档:Android中JS与Java的极简交互库 SimpleJavaJsBridge 设计需求 阅读类型的业务功能页面需要由前端H5实现,需要做到服务端可控; 页面界面更改减少重新发布新版本的频率; 功能页面部分原型需求无法实现,需要原生功能支持; 对未来...

    Lyux 评论0 收藏0
  • (转)iOS- JSBridge的原理

    摘要:作者心叶时间原理概述简介是代码与代码的通信桥梁。目前的一种统一方案是触发捕获原生分析执行原生调用。另外调用时处理完毕后一定要及时通知进行回调要不然这个回调函数不会自动销毁多了后会引发内存泄漏。 作者:心叶时间:2019-03-25 10:18 原理概述 简介 JSBridge是Native代码与JS代码的通信桥梁。目前的一种统一方案是:H5触发url scheme->Native捕获u...

    txgcwm 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<