5.1 操作属性

在本书前4章里,我们经常使用.addClass().removeClass()方法来示范如何改变页面上元素的外观。虽然我们一般会说这两个方法在操作类属性,但jQuery实际上是在操作DOM中的className属性。换句话说,.addClass()方法创建或增加这个属性,而.removeClass()则删除或缩短该属性。而具备了这两种操作的.toggleClass()方法能够交替地添加和移除类。这样,我们就具有了处理类的一种有效而可靠的方式。这些方法特别有用,因为它们可以在某个类已经存在的情况下不添加该类(例如,不会出现<div class="first first">的情况),也可以正确处理给一个元素应用多个类的情况(比如 <div class="first second">)。

5.1.1 非类属性

有时候,我们还需要操作其他一些属性,比如idreltitle属性。jQuery为此也提供了.attr().revoveAttr()方法。这些方法让修改属性变成了小菜一碟。此外,通过jQuery还可以一次修改多个属性,同我们在第4章中使用.css()方法修改多个CSS属性的方式类似。

比如,我们可一次性修改链接的idreltitle属性。首先来看一看我们例子中的HTML代码:

  1. <h1 id="f-title">Flatland: A Romance of Many Dimensions</h1>
  2. <div id="f-author">by Edwin A. Abbott</div>
  3. <h2>Part 1, Section 3</h2>
  4. <h3 id="f-subtitle">
  5. Concerning the Inhabitants of Flatland
  6. </h3>
  7. <div id="excerpt">an excerpt</div>
  8. <div class="chapter">
  9. <p class="square">Our Professional Men and Gentlemen are
  10. Squares (to which class I myself belong) and Five-Sided
  11. Figures or <a
  12. href="http://en.wikipedia.org/wiki/Pentagon">Pentagons
  13. </a>.
  14. </p>
  15. <p class="nobility hexagon">Next above these come the
  16. Nobility, of whom there are several degrees, beginning at
  17. Six-Sided Figures, or <a
  18. href="http://en.wikipedia.org/wiki/Hexagon">Hexagons</a>,
  19. and from thence rising in the number of their sides till
  20. they receive the honourable title of <a
  21. href="http://en.wikipedia.org/wiki/Polygon">Polygonal</a>,
  22. or many-Sided. Finally when the number of the sides
  23. becomes so numerous, and the sides themselves so small,
  24. that the figure cannot be distinguished from a <a
  25. href="http://en.wikipedia.org/wiki/Circle">circle</a>, he
  26. is included in the Circular or Priestly order; and this is
  27. the highest class of all.
  28. </p>
  29. <p><span class="pull-quote">It is a <span class="drop">Law
  30. of Nature</span> with us that a male child shall have
  31. <strong>one more side</strong> than his father</span>, so
  32. that each generation shall rise (as a rule) one step in
  33. the scale of development and nobility. Thus the son of a
  34. Square is a Pentagon; the son of a Pentagon, a Hexagon;
  35. and so on.
  36. </p>
  37. <!-- . . . code continues . . . -->
  38. </div>

 下载代码示例

如同本书其他HTML、CSS以及JavaScript示例一样,上面的标记只是完整文档的一个片段。如果读者想试一试这些示例,可以从以下地址下载完整的示例代码: Packt Publishing 网站 http://www.packtpub.com/support ,或者本书网站 http://book.learningjquery.com/

对于以上HTML,我们可以循环遍历<div class="chapter">中的每个链接,并逐个为它们添加属性。如果只想为所有链接设置一个公共的属性值,那么在$(document).ready处理程序中通过一行代码即可完成这一操作,如代码清单5-1所示。

代码清单5-1

  1. $(document).ready(function() {
  2. $('div.chapter a').attr({rel: 'external'});
  3. });

.css()方法很相似,.attr()方法也接受一对参数,第一个是属性名,第二个是属性值。不过,更常用的方式还是传入一个包含键值对的对象,如代码清单5-1所示。使用对象可以轻松地扩展,以便一次性地修改多个属性,如代码清单5-2所示。

代码清单5-2

  1. $(document).ready(function() {
  2. $('div.chapter a').attr({
  3. rel: 'external',
  4. title: 'Learn more at Wikipedia'
  5. });
  6. });

值回调

如果我们想让每个匹配的元素都具有相同的一个或多个属性值,那么只要给.attr()传入一个静态的对象即可。不过,更常见的情况是为每个元素添加或修改的属性都必须具有不同的值。例如,对于任何给定的文档,如果要保证JavaScript代码有效,那么每个id属性的值必须唯一。要为每个链接设置唯一的id,可以使用jQuery的.css().each()方法的另一个特性:值回调

值回调其实就是给参数传入一个函数,而不是传入具体的值。这个函数会针对匹配的元素集中的每个元素都调用一次,调用后的返回值将作为属性的值。例如,可以使用值回调来为每个元素生成唯一的id值,参见代码清单5-3。

代码清单5-3

  1. $(document).ready(function() {
  2. $('div.chapter a').attr({
  3. rel: 'external',
  4. title: 'Learn more at Wikipedia',
  5. id: function(index, oldValue) {
  6. return 'wikilink-' + index;
  7. }
  8. });
  9. });

每次触发值回调,都会给它传入两个参数。第一个是一个整数,表示迭代次数,我们在此利用这个值为第一个链接生成的idwikilink-0,为第二个链接生成的idwikilink-1,以此类推。代码清单5-3并没有用到第二个参数,这个参数中保存的是修改之前属性的值。

我们是通过title属性来邀请人们学习维基百科中的术语的。在我们目前为止使用的HTML中,所有链接都指向维基百科。不过,考虑到其他链接,还应该把选择符表达式定义得更具体一些,参见代码清单5-4。

代码清单5-4

  1. $(document).ready(function() {
  2. $('div.chapter a[href*="wikipedia"]').attr({
  3. rel: 'external',
  4. title: 'Learn more at Wikipedia',
  5. id: function(index, oldValue) {
  6. return 'wikilink-' + index;
  7. }
  8. });
  9. });

为了把.attr()方法的使用讲得更透彻,下面演示怎么让这些链接的title属性更具体地包含链接的目标。同样,解决这个问题还是要使用值回调,参见代码清单5-5。

代码清单5-5

  1. $(document).ready(function() {
  2. $('div.chapter a[href*="wikipedia"]').attr({
  3. rel: 'external',
  4. title: function() {
  5. return 'Learn more about ' + $(this).text() + ' at Wikipedia.';
  6. },
  7. id: function(index, oldValue) {
  8. return 'wikilink-' + index;
  9. }
  10. });
  11. });

这一次我们利用了值回调的上下文。就像在事件处理程序中一样,在值回调函数中,this关键字指向每次调用回调时正在操作的那个DOM元素。在此,我们把这个元素封装为jQuery对象,这样就可通过.text()方法(第4章介绍过)来取得链接的文档内容了。结果,每个链接的title属性都给出了具体的提示信息,非常贴心。

5.1 操作属性 - 图1

图 5-1

5.1.2 DOM元素属性

我们曾在前面简单提到过,HTML属性DOM属性有一点区别。HTML属性是指页面标记中放在引号中的值,而DOM属性则是指通过JavaScript能够存取的值。如图5-2所示,通过Chrome的开发人员工具可以看到HTML属性和DOM属性值。

5.1 操作属性 - 图2

图 5-2

在Chrome开发人员工具的Elements检查器中,可以清楚地看到<p>元素有一个名为class的属性,值为square。而在右侧面板中,这个属性有一个对应的DOM属性,名为className,值也是square。这种HTML属性与对应的DOM属性名字不相同的情况并不多,而这里就是一个例子。

大多数情况下,HTML属性与对应的DOM属性的作用都是一样的,jQuery可以帮我们处理名字不一致的问题。可是,有时候我们的确需要留意这两种属性的差异。某些DOM属性,例如nodeNamenodeTypeselectedIndexchildNodes,在HTML中没有对应的属性,因此通过.attr()方法就没有办法操作它们。此外,数据类型方面也存在差异,比如HTML中的checked属性是一个字符串,而DOM中的checked属性则是一个布尔值。对于布尔值属性,最后是测试DOM属性而不是HTML属性,以确保跨浏览器的一致行为。

在jQuery中,可以通过.prop()方法取得和设置DOM属性:

  1. //取得"checked"属性的当前值
  2. var currentlyChecked = $('.my-checkbox').prop('checked');
  3. //设置"checked"属性的值
  4. $('.my-checkbox').prop('checked', false);

这个.prop()方法与.attr()方法没有什么不同,比如它们都可以一次性接受一个包含多个值的对象,也支持值回调函数。

5.1.3 表单控件的值

HTML属性与DOM属性差别最大的地方,恐怕就要数表单控件的值了。比如,文本输入框的value属性在DOM中的属性叫defaultValue,DOM中就没有value属性。而选项列表(select)元素呢,其选项的值在 DOM 中通常是通过 selectedIndex 属性,或者通过其选项元素的selected属性来取得。

由于存在这些差异,在取得和设置表单控件的值时,最好不要使用.attr()方法。而对于选项列表呢,最好连.prop()方法也不要使用。那使用什么呢,建议使用jQuery提供的.val()方法:

  1. //取得文本输入框的当前值
  2. var inputValue = $('#my-input').val();
  3. //取得选项列表的当前值
  4. var selectValue = $('#my-select').val();
  5. //设置单选列表的值
  6. $('#my-single-select').val('value3');
  7. //设置多选列表的值
  8. $('#my-multi-select').val(['value1', 'value2']);

.attr().prop()一样,.val()方法也可以接受一个函数作为其setter参数。有了这个多用途的.val()方法,使用jQuery做Web开发你又会倍感高效。