HTML data-* VS jQuery data
了解HTML5的都知道html5新添加了data-* 的属性,下面是API文档说明
HTML5 is designed with extensibility in mind for data that should be associated with a particular element but need not have any defined meaning. data-* attributes allow us to store extra information on standard, semantic HTML elements without other hacks such as classList, non-standard attributes, extra properties on DOM, or setUserData.
首先先看下一个例子:
$("#div1").attr("data-userName","ryot");
$("#div2").attr("data-index-number","10");
console.log(document.getElementById('div1').dataset.userName);//undefined
console.log(document.getElementById('div1').dataset.username);//ryot
console.log(document.getElementById('div2').dataset.indexNumber);//10
console.log(document.getElementById('div2').dataset['index-number']);//uundefined
console.log(document.getElementById('div2').dataset.indexNumber + 10);//1010
由此可以看出HTML5的data的用法,首先html会把html节点的key转化为小写,如果多个以-连接的data-的属性
则会按照骆驼命名法则转化,同时值类型不会自动判断(与jQuery中data值可以自动判断类型).
当然在css中也可以使用:
list[data-columns='3'] {
width: 400px;
}
list[data-columns='6'] {
width: 200px;
}
IE 11+ 才支持dataset属性,ie10及以下版本需要通过getAttribute()来访问,这相比于在js中使用
data存储效率要低的多
众所周知,jQuery中也有data可以存储数据,下面是jQuery的官方API解释:
Store arbitrary data associated with the specified element and/or return the value that was set.
大体意思是说:可以存储与特定的DOM元素关联的值,并可以取得设置的值
下面通过两个例子简单分析一下jQuery中data的使用看看跟HTML中的data区别
- 1、下面通过jQuery的data设置值并取值
$("#div1").data("userName","ryot");
$("#div2").data("index-number","10");
console.log($("#div1").data("userName"));//ryot
console.log($("#div1").data("username"));//undefined
console.log($("#div2").data("indexNumber"));//10
console.log($("#div2").data('index-number'));//10
console.log($("#div2").data('indexNumber') + 10);//1010
- 2、下面是通过HTML5的标签data-attribute设置,然后jQuery取值
$("#div1").attr("data-userName","ryot");
$("#div2").attr("data-index-number","10");
console.log($("#div1").data("userName"));//undefined
console.log($("#div1").data("username"));//ryot
console.log($("#div2").data("indexNumber"));//10
console.log($("#div2").data('index-number'));//10
console.log($("#div2").data('indexNumber') + 10);//20
通过上面的例子可以看出jQuery使用data的几个注意的地方:
- 1.jQuery中data的key是“区分大小写的”,只是表面上的而已,实则另有玄机
- 2.jQuery中data的key如果以“-”做链接的话,可以按照骆驼命名法则读取,也可以按照原始默认key
读取 - 3.jQuery中与HTML5标签同时赋予了同样的key时,会以jQuery中读取值优先
虽然通过代码测试可以看出这些特点,但是还是希望从jQuery(Version 2.1.4最新版)的源代码分析下原因:
1.首先是jQuery.data 赋值,源代码如下
data: function( elem, name, data ) {
return data_user.access( elem, name, data );
},
access: function( owner, key, value ) {
var stored;
// In cases where either:
//
// 1. No key was specified
// 2. A string key was specified, but no value provided
//
// Take the "read" path and allow the get method to determine
// which value to return, respectively either:
//
// 1. The entire cache object
// 2. The data stored at the key
//
if ( key === undefined ||
((key && typeof key === "string") && value === undefined) ) {
stored = this.get( owner, key );
return stored !== undefined ?
stored : this.get( owner, jQuery.camelCase(key) );
}
// [*]When the key is not a string, or both a key and value
// are specified, set or extend (existing objects) with either:
//
// 1. An object of properties
// 2. A key and value
//
this.set( owner, key, value );
// Since the "set" path can have two possible entry points
// return the expected data based on which path was taken[*]
return value !== undefined ? value : key;
},
set: function( owner, data, value ) {
var prop,
// There may be an unlock assigned to this node,
// if there is no entry for this "owner", create one inline
// and set the unlock as though an owner entry had always existed
unlock = this.key( owner ),
cache = this.cache[ unlock ];
// Handle: [ owner, key, value ] args
if ( typeof data === "string" ) {
cache[ data ] = value;
// Handle: [ owner, { properties } ] args
} else {
// Fresh assignments by object are shallow copied
if ( jQuery.isEmptyObject( cache ) ) {
jQuery.extend( this.cache[ unlock ], data );
// Otherwise, copy the properties one-by-one to the cache object
} else {
for ( prop in data ) {
cache[ prop ] = data[ prop ];
}
}
}
return cache;
},
通过jQuery的源码可以看出使用jQuery.data赋值时是将key-value与element做关联存储在cache的
缓存对象中。
下面看看如果在jQuery中和Html5 DOM节点中同时设置同样的data值时,jQuery是如何做的。注意看其中的
两行解释:
如果在内部没找到,则会试着去HTML5的标签上找data-* 的值
意思就是说一旦在使用jQuery设置过值,则会读取jQuery中的值,而不会遍历Html5的data-* 标签,所以
使用jQuery存值效率要高很多。
(下面是jQuery源码)
function dataAttr( elem, key, data ) {
var name;
// If nothing was found internally, try to fetch any
// data from the HTML5 data-* attribute
if ( data === undefined && elem.nodeType === 1 ) {
name = "data-" + key.replace( rmultiDash, "-$1" ).toLowerCase();
data = elem.getAttribute( name );
if ( typeof data === "string" ) {
try {
data = data === "true" ? true :
data === "false" ? false :
data === "null" ? null :
// Only convert to a number if it doesn't change the string
+data + "" === data ? +data :
rbrace.test( data ) ? jQuery.parseJSON( data ) :
data;
} catch( e ) {}
// Make sure we set the data so it isn't changed later
data_user.set( elem, key, data );
} else {
data = undefined;
}
}
return data;
}
Only convert to a number if it doesn't change the string
其中的这句也就解释了为什么HTML5标签中的data-* 通过jQuery.data取值是会自动类型匹配了。
最有意思的就是取值了,上面我们知道html5 节点的属性值均会自动改为小写。但是jQuery存储读取
则是以骆驼法则来读取设置值的:
简单来说就是
:$("#div1").data("userName","mike");
等同于
$("#div1").data("user-name","mike");
所以在取值的时候两种方式取得值为一样的,这就是所谓看似区分大小写的真面目。
(下面是jQuery源码)
// Convert dashed to camelCase; used by the css and data modules
// Support: IE9-11+
// Microsoft forgot to hump their vendor prefix (#9572)
camelCase: function( string ) {
return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase );
},
nodeName: function( elem, name ) {
return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase();
},
以上如有错误的地方,欢迎批评指正。
已收藏到github中 http://ryotlee.github.io/blog/2015/10/21/HTML data-* VS jQuery data/