1.操作属性
之前的css方法还有addClass、removeClass、toggleClass都是对DOM元素进行style属性的操作。而对于其他属性则可以使用attr和removeAttr来实现。
例如:
$('a[href*="wikipedia"]').attr({
rel:'external',
title:function(){
return 'Learn more about ' + $(this).text() + ' from wikipedia.';
},
id:function(index, oldValue){
return 'wikilink-' + index;
}
});
这里指定了a标签的rel属性、title属性还有id属性,并使用值回调处理属性值。
另外,如果想要操作一些DOM属性(非HTML属性)则需要使用prop方法
prop方法的用法和attr方法没有什么不同,他们既支持一次性包含多个属性值的映射,同样也支持值回调。
2.DOM树操作
首先,先来看DOM元素的添加。要将一个DOM元素加入到一个DOM树中,所需要的步骤就是:a.创建这个DOM元素;b.将这个元素插入到已有的DOM树中。
如代码所示:
//创建2个a标签,并且插入到指定DOM位置
$('<a href="#top">back to top</a>').insertAfter('div.chapter');
$('<a id="top"></a>').prependTo('body');
这里首先使用$() 创建了两个a标签。然后分别使用insertAfter和prependTo,插入到已有的DOM树中。对应的插入方法有:
insertAfter、insertBefore 在现有元素外部的之后、之前加入
appendTo、prependTo 在现有元素内部的之后、之前加入
具体的DOM树操作还有更加复杂的方法,在开发中,我们常常要针对同一个环境$(this)对象做连缀操作。jQuery为我们提供了对应的反向插入方法:
after、before
append、prepend
这一组插入方法和之前的一组最大的区别可以理解为以……为主,将……插入到或者说是……不动,将……移动到。对比一下:
$a.appendTo($b) 表示,以b为主,将a插入到b的后面。(或者说 b 不动,将a移动到b后面)
$a.append($b) 表示,以a为主,将b插入到a后面。(或者说a不动,将b移动到a后面)
这样就可以对于同一个DOM对象进行操作,如下:
//移动元素
var $notes = $('<ol id="notes"></ol>').insertBefore('#footer');
$('span.footnote').each(function(index){
$(this).before(['<a id="content_',index+1,'" href="#footnote_',index+1,'" class="context"><sup>',index+1,'</sup></a>'].join(''))
.appendTo($notes).append(['<a href="#content_',index+1,'">(content)</a>'].join(''))
.wrap('<li id="footnote_'+index+'"></li>');
});
这里使用join函数进行字符数组的链接,取代+号连字符有时所带来的不必要的麻烦。还有,有必要解释一下这里还使用到了wrap包装方法,将目标元素包装到li内。
3.复制元素
简单的说复制元素就是使用方法clone。使用这个方法需要注意的是,这个方法默认是不复制与元素一起绑定的事件的,如果需要一并复制所绑定的事件,需要加入参数true,如:$a.clone(true);
下面是一个综合使用复制元素和移动元素的例子:
//复制元素示例:加入侧边引用
$('span.pull-quote').each(function(index){
var $parentParagraph = $(this).parent('p');
$parentParagraph.css('position','relative');
var $clonedCopy = $(this).clone();
$clonedCopy.addClass('pulled')
.find('span.drop').html('…').end()
.text($clonedCopy.text())
.prependTo($parentParagraph)
.addClass('rounded-top')
.wrapInner('<div class="rounded-bottom"></div>');
});
解释本例。首先通过clone获得了包含<span class="pull-quote">的段落<p>的一个副本。
接着为其套用pulled样式,
替换特定span的内容为...,
去掉特殊的text显示,
移动元素,
加入圆角样式,并把一个包装div加入到这个复制的元素内包装其内容。(其实CSS3提供了更加简便的呈现圆角+阴影的方法。参考css3学习)
4.其他DOM操作方法
替换:replaceWith()、replaceAll();
移除匹配元素:empty();
移除匹配元素以及其后代所有子元素:remove()、detach();
5.高级DOM操作方法--排序表格行
这里提到的表格行,是对于一个表格来说,使用本地javascript方法,将表格的全部tr行进行排序,达到某一列按照期望顺序呈现的目的。
主要使用的方法是sort方法。这里jQuery对象没有sort这类dom原生数组方法。所以切记要使用get来获得DOM元素。
如下例:(关键部位已经注释)
//通过index方法返回列索引
var column = $(this).index();
//使用get方法将jQuery对象转换为DOM节点数组
//转换的原因是要使用原生数组方法sort必须转换,另外‘>’号的作用是:仅匹配儿子辈,不匹配孙子辈
var rows = $table.find('tbody > tr').get();
//为rows添加字母排序
rows.sort(function(a, b){
//获得传入的参数a的子元素的相应列td的文本值
var keyA = $(a).children('td').eq(column).text();
//将keyA值去掉首尾括号,并且大写。
keyA = $.trim(keyA).toUpperCase();
var keyB = $(b).children('td').eq(column).text();
keyB = $.trim(keyB).toUpperCase();
if(keyA > keyB)
{
return 1;
}
else if(keyA < keyB)
{
return -1;
}
return 0;
});
//遍历排序并加入tbody中
$.each(rows, function(index, row){
$table.children('tbody').append(row);
});
这种做法可以附加到比如表格标题th的a标签事件中。
当然这种排序方法的确实现了需求,但是速度还不是很理想。使用jQuery的data函数,可以将要排序的数据预存起来,使用起来就比较快捷了。如下
var rows = $table.find('tbody > tr').each(function(){
var key = $(this).children('td').eq(column).text();
//将tr中的相对应的td值使用data方法将计算结果(这里是获得key并且trim后并转为大写)为值,
//附以键‘sortKey’保存到每个tr的jQuery对象中。
$(this).data('sortKey',$.trim(key).toUpperCase());
}).get();
rows.sort(function(a, b){
var keyA = $(a).data('sortKey');
var keyB = $(b).data('sortKey');
if(keyA > keyB)
{
return 1;
}
else if(keyA < keyB)
{
return -1;
}
return 0;
});
而这些都算是一种对于表格的预先计算,可以一定程度的提高表格排序的响应速度。以下例子则介绍了更多预先的额外计算,分别用于处理数字型、日期型、名字组合、排序方向等内容:
var $table = $('#t-1');
//使用slice方法跳过表格的第一个th元素。
var $headers = $table.find('thead th').slice(1);
$headers.each(function(){
//储存keyType数据类型
var keyType = this.className.replace(/^sort-/,'');
$(this).data('keyType', keyType);
}).wrapInner('<a href="#"></a>')
.addClass('sort');
//构造sortKeys方法,分别针对不同的类型的不同方法。
var sortKeys = {
alpha:function($cell){
var key = $cell.find('span.sort-key').text() + ' ';
key += $.trim($cell.text()).toUpperCase();
return key;
},
numeric:function($cell){
var num = $cell.text().replace(/^[^\d.]*/,'');
var key = parseFloat(num);
//将值为NaN的转换成0
if(isNaN(key)){
key = 0;
}
return key;
},
date:function($cell){
//使用javascript原生Date对象的parse函数,用来构建日期对象。
//由于本例$cell.text()不包含日期,所以前面加入‘1 ’
var key = Date.parse('1 ' + $cell.text());
return key;
}
};
$headers.bind('click',function(event){
event.preventDefault();
var $header = $(this),
column = $header.index(),
keyType = $header.data('keyType'),
sortDirection = 1;
//判断sortKeys方法是否存在
if(!$.isFunction(sortKeys[keyType])){
return;
}
if($header.hasClass('sort-asc')){
sortDirection = -1;
}
var rows = $table.find('tbody > tr').each(function(){
var $cell = $(this).children('td').eq(column);
//使用函数的数组表示法调用sortKeys[keyType]相应的函数。
$(this).data('sortKey',sortKeys[keyType]($cell));
}).get();
rows.sort(function(a, b){
var keyA = $(a).data('sortKey');
var keyB = $(b).data('sortKey');
if(keyA < keyB) return -sortDirection;
if(keyA > keyB) return sortDirection;
return 0;
});
$headers.removeClass('sorted-asc sorted-desc');
$header.addClass(sortDirection==1?'sorted-asc':'sorted-desc');
$.each(rows, function(index, row){
$table.children('tbody').append(row);
});
});
如上例,定义了一个sortKeys[keyType]方法,会根据keyType的不同而实现不同的排序内容:如alpha针对于名称、字符串排序;numeric针对于数字、单价等排序;date针对于日期排序这样。例子稍微有些复杂,不过不难理解。