html标签属性之 `data-*`的问题

问题:
在使用jquery时,通过data()方法获取属性时,如果动态更新了data-*是获取不到的;

// html
<div id="app" data-id="001" data-type="container">示例</div>

// js
let app = $("#app");
console.log("原始:",app.data("id"),app.data("type")); // 001 , container
// 动态改变
app.attr("data-id","002");
app.attr("data-type","container_02");

console.log("更新:",app.data("id"),app.data("type"));     // 001 , container
// 尝试通过 attr() 进行获取,获取到了
console.log(app.attr("data-id"),app.attr("data-type"));    // 002, container_02

分析: 通过查看网页源代码、实际的标签上的属性data-id/data-type均已改变,但是通过data()方法获取到的仍是第一次的值。然后通过使用attr()方法获取到了正确值。
 那就说明Jquery中的data()不是专门用于处理html元素data-*属性的。

Jquery .data()说明
JQuery官网

  • 描述:存储与匹配元素(DOM元素)的任意数据,返回与值匹配的数据值。

    app.data("user",{name:"hello",age:"23"});
    
    console.log(app.data("user").age);           // 23
    
    // 使用原生html元素属性获取不到值
    console.log(app[0].dataset.user);        // undefined
    
    // 设置 JSONString  然后通过解析获取到对象进行操作
    <div data-user='{"name":"hello","age":"23"}'>示例</div>
    console.log(JSON.parse(app[0].dataset.user));
    

    Jquerydata()方法是把属性存储在内存中的,顺便把数值、字符串作为html属性加到元素上;
    原生htmldata-*方法将值作为节点属性挂载到DOM上,所以不能放置对象,可以设置规范的JSONString,获取到之后parse()

  • 分析:使用规则
    官网介绍说,如果值更新将不会影响DOM属性,也就不会获取到更新后的值;推荐属性attr可以获取到
    而且官网也说
    而且通过原生方式dataset是可以去获取到的,说明是方法data()的内部实现问题导致。

    console.log(app[0].dataset.id);         // 002
    
  • 解剖:分析data()实现
    1.4.3之前的早版本中data(obj)会覆盖所有已设置的值;之后则是进行浅复制覆盖。(即注意对象的引用特性)

    data-*会被用来初始数据,之后不会再被访问,这也是为什么更新之后不能获取到改变的值
    在这里插入图片描述
    所以在html元素上设置的标注JSONStringJquery会自动解析,使用data()拿到数据对象。

    github上源码查看,自行查看

    做一个测试:

    1. 第一种测试,先不要调用data()方法 ,更新后再获取
    app.attr("data-id","002");
    app.attr("data-name","app_02");
    app.attr("data-type","container_02");
    
    console.log("更新:",app.data("id"),app.data("name"),app.data("type"));    // 002 app_02 container_02
    
    2. 复制DOM结构重新添加进去
    // 复制DOM结构
    let node = app.clone();
    app.remove();
    $("body").append(node);
    
    console.log("更新:",app.data("id"),app.data("name"),app.data("type")); // 002 app_02 container_02 
    

    也就是Jquery键值对保存了<dom,data>类似WeabkMap数据结构,为了方便存储DOM关联数据,查询提升响应速度。

    结论:要操作DOM元素的属性还是使用attr吧。

原生DOM中的data-*属性
data-*是html 标签的全局属性;

  • 作为DOM元素的属性获取 - getAttribute()
    getAttribute()获取html元素的属性,指定属性不存在则返回Null或空字符串。
    let name = app[0].getAttribute("data-name");
    console.log(name);       // app_02
    
  • 通过HTMLElement.dataset获取data-*值,所有的属性值类型为DOMStringMap
    DOM.dataset.*获取不到时为undefined,类似data-*-*属性获取时驼峰式命名获取值;
    let main = app[0];
    for(key in main.dataset){
        console.log(main.dataset[key]);
    }
    // 直接访问获取某个属性
    console.log(main.dataset.id);
    
  • data-* 作为html属性,既可以使用JS操作,也可用作css属性过滤设置样式;
    ::after等伪类将html属性data-*的值添加到元素;
    div[data-id="001"]{
    	background: red;
    }
    /*也可以将属性的data-* 使用伪类展示在元素中*/
    div::after{
       content:attr(data-id)
    }
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

heroboyluck

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值