使用 data-someAttribute
时,$.data
和 $.attr
的用法有什么区别?
我的理解是 $.data
存储在 jQuery 的 $.cache
中,而不是 DOM 中。因此,如果我想使用 $.cache
进行数据存储,我应该使用 $.data
。如果我想添加 HTML5 数据属性,我应该使用 $.attr("data-attribute", "myCoolValue")
。
attr()
附加对象可能会导致内存泄漏(至少在 IE 中),而使用 data()
是安全的。他在回复中暗示了这一点,尽管他没有明确地站出来说出来。有关 jQuery 文档的更多信息(请参阅“附加说明”):api.jquery.com/attr
data-someAttribute
的数据属性无效;根据规范,只允许使用小写字母。使用大写字符会遇到无数奇怪的问题。
如果要从服务器向 DOM 元素传递数据,则应在元素上设置数据:
<a id="foo" data-foo="bar" href="#">foo!</a>
然后可以在 jQuery 中使用 .data()
访问数据:
console.log( $('#foo').data('foo') );
//outputs "bar"
但是,当您使用数据将数据存储在 jQuery 中的 DOM 节点上时,变量将存储在节点对象上。这是为了容纳复杂的对象和引用,因为将节点元素上的数据存储为属性只会容纳字符串值。
从上面继续我的例子:
$('#foo').data('foo', 'baz');
console.log( $('#foo').attr('data-foo') );
//outputs "bar" as the attribute was never changed
console.log( $('#foo').data('foo') );
//outputs "baz" as the value has been updated on the object
此外,数据属性的命名约定有一点隐藏的“陷阱”:
HTML:
<a id="bar" data-foo-bar-baz="fizz-buzz" href="#">fizz buzz!</a>
JS:
console.log( $('#bar').data('fooBarBaz') );
//outputs "fizz-buzz" as hyphens are automatically camelCase'd
带连字符的键仍然有效:
HTML:
<a id="bar" data-foo-bar-baz="fizz-buzz" href="#">fizz buzz!</a>
JS:
console.log( $('#bar').data('foo-bar-baz') );
//still outputs "fizz-buzz"
但是 .data()
返回的对象将没有连字符键集:
$('#bar').data().fooBarBaz; //works
$('#bar').data()['fooBarBaz']; //works
$('#bar').data()['foo-bar-baz']; //does not work
正是出于这个原因,我建议避免使用 javascript 中的连字符键。
对于 HTML,请继续使用连字符形式。 HTML attributes are supposed to get ASCII-lowercased automatically,因此 <div data-foobar></div>
、<DIV DATA-FOOBAR></DIV>
和 <dIv DaTa-FoObAr></DiV>
应该被视为相同,但为了获得最佳兼容性,应首选小写形式。
如果值与可识别的模式匹配,.data()
方法还将执行一些基本的自动转换:
HTML:
<a id="foo"
href="#"
data-str="bar"
data-bool="true"
data-num="15"
data-json='{"fizz":["buzz"]}'>foo!</a>
JS:
$('#foo').data('str'); //`"bar"`
$('#foo').data('bool'); //`true`
$('#foo').data('num'); //`15`
$('#foo').data('json'); //`{fizz:['buzz']}`
这种自动转换能力对于实例化小部件和插件非常方便:
$('.widget').each(function () {
$(this).widget($(this).data());
//-or-
$(this).widget($(this).data('widget'));
});
如果您绝对必须将原始值作为字符串,那么您需要使用 .attr()
:
HTML:
<a id="foo" href="#" data-color="ABC123"></a>
<a id="bar" href="#" data-color="654321"></a>
JS:
$('#foo').data('color').length; //6
$('#bar').data('color').length; //undefined, length isn't a property of numbers
$('#foo').attr('data-color').length; //6
$('#bar').attr('data-color').length; //6
这是一个人为的例子。对于存储颜色值,我曾经使用数字十六进制表示法(即 0xABC123),但值得注意的是 hex was parsed incorrectly in jQuery versions before 1.7.2,并且从 jQuery 1.8 rc 1 开始不再解析为 Number
。
jQuery 1.8 rc 1 改变了自动转换的行为。以前,任何作为 Number
的有效表示的格式都将被强制转换为 Number
。现在,数字值仅在其表示保持不变时才会自动转换。最好用一个例子来说明这一点。
HTML:
<a id="foo"
href="#"
data-int="1000"
data-decimal="1000.00"
data-scientific="1e3"
data-hex="0x03e8">foo!</a>
JS:
// pre 1.8 post 1.8
$('#foo').data('int'); // 1000 1000
$('#foo').data('decimal'); // 1000 "1000.00"
$('#foo').data('scientific'); // 1000 "1e3"
$('#foo').data('hex'); // 1000 "0x03e8"
如果您计划使用替代数字语法来访问数值,请务必先将值转换为 Number
,例如使用一元 +
运算符。
JS(续):
+$('#foo').data('hex'); // 1000
两者之间的主要区别在于它的存储位置和访问方式。
$.fn.attr
将信息直接存储在元素中的属性中,这些属性在检查时公开可见,也可从元素的原生 API 获得。
$.fn.data
将信息存储在 ridiculously obscure 位置。它位于一个名为 data_user
的封闭局部变量中,它是本地定义的函数 Data 的一个实例。无法从 jQuery 外部直接访问此变量。
包含 attr()
的数据集
可从 $(element).attr('data-name') 访问
可从 element.getAttribute('data-name') 访问,
如果值是数据名称的形式,也可以从 $(element).data(name) 和 element.dataset['name'] 和 element.dataset.name 访问
检查时在元素上可见
不能是对象
包含 .data()
的数据集
只能从 .data(name) 访问
无法从 .attr() 或其他任何地方访问
检查时在元素上不公开可见
可以是对象
您可以使用 data-*
属性嵌入自定义数据。 data-*
属性使我们能够在所有 HTML 元素中嵌入自定义数据属性。
jQuery .data()
方法允许您以一种安全的方式获取/设置任何类型的数据到 DOM 元素,从而避免循环引用,从而避免内存泄漏。
jQuery .attr()
方法仅获取/设置匹配集中第一个元素的属性值。
例子:
<span id="test" title="foo" data-kind="primary">foo</span>
$("#test").attr("title");
$("#test").attr("data-kind");
$("#test").data("kind");
$("#test").data("value", "bar");
.data()
返回的对象将不设置连字符形式,因此$('#bar').data('foo-bar-baz')
可以工作,但$('#bar').data()['foo-bar-baz']
不会。正是出于这个原因,我建议人们避免使用连字符形式。