5.1 操作属性
在本书前4章里,我们经常使用.addClass()
和.removeClass()
方法来示范如何改变页面上元素的外观。虽然我们一般会说这两个方法在操作类属性,但jQuery实际上是在操作DOM中的className
属性。换句话说,.addClass()
方法创建或增加这个属性,而.removeClass()
则删除或缩短该属性。而具备了这两种操作的.toggleClass()
方法能够交替地添加和移除类。这样,我们就具有了处理类的一种有效而可靠的方式。这些方法特别有用,因为它们可以在某个类已经存在的情况下不添加该类(例如,不会出现<div class="first first">
的情况),也可以正确处理给一个元素应用多个类的情况(比如 <div class="first second">
)。
5.1.1 非类属性
有时候,我们还需要操作其他一些属性,比如id
、rel
和title
属性。jQuery为此也提供了.attr()
和.revoveAttr()
方法。这些方法让修改属性变成了小菜一碟。此外,通过jQuery还可以一次修改多个属性,同我们在第4章中使用.css()
方法修改多个CSS属性的方式类似。
比如,我们可一次性修改链接的id
、rel
和title
属性。首先来看一看我们例子中的HTML代码:
<h1 id="f-title">Flatland: A Romance of Many Dimensions</h1>
<div id="f-author">by Edwin A. Abbott</div>
<h2>Part 1, Section 3</h2>
<h3 id="f-subtitle">
Concerning the Inhabitants of Flatland
</h3>
<div id="excerpt">an excerpt</div>
<div class="chapter">
<p class="square">Our Professional Men and Gentlemen are
Squares (to which class I myself belong) and Five-Sided
Figures or <a
href="http://en.wikipedia.org/wiki/Pentagon">Pentagons
</a>.
</p>
<p class="nobility hexagon">Next above these come the
Nobility, of whom there are several degrees, beginning at
Six-Sided Figures, or <a
href="http://en.wikipedia.org/wiki/Hexagon">Hexagons</a>,
and from thence rising in the number of their sides till
they receive the honourable title of <a
href="http://en.wikipedia.org/wiki/Polygon">Polygonal</a>,
or many-Sided. Finally when the number of the sides
becomes so numerous, and the sides themselves so small,
that the figure cannot be distinguished from a <a
href="http://en.wikipedia.org/wiki/Circle">circle</a>, he
is included in the Circular or Priestly order; and this is
the highest class of all.
</p>
<p><span class="pull-quote">It is a <span class="drop">Law
of Nature</span> with us that a male child shall have
<strong>one more side</strong> than his father</span>, so
that each generation shall rise (as a rule) one step in
the scale of development and nobility. Thus the son of a
Square is a Pentagon; the son of a Pentagon, a Hexagon;
and so on.
</p>
<!-- . . . code continues . . . -->
</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
$(document).ready(function() {
$('div.chapter a').attr({rel: 'external'});
});
与.css()
方法很相似,.attr()
方法也接受一对参数,第一个是属性名,第二个是属性值。不过,更常用的方式还是传入一个包含键值对的对象,如代码清单5-1所示。使用对象可以轻松地扩展,以便一次性地修改多个属性,如代码清单5-2所示。
代码清单5-2
- $(document).ready(function() {
- $('div.chapter a').attr({
- rel: 'external',
- title: 'Learn more at Wikipedia'
- });
- });
值回调
如果我们想让每个匹配的元素都具有相同的一个或多个属性值,那么只要给.attr()
传入一个静态的对象即可。不过,更常见的情况是为每个元素添加或修改的属性都必须具有不同的值。例如,对于任何给定的文档,如果要保证JavaScript代码有效,那么每个id
属性的值必须唯一。要为每个链接设置唯一的id
,可以使用jQuery的.css()
和.each()
方法的另一个特性:值回调。
值回调其实就是给参数传入一个函数,而不是传入具体的值。这个函数会针对匹配的元素集中的每个元素都调用一次,调用后的返回值将作为属性的值。例如,可以使用值回调来为每个元素生成唯一的id
值,参见代码清单5-3。
代码清单5-3
- $(document).ready(function() {
- $('div.chapter a').attr({
- rel: 'external',
- title: 'Learn more at Wikipedia',
- id: function(index, oldValue) {
- return 'wikilink-' + index;
- }
- });
- });
每次触发值回调,都会给它传入两个参数。第一个是一个整数,表示迭代次数,我们在此利用这个值为第一个链接生成的id
是wikilink-0
,为第二个链接生成的id
是wikilink-1
,以此类推。代码清单5-3并没有用到第二个参数,这个参数中保存的是修改之前属性的值。
我们是通过title
属性来邀请人们学习维基百科中的术语的。在我们目前为止使用的HTML中,所有链接都指向维基百科。不过,考虑到其他链接,还应该把选择符表达式定义得更具体一些,参见代码清单5-4。
代码清单5-4
- $(document).ready(function() {
- $('div.chapter a[href*="wikipedia"]').attr({
- rel: 'external',
- title: 'Learn more at Wikipedia',
- id: function(index, oldValue) {
- return 'wikilink-' + index;
- }
- });
- });
为了把.attr()
方法的使用讲得更透彻,下面演示怎么让这些链接的title
属性更具体地包含链接的目标。同样,解决这个问题还是要使用值回调,参见代码清单5-5。
代码清单5-5
- $(document).ready(function() {
- $('div.chapter a[href*="wikipedia"]').attr({
- rel: 'external',
- title: function() {
- return 'Learn more about ' + $(this).text() + ' at Wikipedia.';
- },
- id: function(index, oldValue) {
- return 'wikilink-' + index;
- }
- });
- });
这一次我们利用了值回调的上下文。就像在事件处理程序中一样,在值回调函数中,this
关键字指向每次调用回调时正在操作的那个DOM元素。在此,我们把这个元素封装为jQuery对象,这样就可通过.text()
方法(第4章介绍过)来取得链接的文档内容了。结果,每个链接的title
属性都给出了具体的提示信息,非常贴心。
图 5-1
5.1.2 DOM元素属性
我们曾在前面简单提到过,HTML属性与DOM属性有一点区别。HTML属性是指页面标记中放在引号中的值,而DOM属性则是指通过JavaScript能够存取的值。如图5-2所示,通过Chrome的开发人员工具可以看到HTML属性和DOM属性值。
图 5-2
在Chrome开发人员工具的Elements检查器中,可以清楚地看到<p>
元素有一个名为class
的属性,值为square
。而在右侧面板中,这个属性有一个对应的DOM属性,名为className
,值也是square
。这种HTML属性与对应的DOM属性名字不相同的情况并不多,而这里就是一个例子。
大多数情况下,HTML属性与对应的DOM属性的作用都是一样的,jQuery可以帮我们处理名字不一致的问题。可是,有时候我们的确需要留意这两种属性的差异。某些DOM属性,例如nodeName
、nodeType
、selectedIndex
和childNodes
,在HTML中没有对应的属性,因此通过.attr()
方法就没有办法操作它们。此外,数据类型方面也存在差异,比如HTML中的checked
属性是一个字符串,而DOM中的checked
属性则是一个布尔值。对于布尔值属性,最后是测试DOM属性而不是HTML属性,以确保跨浏览器的一致行为。
在jQuery中,可以通过.prop()
方法取得和设置DOM属性:
//取得"checked"属性的当前值
var currentlyChecked = $('.my-checkbox').prop('checked');
//设置"checked"属性的值
$('.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()
方法:
//取得文本输入框的当前值
var inputValue = $('#my-input').val();
//取得选项列表的当前值
var selectValue = $('#my-select').val();
//设置单选列表的值
$('#my-single-select').val('value3');
//设置多选列表的值
$('#my-multi-select').val(['value1', 'value2']);
与.attr()
和.prop()
一样,.val()
方法也可以接受一个函数作为其setter参数。有了这个多用途的.val()
方法,使用jQuery做Web开发你又会倍感高效。