5.3 对DOM节点进行操作
了解JavaScript的读者应该知道,通过JavaScript可以实现对DOM节点的操作,例如查找节点、创建节点、插入节点、复制节点或是删除节点,不过操作起来比较复杂。jQuery为了简化开发人员的工作,也提供了对DOM节点进行操作的方法,下面进行详细介绍。
5.3.1 创建节点
在DOM操作中,常常需要动态创建HTML内容,使文档在浏览器中的样式发生变化,从而达到各种交互目的。创建节点分为3种:创建元素节点、创建文本节点和创建属性节点。
1.创建元素节点
例如要创建两个<p>元素节点,并且要把它们作为<div>元素节点的子节点添加到DOM节点树上,完成这个任务需要两个步骤。
(1)创建两个新的<p>元素。
(2)将这两个新元素插入到文档中。
第(1)步可以使用jQuery的工厂函数$()来完成,格式如下:
$(html)
$(html)方法可以根据传入的HTML标记字符串,创建一个DOM对象,并且将这个DOM对象包装成一个jQuery对象后返回。
首先,创建两个<p>元素,jQuery代码如下:
var$p_1=$("<p></p>"); //创建第1个p元素 var$p_2=$("<p></p>"); //创建第2个p元素,文本为空
然后将这两个新的元素插入到文档中,可以使用jQuery中的append()等方法(将在5.3.3节中介绍)
具体的jQuery代码如下:
$("div").append($p_1); //将第1个p元素添加到div中,使它能在页面中显示 $("div").append($p_2); //也可以采用链式写法:$("div").append($p_1).append($p_2);
运行代码后,新创建的<p>元素将被添加到页面当中。
2.创建文本节点
两个<p>元素节点已经创建完毕并插入到文档中了,此时需要为它们添加文本内容。具体的jQuery代码如下:
var$p_1=$("<p>明日科技</p>"); //创建第1个p元素,包含元素节点和文本节点,文本节点为“明日科技” var$p_2=$("<p>明日图书</p>"); //创建第2个p元素,包含元素节点和文本节点,文本节点为“明日图书” $("div").append($p_1); //将第1个p元素添加到div中,使它能在页面中显示 $("div").append($p_2); //将第2个p元素添加到div中,使它能在页面中显示
创建文本节点就是在创建元素节点时直接把文本内容写出来,然后使用append()等方法将它们添加到文档中。运行代码后,新创建的<p>元素将被添加到页面当中,如图5.6所示。
图5.6 创建文本节点
3.创建属性节点
创建属性节点与创建文本节点类似,也是直接在创建元素节点时一起创建。具体jQuery代码如下:
var$p_1=$("<p title=’明日科技’>明日科技</p>"); //创建第1个p元素,包含元素节点和文本节点和属性 节点,其中“title=’明日科技’”就是属性节点 var$p_2=$("<p title=’明日图书’>明日图书</p>"); //创建第2个p元素,包含元素节点和文本节点和属性 节点,其中“title=’明日图书’就是属性节点 $("div").append($p_1); //将第1个p元素添加到div中,使它能在页面中显示 $("div").append($p_2); //将第2个p元素添加到div中,使它能在页面中显示
运行以上代码,将鼠标移至文字“明日科技”上,可以看到title信息,效果如图5.7所示。
图5.7 创建属性节点
5.3.2 查找节点
通过jQuery提供的选择器可以轻松实现查找页面中的任何节点。关于jQuery的选择器我们已经在第4章中进行了详细介绍,读者可以参考第4章“使用jQuery选择器”了解如何查找节点。
5.3.3 插入节点
在创建节点时,我们应用了append()方法将定义的节点内容插入到指定的元素。实际上,该方法是用于插入节点的方法。除了append()方法外,jQuery还提供了几种插入节点的方法。这一节我们将详细介绍。在jQuery中,插入节点可以分为在元素内部插入和在元素外部插入两种,下面分别进行介绍。
1.在元素内部插入
在元素内部插入就是向一个元素中添加子元素和内容。jQuery提供了如表5.2所示的在元素内部插入的方法。
表5.2 在元素内部插入的方法
从表中可以看出append()方法与prepend()方法类似,所不同的是prepend()方法将添加的内容插入到原有内容的前面。
appendTo()实际上是颠倒了append()方法,例如下面这句代码:
$("<p>A</p>").appendTo("#B"); //将指定内容添加到id为B的元素中
等同于:
$("#B").append("<p>A</p>"); //将指定内容添加到id为B的元素中
不过,append()方法并不能移动页面上的元素,而appendTo()方法是可以的,例如下面的代码:
$("#B").appendTo("#A"); //移动B元素到A元素的后面
append()方法是无法实现该功能的,注意两者的区别。
说明
prepend()方法是向所有匹配元素内部的开始处插入内容的最佳方法。prepend()方法与prependTo()的区别同append()方法与appendTo()方法的区别。
【例5.4】向<div>元素插入节点。(实例位置:光盘\TM\sl\5\4)
(1)创建一个名称为index.html的文件,在该文件的<head>标记中应用下面的语句引入jQuery库。
<script type="text/javascript" src="../js/jquery-1.11.1.min.js"></script>
(2)在页面的<body>标记中,添加一个空的<div>元素,代码如下:
<div></div>
(3)在引入jQuery库的代码下方编写jQuery代码,创建两个<p>节点,分别使用append()和appendTo()方法将这两个<p>节点插入到<div>元素中,具体代码如下:
$(document).ready(function(){ var$p_1=$("<p>明日图书</p>"); //创建第1个p元素 var$p_2=$("<p>编程词典</p>"); //创建第2个p元素 $div=$("div"); //获取div元素对象 $div.append($p_1); //将第1个p元素添加到div中 $p_2.appendTo($div); //将第2个p元素添加到div中 });
运行后将显示如图5.8所示的效果。
图5.8 向元素内插入节点
2.在元素外部插入
在元素外部插入就是将要添加的内容添加到元素之前或元素之后。jQuery提供了如表5.3所示的在元素外部插入的方法。
表5.3 在元素外部插入的方法
5.3.4 删除、复制与替换节点
在页面上只执行插入和移动元素的操作是远远不够的,在实际开发的过程中还经常需要删除、复制和替换相应的元素。下面将介绍如何应用jQuery实现删除、复制和替换节点。
1.删除节点
jQuery提供了3种删除节点的方法,分别是remove()、detach()和empty()方法。
1)remove()方法
remove()方法用于从DOM中删除所有匹配的元素,传入的参数用于根据jQuery表达式来筛选元素。
当使用remove()方法删除某个节点之后,该节点所包含的所有后代节点将同时被删除。remove()方法的返回值是一个指向已被删除的节点的引用,以后也可以继续使用这些元素。例如以下代码:
var$p_2=$("div p:eq(1)").remove(); //获取第2个<p>节点后,将它从页面中删除 $("div").append($p_2); //把删除的节点重新添加到div中
【例5.5】使用remove()方法删除节点。(实例位置:光盘\TM\sl\5\5)
(1)创建一个名称为index.html的文件,在该文件的<head>标记中应用下面的语句引入jQuery库。
<script type="text/javascript" src="../js/jquery-1.11.1.min.js"></script>
(2)在页面的<body>标记中,添加一个<div>元素,在<div>元素下创建2个<p>节点,并且为<p>节点赋予属性title,具体代码如下:
<div> <p title="明日科技">明日科技</p> <p title="明日图书">明日图书</p> </div>
(3)在引入jQuery库的代码下方编写jQuery代码,删除<div>元素下的第2个<p>节点,具体代码如下:
$(document).ready(function(){ $("div p").remove("p[title!=明日科技]"); //删除<p>元素中属性不等于“明日科技”的元素 });
运行后将显示如图5.9所示的效果。
图5.9 删除节点
2)detach()方法
detach ()方法和remove()方法一样,也是删除DOM中匹配的元素。需要注意的是,这个方法不会把匹配的元素从jQuery对象中删除,因此,在将来仍然可以使用这些匹配元素。与remove不同的是,所有绑定的事件或附加的数据都会保留下来。
请看如下实例:
$("div p").click(function(){ alert($(this).text()); }); var$p_2=$("div p:eq(1)").detach(); //删除元素 $p_2.appendTo("div");
由此可以看出,使用detach()方法删除元素之后,再执行“$p_2.appendTo("div"); ”重新追加此元素,之前绑定的事件还在,而如果是使用remove()方法删除元素,再重新追加元素,之前绑定的事件将失效。
【例5.6】使用detach()方法删除节点。(实例位置:光盘\TM\sl\5\6)
使用detach()方法将例5.5中页面<div>元素的第2个<p>元素删除,具体代码如下:
var$p_2=$("div p:eq(1)").detach(); //删除元素
之后再使用appendTo()方法将已删除的<p>节点添加到<div>元素中,具体代码如下:
$p_2.appendTo("div");
可以看到,该元素又显示在页面中,页面运行效果如图5.10所示。
图5.10 使用detach()方法删除节点
3)empty()方法
严格地说,empty()方法并不是删除元素节点,而是将节点清空,该方法可以清空元素中所有的后代节点。具体jQuery代码如下:
$("div p:eq(1)").empty(); //获取第2个p元素后,清空该元素中的内容
运行此段代码后,第2个<p>元素的内容被清空了,但第2个<p>元素还在,即<p title="明日图书"></p>。
2.复制节点
jQuery提供了clone()方法用于复制节点,该方法有两种形式,一种是不带参数,用于复制匹配的DOM元素并且选中这些复制的副本;另一种是带有一个布尔型的参数,当参数为true时,表示复制匹配的元素以及其所有的事件处理并且选中这些复制的副本,当参数为false时,表示不复制元素的事件处理。
【例5.7】复制节点。(实例位置:光盘\TM\sl\5\7)
(1)创建一个名称为index.html的文件,在该文件的<head>标记中应用下面的语句引入jQuery库。
<script type="text/javascript" src="../js/jquery-1.11.1.min.js"></script>
(2)在页面的<body>标记中,添加一个<div>元素,在<div>元素下创建两个<p>节点,并且为<p>节点赋予属性title,具体代码如下:
<div> <p title="明日科技">明日科技</p> <p title="明日图书">明日图书</p> </div>
(3)在引入jQuery库的代码下方编写jQuery代码,删除<div>元素下的第2个<p>节点,具体代码如下:
<script type="text/javascript"> $(function() { $("div p:eq(1)").bind("click", function(){ //为按钮绑定单击事件 $(this).clone().insertAfter(this); //复制自己但不复制事件处理 }); }); </script> 运行本实例,多次单击“明日图书”可以显示如图5.11所示的效果。
图5.11 复制节点
上面的效果,是一直单击第一个“明日图书”产生的,如果单击其他的“明日图书”所在的<p>元素,是不能继续复制节点的,因为没有复制元素的事件。如果需要同时复制元素的事件处理,可以给clone()方法传递true参数,即clone(true)。
3.替换节点
jQuery提供了两个替换节点的方法,分别是replaceAll(selector)和replaceWith(content)。其中,replaceAll(selector)方法用于使用匹配的元素替换掉所有selector匹配到的元素;replaceWith(content)方法用于将所有匹配的元素替换成指定的HTML或DOM元素。这两种方法的功能相同,只是两者的表现形式不同。
【例5.8】替换节点。(实例位置:光盘\TM\sl\5\8)
(1)创建一个名称为index.html的文件,在该文件的<head>标记中应用下面的语句引入jQuery库。
<script type="text/javascript" src="../js/jquery-1.11.1.min.js"></script>
(2)在页面的<body>标记中,添加两个指定id的<div>元素,具体代码如下:
div1: <div id="div1"></div> div2: <div id="div2"></div>
(3)在引入jQuery库的代码下方编写jQuery代码,分别使用replaceWith()方法和replaceAll()方法替换指定<div>元素的内容,具体代码如下:
<script type="text/javascript"> $(document).ready(function() { //替换id为div1的<div>元素 $("#div1").replaceWith("<div>replaceWith()方法的替换结果</div>"); //替换id为div2的<div>元素 $("<div>replaceAll()方法的替换结果</div>").replaceAll("#div2"); }); </script>
运行本实例,可以看到如图5.12所示的效果。
图5.12 替换节点
5.3.5 遍历节点
在操作DOM元素时,有时需要对同一标记的全部元素进行统一的操作。传统JavaScript中,是首先获取元素的总长度,之后通过for循环语句来访问其中的某个元素,书写的代码较多,相对比较复杂。在jQuery中,可以直接使用each()方法来遍历元素,它的语法格式为:
each(callback)
callback是一个函数,该函数可以接受一个形参index,这个形参是遍历元素的序号,序号为从0开始。如果要访问元素中的属性,可以借助形参index配合this关键字来实现元素属性的设置或获取。
【例5.9】使用each()方法img遍历元素。(实例位置:光盘\TM\sl\5\9)
(1)创建一个名称为index.html的文件,在该文件的<head>标记中应用下面的语句引入jQuery库。
<script type="text/javascript" src="../js/jquery-1.11.1.min.js"></script>
(2)在页面的<body>标记中,使用<img>标签添加5张图片,代码如下:
<img height=60 src="images/01.jpg" width=80 /> <img height=60 src="images/02.jpg" width=80 /> <img height=60 src="images/03.jpg" width=80 /> <img height=60 src="images/04.jpg" width=80 /> <img height=60 src="images/05.jpg" width=80 />
(3)在引入jQuery库的代码下方编写jQuery代码,使用each()方法遍历img全部图片,给每一张图片添加一个title属性,即鼠标文字移动到图片上面时的提示信息,具体代码如下:
$("img").each(function(index){ $(this).attr("title", "第"+(index+1)+"张图片"); })
运行后将显示如图5.13所示的效果。
图5.13 获取到的多行列表框的值
5.3.6 包裹节点
在jQuery中不仅替换元素节点,还可以使用wrap()方法根据需求将某个节点用其他标记包裹起来。对节点的包裹也是DOM操作中很重要的一项,wrap()方法的语法格式为:
$("p").wrap("<b></b>"); //用<b>标签把<p>元素包裹起来
得到如下结果:
<b><p>明日科技</p></b>
包裹节点也可以使用wrapAll()方法和wrapInner()方法。
1. wrapAll()方法
wrapAll()方法会将所有匹配元素用一个元素来包裹。它与wrap()方法不同,wrap()方法是将所有元素进行单独的包裹。
【例5.10】使用wrapAll()方法包裹所有p元素。(实例位置:光盘\TM\sl\5\10)
(1)创建一个名称为index.html的文件,在该文件的<head>标记中应用下面的语句引入jQuery库。
<script type="text/javascript" src="../js/jquery-1.11.1.min.js"></script>
(2)在页面的<body>标记中,创建两个<p>元素以及一个<ul>元素,令<ul>元素下包含3个<li>元素,代码如下:
<p>明日图书</p> <p>明日编程词典</p> <ul> <li title="Java Web编程词典">Java Web编程词典</li> <li title="PHP编程词典">PHP编程词典</li> <li title="VC编程词典">VC编程词典</li> </ul>
(3)在引入jQuery库的代码下方编写jQuery代码,使用wrapAll()方法包裹全部<p>元素,具体代码如下:
$(document).ready(function(){ $("p").wrapAll("<b></b>"); });
运行后可以看到,全部<p>元素都被<b></b>包裹,运行结果如图5.14所示。
图5.14 包裹元素节点