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;
}

jsbin中的例子

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/

posted @ 2015-08-20 00:16  Ryot  阅读(303)  评论(0编辑  收藏  举报