一、DOM节点的创建
1、创建节点及节点属性
通过JavaScript可以很方便的获取DOM节点,从而进行一系列的DOM操作。但实际上一般开发者都习惯性的先定义好HTML结构,但这样就非常不灵活了。
试想下这样的情况:如果我们通过AJAX获取到数据之后然后才能确定结构的话,这种情况就需要动态的处理节点了
本文向大家介绍一下如何使用JavaScript创建div节点元素,主要包括创建div节点元素的属性和创建div节点元素的样式两大部分内容,相信本文介绍一定会让你有所收获。
先介绍下需要用到的浏览器提供的一些原生的方法(这里不处理低版本的IE兼容问题)
创建流程比较简单,大体如下:
- 创建节点(常见的:元素、属性和文本)
- 添加节点的一些属性
- 加入到文档中
流程中涉及的一点方法:
- 创建元素:document.createElement
- 设置属性:setAttribute
- 添加文本:innerHTML
- 加入文档:appendChild
<!DOCTYPE html> <html> <head> <meta http-equiv="Content-type" content="text/html; charset=utf-8" /> <title></title> <style> .left, .right { width: 300px; height: 120px; } .left div, .right div { width: 100px; height: 90px; padding: 5px; margin: 5px; float: left; border: 1px solid #ccc; } .left div { background: #bbffaa; } .right div { background: yellow; } </style> </head> <body> <h2>动态创建元素节点</h2> <div class="left"> <div class="aaron">点击body区域会动态创建元素节点</div> </div> <script type="text/javascript"> var body = document.querySelector('body'); document.addEventListener('click',function(){ //创建2个div元素 var rightdiv = document.createElement('div') var rightaaron = document.createElement("div"); //给2个div设置不同的属性 rightdiv.setAttribute('class', 'right') rightaaron.className = 'aaron' rightaaron.innerHTML = "动态创建DIV元素节点"; //2个div合并成包含关系 rightdiv.appendChild(rightaaron) //绘制到页面body body.appendChild(rightdiv) },false) </script> </body> </html>
如上面代码所示,写一个最简单的元素创建,我们会发现几个问题:
- 每一个元素节点都必须单独创建
- 节点是属性需要单独设置,而且设置的接口不是很统一
- 添加到指定的元素位置不灵活
- 最后还有一个最重要的:浏览器兼容问题处理
针对这一系列的DOM操作的问题,jQuery给出了一套非常完美的接口方法,我们之后就开始深入学习
2、jQuery节点创建与属性的处理
上一节介绍了通过JavaScript原生接口创建节点,在处理上是非常复杂与繁琐的。我们可以通过使用jQuery来简化了这个过程
创建元素节点:
可以有几种方式,后面会慢慢接触。常见的就是直接把这个节点的结构给通过HTML标记字符串描述出来,通过$()函数处理,$("html结构")
$("<div></div>")
创建为本节点:
与创建元素节点类似,可以直接把文本内容一并描述
$("<div>我是文本节点</div>")
创建为属性节点:
与创建元素节点同样的方式
$("<div id='test' class='aaron'>我是文本节点</div>")
我们通过jQuery把上一届的代码改造一下,如下面代码所示:
1 <!DOCTYPE html> 2 <html> 3 4 <head> 5 <meta http-equiv="Content-type" content="text/html; charset=utf-8" /> 6 <title></title> 7 <script src="http://lib.sinaapp.com/js/jquery/1.9.1/jquery-1.9.1.min.js"></script> 8 <style> 9 .left, 10 .right { 11 width: 300px; 12 height: 120px; 13 } 14 15 .left div, 16 .right div { 17 width: 100px; 18 height: 90px; 19 padding: 5px; 20 margin: 5px; 21 float: left; 22 border: 1px solid #ccc; 23 } 24 25 .left div { 26 background: #bbffaa; 27 } 28 29 .right div { 30 background: yellow; 31 } 32 </style> 33 </head> 34 35 <body> 36 <h2>动态创建元素节点</h2> 37 <button>点击通过jQuery动态创建元素节点</button> 38 <script type="text/javascript"> 39 var $body = $('body'); 40 $body.on('click', function() { 41 //通过jQuery生成div元素节点 42 var div = $("<div class='right'><div class='aaron'>动态创建DIV元素节点</div></div>") 43 $body.append(div) 44 }) 45 46 47 48 // var body = document.querySelector('body'); 49 50 // document.addEventListener('click',function(){ 51 52 // //创建2个div元素 53 // var rightdiv = document.createElement('div') 54 // var rightaaron = document.createElement("div"); 55 56 // //给2个div设置不同的属性 57 // rightdiv.setAttribute('class', 'right') 58 // rightaaron.className = 'aaron' 59 // rightaaron.innerHTML = "动态创建DIV元素节点"; 60 61 // //2个div合并成包含关系 62 // rightdiv.appendChild(rightaaron) 63 64 // //绘制到页面body 65 // body.appendChild(rightdiv) 66 67 // },false) 68 </script> 69 </body> 70 71 </html>
一条一句就搞定了,跟写HTML结构方式是一样的
$("<div class='right'><div class='aaron'>动态创建DIV元素节点</div></div>")
(注意:点击事件是绑定在body上的,点击body的任意地方都是可以新增div的。注意body是有高度的,点击空白的地方没有效果是因为body高度没有那么高)
这就是jQuery创建节点的方式,让我们保留HTML的结构书写方式,非常的简单、方便和灵活。
二、DOM节点的插入
3、内部插入append()与appendTo()
动态创建的元素是不够的,它只是临时存放在内存中,最终我们需要放到页面文档并呈现出来。那么问题来了,怎么放到文档上?
这里就涉及到一个位置关系,常见的就是把这个新创建的元素,当作页面某一个元素的子元素放到其内部。针对这样的处理,jQuery就定义2个操作的方法
append:这个操作与对指定的元素执行原生的appendChild方法,将它们添加到文档中的情况类似。
appendTo:实际上,使用这个方法是颠倒了常规的$(A).append(B)的操作,即不是把B追加到A中,而是把A追加到B中。
简单的总结就是:
.append()和.appendTo()两种方法功能相同,主要的不同是语法——内容和目标的位置不同
append()前面是要选择的对象,后面是要在对象内插入的元素内容 appendTo()前面是要插入的元素内容,而后面是要选择的对象
示例代码:
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta http-equiv="Content-type" content="text/html; charset=utf-8" /> 5 <title></title> 6 <script src="http://lib.sinaapp.com/js/jquery/1.9.1/jquery-1.9.1.min.js"></script> 7 <style> 8 .content { 9 width: 300px; 10 } 11 .append{ 12 background-color: blue; 13 } 14 .appendTo{ 15 background-color: red; 16 } 17 </style> 18 </head> 19 20 <body> 21 <h2>通过append与appendTo添加元素</h2> 22 <button id="bt1">点击通过jQuery的append添加元素</button> 23 <button id="bt2">点击通过jQuery的appendTo添加元素</button> 24 <div class="content"></div> 25 <script type="text/javascript"> 26 27 $("#bt1").on('click', function() { 28 //.append(), 选择表达式在函数的前面, 29 //参数是将要插入的内容。 30 $(".content").append('<div class="append">通过append方法添加的元素</div>') 31 }) 32 33 </script> 34 <script type="text/javascript"> 35 36 $("#bt2").on('click', function() { 37 //.appendTo()刚好相反,内容在方法前面, 38 //无论是一个选择器表达式 或创建作为标记上的标记 39 //它都将被插入到目标容器的末尾。 40 $('<div class="appendTo">通过appendTo方法添加的元素</div>').appendTo($(".content")) 41 }) 42 43 </script> 44 </body> 45 </html>
4、外部插入after()与before()
节点与节点之前有各种关系,除了父子,祖辈关系,还可以是兄弟关系。之前我们在处理节点插入的时候,接触到了内部插入的几个方法,这节我们开始讲外部插入的处理,也就是兄弟之间的关系处理,这里jQuery引入了2个方法,可以用来在匹配I的元素前后插入内容
选择器的描述:
- before与after都是用来对相对选中元素外部增加相邻的兄弟节点
- 2个方法都是都可以接收HTML字符串,DOM 元素,元素数组,或者jQuery对象,用来插入到集合中每个匹配元素的前面或者后面
- 2个方法都支持多个参数传递after(div1,div2,....) 可以参考右边案例代码
注意点:
- after向元素的后边添加html代码,如果元素后面有元素了,那将后面的元素后移,然后将html代码插入
- before向元素的前边添加html代码,如果元素前面有元素了,那将前面的元素前移,然后将html代码插
1 <!DOCTYPE html> 2 <html> 3 4 <head> 5 <meta http-equiv="Content-type" content="text/html; charset=utf-8" /> 6 <title></title> 7 <script src="http://lib.sinaapp.com/js/jquery/1.9.1/jquery-1.9.1.min.js"></script> 8 <style> 9 .aaron{ 10 border: 1px solid red; 11 } 12 </style> 13 </head> 14 15 <body> 16 <h2>通过before与after添加元素</h2> 17 <button id="bt1">点击通过jQuery的before添加元素</button> 18 <button id="bt2">点击通过jQuery的after添加元素</button> 19 <div class="aaron"> 20 <p class="test1">测试before</p> 21 </div> 22 <div class="aaron"> 23 <p class="test2">测试after</p> 24 </div> 25 <script type="text/javascript"> 26 $("#bt1").on('click', function() { 27 //在匹配test1元素集合中的每个元素前面插入p元素 28 $(".test1").before('<p style="color:red">before,在匹配元素之前增加</p>', '<p style="color:red">多参数</p>') 29 }) 30 </script> 31 <script type="text/javascript"> 32 $("#bt2").on('click', function() { 33 //在匹配test1元素集合中的每个元素后面插入p元素 34 $(".test2").after('<p style="color:blue">after,在匹配元素之后增加</p>', '<p style="color:blue">多参数</p>') 35 36 }) 37 </script> 38 </body>
5、内部插入prepend()与prependTo()
在元素内部进行操作的方法,除了在被选元素的结尾(仍然在内部)通过append与appendTo插入指定内容外,相应的还可以在被选元素之前插入,jQuery提供的方法是prepend与prependTo
选择器的描述:
通过右边代码可以看到prepend与prependTo的使用及区别:
- .prepend()方法将指定元素插入到匹配元素里面作为它的第一个子元素 (如果要作为最后一个子元素插入用.append()).
- .prepend()和.prependTo()实现同样的功能,主要的不同是语法,插入的内容和目标的位置不同
- 对于.prepend() 而言,选择器表达式写在方法的前面,作为待插入内容的容器,将要被插入的内容作为方法的参数
- 而.prependTo() 正好相反,将要被插入的内容写在方法的前面,可以是选择器表达式或动态创建的标记,待插入内容的容器作为参数。
这里总结下内部操作四个方法的区别:
- append()向每个匹配的元素内部追加内容
- prepend()向每个匹配的元素内部前置内容
- appendTo()把所有匹配的元素追加到另一个指定元素的集合中
- prependTo()把所有匹配的元素前置到另一个指定的元素集合中
1 <!DOCTYPE html> 2 <html> 3 4 <head> 5 <meta http-equiv="Content-type" content="text/html; charset=utf-8" /> 6 <title></title> 7 <script src="http://lib.sinaapp.com/js/jquery/1.9.1/jquery-1.9.1.min.js"></script> 8 <style> 9 .aaron1{ 10 border: 1px solid red; 11 } 12 .aaron1 p { 13 color: red; 14 } 15 .aaron2{ 16 border: 1px solid blue; 17 } 18 .aaron2 p { 19 color: blue; 20 } 21 </style> 22 </head> 23 24 <body> 25 <h2>通过prepend与prependTo添加元素</h2> 26 <button id="bt1">点击通过jQuery的prepend添加元素</button> 27 <button id="bt2">点击通过jQuery的prependTo添加元素</button> 28 <div class="aaron1"> 29 <p>测试prepend</p> 30 </div> 31 <div class="aaron2"> 32 <p>测试prependTo</p> 33 </div> 34 <script type="text/javascript"> 35 $("#bt1").on('click', function() { 36 //找到class="aaron1"的div节点 37 //然后通过prepend在内部的首位置添加一个新的p节点 38 $('.aaron1') 39 .prepend('<p>prepend增加的p元素</p>') 40 }) 41 </script> 42 <script type="text/javascript"> 43 $("#bt2").on('click', function() { 44 //找到class="aaron2"的div节点 45 //然后通过prependTo内部的首位置添加一个新的p节点 46 $('<p>prependTo增加的p元素</p>') 47 .prependTo($('.aaron2')) 48 }) 49 </script> 50 </body> 51 52 </html>
6、外部插入insertAfter()与insertBefore()
与内部插入处理一样,jQuery由于内容目标的位置不同,然增加了2个新的方法insertAfter与insertBefore
- .before()和.insertBefore()实现同样的功能。主要的区别是语法——内容和目标的位置。 对于before()选择表达式在函数前面,内容作为参数,而.insertBefore()刚好相反,内容在方法前面,它将被放在参数里元素的前面
- .after()和.insertAfter() 实现同样的功能。主要的不同是语法——特别是(插入)内容和目标的位置。 对于after()选择表达式在函数的前面,参数是将要插入的内容。对于 .insertAfter(), 刚好相反,内容在方法前面,它将被放在参数里元素的后面
- before、after与insertBefore。insertAfter的除了目标与位置的不同外,后面的不支持多参数处理
注意事项:
- insertAfter将JQuery封装好的元素插入到指定元素的后面,如果元素后面有元素了,那将后面的元素后移,然后将JQuery对象插入;
- insertBefore将JQuery封装好的元素插入到指定元素的前面,如果元素前面有元素了,那将前面的元素前移,然后将JQuery对象插入;
1 <!DOCTYPE html> 2 <html> 3 4 <head> 5 <meta http-equiv="Content-type" content="text/html; charset=utf-8" /> 6 <title></title> 7 <script src="http://lib.sinaapp.com/js/jquery/1.9.1/jquery-1.9.1.min.js"></script> 8 <style> 9 .test1 { 10 background: #bbffaa; 11 } 12 13 .test2 { 14 background: yellow; 15 } 16 </style> 17 </head> 18 19 <body> 20 <h2>通过insertBefore与insertAfter添加元素</h2> 21 <button id="bt1">点击通过jQuery的insertBefore添加元素</button> 22 <button id="bt2">点击通过jQuery的insertAfter添加元素</button> 23 <div class="aaron"> 24 <p class="test1">测试insertBefore,不支持多参数</p> 25 </div> 26 <div class="aaron"> 27 <p class="test2">测试insertAfter,不支持多参数</p> 28 </div> 29 <script type="text/javascript"> 30 $("#bt1").on('click', function() { 31 //在test1元素前后插入集合中每个匹配的元素 32 //不支持多参数 33 $('<p style="color:red">测试insertBefore方法增加</p>', '<p style="color:red">多参数</p>').insertBefore($(".test1")) 34 }) 35 </script> 36 <script type="text/javascript"> 37 $("#bt2").on('click', function() { 38 //在test2元素前后插入集合中每个匹配的元素 39 //不支持多参数 40 $('<p style="color:red">测试insertAfter方法增加</p>', '<p style="color:red">多参数</p>').insertAfter($(".test2")) 41 }) 42 </script> 43 </body> 44 45 </html>
三、DOM节点的删除
7、empty()的基本用法
要移除页面上节点是开发者常见的操作,jQuery提供了几种不同的方法用来处理这个问题,这里我们开仔细了解下empty方法
empty 顾名思义,清空方法,但是与删除又有点不一样,因为它只移除了 指定元素中的所有子节点。
这个方法不仅移除子元素(和其他后代元素),同样移除元素里的文本。因为,根据说明,元素里任何文本字符串都被看做是该元素的子节点。请看下面的HTML:
<div class="hello"><p>慕课网</p></div>
如果我们通过empty方法移除里面div的所有元素,它只是清空内部的html代码,但是标记仍然留在DOM中
//通过empty处理 $('.hello').empty() //结果:<p>慕课网</p>被移除 <div class="hello"></div>
可以参考下边的代码区域:
通过empty移除了当前div元素下的所有p元素 但是本身id=test的div元素没有被删除
1 <!DOCTYPE html> 2 <html> 3 4 <head> 5 <meta http-equiv="Content-type" content="text/html; charset=utf-8" /> 6 <title></title> 7 <script src="http://lib.sinaapp.com/js/jquery/1.9.1/jquery-1.9.1.min.js"></script> 8 <style> 9 div { 10 background: #bbffaa; 11 width: 300px; 12 } 13 </style> 14 </head> 15 16 <body> 17 <h2>通过empty移除元素</h2> 18 <div id="test"> 19 <p>p元素1</p> 20 <p>p元素2</p> 21 </div> 22 <button>点击通过jQuery的empty移除元素</button> 23 <script type="text/javascript"> 24 $("button").on('click', function() { 25 //通过empty移除了当前div元素下的所有p元素 26 //但是本身id=test的div元素没有被删除 27 $("#test").empty() 28 }) 29 </script> 30 </body> 31 32 </html>
8、remove()的有参用法和无参用法
remove与empty一样,都是移除元素的方法,但是remove会将元素自身移除,同时也会移除元素内部的一切,包括绑定的事件及与该元素相关的jQuery数据。
例如一段节点,绑定点击事件
<div class="hello"><p>慕课网</p></div> $('.hello').on("click",fn)
如果不通过remove方法删除这个节点其实也很简单,但是同时需要把事件给销毁掉,这里是为了防止"内存泄漏",所以前端开发者一定要注意,绑了多少事件,不用的时候一定要记得销毁
通过remove方法移除div及其内部所有元素,remove内部会自动操作事件销毁方法,所以使用使用起来非常简单
//通过remove处理 $('.hello').remove() //结果:<div class="hello"><p>慕课网</p></div> 全部被移除 //节点不存在了,同事事件也会被销毁
remove表达式参数:
remove比empty好用的地方就是可以传递一个选择器表达式用来过滤将被移除的匹配元素集合,可以选择性的删除指定的节点
我们可以通过$()选择一组相同的元素,然后通过remove()传递筛选的规则,从而这样处理
对比下边的代码区域,我们可以通过类似于这样处理
$("p").filter(":contains('3')").remove()
1 <!DOCTYPE html> 2 <html> 3 4 <head> 5 <meta http-equiv="Content-type" content="text/html; charset=utf-8" /> 6 <title></title> 7 <script src="http://lib.sinaapp.com/js/jquery/1.9.1/jquery-1.9.1.min.js"></script> 8 <style> 9 .test1 { 10 background: #bbffaa; 11 } 12 13 .test2 { 14 background: yellow; 15 } 16 </style> 17 </head> 18 19 <body> 20 <h2>通过jQuery remove方法移除元素</h2> 21 <div class="test1"> 22 <p>p元素1</p> 23 <p>p元素2</p> 24 </div> 25 <div class="test2"> 26 <p>p元素3</p> 27 <p>p元素4</p> 28 </div> 29 <button>点击通过jQuery的empty移除元素</button> 30 <button>点击通过jQuery的empty移除指定元素</button> 31 <script type="text/javascript"> 32 $("button:first").on('click', function() { 33 //删除整个 class=test1的div节点 34 $(".test1").remove() 35 }) 36 37 $("button:last").on('click', function() { 38 //找到所有p元素中,包含了3的元素 39 //这个也是一个过滤器的处理 40 $("p").remove(":contains('3')") 41 }) 42 </script> 43 </body> 44 45 </html>
9、empty和remove区别
要用到移除指定元素的时候,jQuery提供了empty()与remove([expr])二个方法,两个都是删除元素,但是两者还是有区别
empty方法
- 严格地讲,empty()方法并不是删除节点,而是清空节点,它能清空元素中的所有后代节点
- empty不能删除自己本身这个节点
remove方法
- 该节点与该节点所包含的所有后代节点将同时被删除
- 提供传递一个筛选的表达式,用来指定删除选中合集中的元素
以上就是二者的区别,我们具体通过下边代码部分加深理解
1 <!DOCTYPE html> 2 <html> 3 4 <head> 5 <meta http-equiv="Content-type" content="text/html; charset=utf-8" /> 6 <title></title> 7 <script src="http://lib.sinaapp.com/js/jquery/1.9.1/jquery-1.9.1.min.js"></script> 8 <style> 9 .left, 10 .right { 11 width: 300px; 12 } 13 14 .left div, 15 .right div { 16 width: 100px; 17 height: 90px; 18 padding: 5px; 19 margin: 5px; 20 float: left; 21 border: 1px solid #ccc; 22 } 23 24 .left div { 25 background: #bbffaa; 26 } 27 28 .right div { 29 background: yellow; 30 } 31 </style> 32 </head> 33 34 <body> 35 <h2>通过empty与remove移除元素</h2> 36 <div class="left"> 37 <button id="bt1">点击通过jQuery的empty移除内部P元素</button> 38 <button id="bt2">点击通过jQuery的remove移除整个节点</button> 39 </div> 40 <div class="right"> 41 <div id="test1"> 42 <p>p元素1</p> 43 <p>p元素2</p> 44 </div> 45 <div id="test2"> 46 <p>p元素3</p> 47 <p>p元素4</p> 48 </div> 49 </div> 50 <script type="text/javascript"> 51 $("#bt1").on('click', function() { 52 //删除了2个p元素,但是本着没有删除 53 $("#test1").empty() 54 }) 55 56 $("#bt2").on('click', function() { 57 //删除整个节点 58 $("#test2").remove() 59 }) 60 </script> 61 </body> 62 63 </html>
10、保留数据的删除操作detach()
如果我们希望临时删除页面上的节点,但是又不希望节点上的数据与事件丢失,并且能在下一个时间段让这个删除的节点显示到页面,这时候就可以使用detach方法来处理
detach从字面上就很容易理解。让一个web元素托管。即从当前页面中移除该元素,但保留这个元素的内存模型对象。
来看看jquery官方文档的解释:
这个方法不会把匹配的元素从jQuery对象中删除,因而可以在将来再使用这些匹配的元素。与remove()不同的是,所有绑定的事件、附加的数据等都会保留下来。 $("div").detach()这一句会移除对象,仅仅是显示效果没有了。但是内存中还是存在的。当你append之后,又重新回到了文档流中。就又显示出来了。
当然这里要特别注意,detach方法是JQuery特有的,所以它只能处理通过JQuery的方法绑定的事件或者数据
参考右边的代码区域,通过 $("p").detach()把所有的P元素元素删除后,在通过append把删除的p放到页面上,可以通过点击文字测试,事件没有丢失
1 <html> 2 3 <head> 4 <meta http-equiv="Content-type" content="text/html; charset=utf-8" /> 5 <script src="http://lib.sinaapp.com/js/jquery/1.9.1/jquery-1.9.1.min.js"></script> 6 <style type="text/css"> 7 p { 8 color: red; 9 } 10 </style> 11 </head> 12 13 <body> 14 <p>P元素1,默认给绑定一个点击事件</p> 15 <p>P元素2,默认给绑定一个点击事件</p> 16 <button id="bt1">点击删除 p 元素</button> 17 <button id="bt2">点击移动 p 元素</button> 18 <script type="text/javascript"> 19 $('p').click(function(e) { 20 alert(e.target.innerHTML) 21 }) 22 var p; 23 $("#bt1").click(function() { 24 if (!$("p").length) return; //去重 25 //通过detach方法删除元素 26 //只是页面不可见,但是这个节点还是保存在内存中 27 //数据与事件都不会丢失 28 p = $("p").detach() 29 }); 30 31 $("#bt2").click(function() { 32 //把p元素在添加到页面中 33 //事件还是存在 34 $("body").append(p); 35 }); 36 </script> 37 </body> 38 39 </html>
注意:
if (!$("p").length) return; //去重
判断 p的“存在”否,若不“存在”,则退出函数
11、detach()和remove()区别
JQuery是一个很大强的工具库,在工作中开发中,可是有些方法还是因为不常用到,或是没有注意到而被我们而忽略。
remove()和detach()可能就是其中的一个,可能remove()我们用得比较多,而detach()就可能会很少了
通过一张对比表来解释2个方法之间的不同
方法名 |
参数 |
事件及数据是否也被移除 |
元素自身是否被移除 |
remove |
支持选择器表达 |
是 |
是(无参数时),有参数时要根据参数所涉及的范围 |
detach |
参数同remove |
否 |
情况同remove |
remove:移除节点
- 无参数,移除自身整个节点以及该节点的内部的所有节点,包括节点上事件与数据
- 有参数,移除筛选出的节点以及该节点的内部的所有节点,包括节点上事件与数据
detach:移除节点
- 移除的处理与remove一致
- 与remove()不同的是,所有绑定的事件、附加的数据等都会保留下来
- 例如:$("p").detach()这一句会移除对象,仅仅是显示效果没有了。但是内存中还是存在的。当你append之后,又重新回到了文档流中。就又显示出来了。
具体可以参考下边的代码区域的对比:
1 <html> 2 3 <head> 4 <meta http-equiv="Content-type" content="text/html; charset=utf-8" /> 5 <style type="text/css"> 6 p{ 7 border: 1px solid red; 8 } 9 </style> 10 <script src="http://libs.baidu.com/jquery/1.9.1/jquery.js"></script> 11 </head> 12 13 <body> 14 <h3>给页面2个p元素节点绑定点击事件,点击后弹出自己本身的节点内容</h3> 15 <p>元素p1,同时绑定点击事件</p> 16 <p>元素p2,同时绑定点击事件</p> 17 <h3>通过点击2个按钮后观察方法处理的区别</h3> 18 <button>点击通过remove处理元素p1</button> 19 <button>点击通过detach处理元素p2</button> 20 </body> 21 <script type="text/javascript"> 22 //给页面上2个p元素都绑定时间 23 $('p').click(function(e) { 24 alert(e.target.innerHTML) 25 }) 26 27 $("button:first").click(function() { 28 var p = $("p:first").remove(); 29 p.css('color','red').text('p1通过remove处理后,点击该元素,事件丢失') 30 $("body").append(p); 31 }); 32 33 $("button:last").click(function() { 34 var p = $("p:first").detach(); 35 p.css('color','blue').text('p2通过detach处理后,点击该元素事件存在') 36 $("body").append(p); 37 }); 38 </script> 39 </script> 40 41 </html>
四、DOM节点的复制与替换
12、DOM拷贝clone()
克隆节点是DOM的常见操作,jQuery提供一个clone方法,专门用于处理dom的克隆
.clone()方法深度 复制所有匹配的元素集合,包括所有匹配元素、匹配元素的下级元素、文字节点。
clone方法比较简单就是克隆节点,但是需要注意,如果节点有事件或者数据之类的其他处理,我们需要通过clone(ture)传递一个布尔值ture用来指定,这样不仅仅只是克隆单纯的节点结构,还要把附带的事件与数据给一并克隆了
例如:
HTML部分 <div></div> JavaScript部分 $("div").on('click', function() {//执行操作}) //clone处理一 $("div").clone() //只克隆了结构,事件丢失 //clone处理二 $("div").clone(true) //结构、事件与数据都克隆
使用上就是这样简单,使用克隆的我们需要额外知道的细节:
- clone()方法时,在将它插入到文档之前,我们可以修改克隆后的元素或者元素内容,如右边代码我 $(this).clone().css('color','red') 增加了一个颜色
- 通过传递true,将所有绑定在原始元素上的事件处理函数复制到克隆元素上
- clone()方法是jQuery扩展的,只能处理通过jQuery绑定的事件与数据
- 元素数据(data)内对象和数组不会被复制,将继续被克隆元素和原始元素共享。深复制的所有数据,需要手动复制每一个
1 <!DOCTYPE html> 2 <html> 3 4 <head> 5 <meta http-equiv="Content-type" content="text/html; charset=utf-8" /> 6 <title></title> 7 <script src="http://lib.sinaapp.com/js/jquery/1.9.1/jquery-1.9.1.min.js"></script> 8 <style> 9 .left, 10 .right { 11 width: 300px; 12 height: 120px; 13 } 14 15 .left div, 16 .right div { 17 width: 100px; 18 height: 90px; 19 padding: 5px; 20 margin: 5px; 21 float: left; 22 border: 1px solid #ccc; 23 background: #bbffaa; 24 } 25 </style> 26 </head> 27 28 <body> 29 <h2>通过clone克隆元素</h2> 30 <div class="left"> 31 <div class="aaron1">点击,clone浅拷贝</div> 32 <div class="aaron2">点击,clone深拷贝,可以继续触发创建</div> 33 </div> 34 <script type="text/javascript"> 35 //只克隆节点 36 //不克隆事件 37 $(".aaron1").on('click', function() { 38 $(".left").append( $(this).clone().css('color','red') ) 39 }) 40 </script> 41 42 <script type="text/javascript"> 43 //克隆节点 44 //克隆事件 45 $(".aaron2").on('click', function() { 46 console.log(1) 47 $(".left").append( $(this).clone(true).css('color','blue') ) 48 }) 49 </script> 50 </body> 51 52 </html>
13、DOM替换replaceWith()和replaceAll()
之前学习了节点的内插入、外插入以及删除方法,这节会学习替换方法replaceWith
.replaceWith( newContent ):用提供的内容替换集合中所有匹配的元素并且返回被删除元素的集合
简单来说:用$()选择节点A,调用replaceWith方法,传入一个新的内容B(HTML字符串,DOM元素,或者jQuery对象)用来替换选中的节点A
看个简单的例子:一段HTML代码
<div> <p>第一段</p> <p>第二段</p> <p>第三段</p> </div>
替换第二段的节点与内容
$("p:eq(1)").replaceWith('<a style="color:red">替换第二段的内容</a>')
通过jQuery筛选出第二个p元素,调用replaceWith进行替换,结果如下
<div> <p>第一段</p> <a style="color:red">替换第二段的内容</a>' <p>第三段</p> </div>
.replaceAll( target ) :用集合的匹配元素替换每个目标元素
.replaceAll()和.replaceWith()功能类似,但是目标和源相反,用上述的HTML结构,我们用replaceAll处理
$('<a style="color:red">替换第二段的内容</a>').replaceAll('p:eq(1)')
总结:
- .replaceAll()和.replaceWith()功能类似,主要是目标和源的位置区别
- .replaceWith()与.replaceAll() 方法会删除与节点相关联的所有数据和事件处理程序
- .replaceWith()方法,和大部分其他jQuery方法一样,返回jQuery对象,所以可以和其他方法链接使用
- 返回的jQuery对象引用的是被删除的节点,而不是通过replaceWith/replaceAll方法替换的节点
1 <!DOCTYPE html> 2 <html> 3 4 <head> 5 <meta http-equiv="Content-type" content="text/html; charset=utf-8" /> 6 <title></title> 7 <script src="http://libs.baidu.com/jquery/1.9.1/jquery.js"></script> 8 <style> 9 10 .right div { 11 background: yellow; 12 } 13 </style> 14 </head> 15 16 <body> 17 <h2>replaceWith()和replaceAll()</h2> 18 <div class="left"> 19 <button class="bt1">点击,通过replaceWith替换内容</button> 20 <button class="bt2">点击,通过rreplaceAll替换内容</button> 21 </div> 22 <div class="right"> 23 <div> 24 <p>第一段</p> 25 <p>第二段</p> 26 <p>第三段</p> 27 </div> 28 <div> 29 <p>第四段</p> 30 <p>第五段</p> 31 <p>第六段</p> 32 </div> 33 </div> 34 <script type="text/javascript"> 35 //只克隆节点 36 //不克隆事件 37 $(".bt1").on('click', function() { 38 //找到内容为第二段的p元素 39 //通过replaceWith删除并替换这个节点 40 $(".right > div:first p:eq(1)").replaceWith('<a style="color:red">replaceWith替换第二段的内容</a>') 41 }) 42 </script> 43 <script type="text/javascript"> 44 //找到内容为第六段的p元素 45 //通过replaceAll删除并替换这个节点 46 $(".bt2").on('click', function() { 47 $('<a style="color:red">replaceAll替换第六段的内容</a>').replaceAll('.right > div:last p:last'); 48 }) 49 </script> 50 </body> 51 52 </html>
14、DOM包裹wrap()方法
如果要将元素用其他元素包裹起来,也就是给它增加一个父元素,针对这样的处理,JQuery提供了一个wrap方法
.wrap( wrappingElement ):在集合中匹配的每个元素周围包裹一个HTML结构
简单的看一段代码:
<p>p元素</p>
给p元素增加一个div包裹
$('p').wrap('<div></div>')
最后的结构,p元素增加了一个父div的结构
<div> <p>p元素</p> </div>
.wrap( function ) :一个回调函数,返回用于包裹匹配元素的 HTML 内容或 jQuery 对象
使用后的效果与直接传递参数是一样,只不过可以把代码写带函数体内部,写法不同而已
以第一个案例为例:
$('p').wrap(function() { return '<div><div/>'; //与第一种类似,只是写法不一样 })
注意:
.wrap()函数可以接受任何字符串或对象,可以传递给$()工厂函数来指定一个DOM结构。这种结构可以嵌套了好几层深,但应该只包含一个核心的元素。每个匹配的元素都会被这种结构包裹。该方法返回原始的元素集,以便之后使用链式方法。
1 <!DOCTYPE html> 2 <html> 3 4 <head> 5 <meta http-equiv="Content-type" content="text/html; charset=utf-8" /> 6 <title></title> 7 <script src="http://lib.sinaapp.com/js/jquery/1.9.1/jquery-1.9.1.min.js"></script> 8 <style> 9 .left div, 10 .right div { 11 width: 100px; 12 padding: 5px; 13 margin: 5px; 14 float: left; 15 border: 1px solid #ccc; 16 background: #bbffaa; 17 } 18 19 .right div { 20 background: yellow; 21 } 22 23 p { 24 border: 1px solid red; 25 } 26 27 a { 28 border: 1px solid blue; 29 } 30 </style> 31 </head> 32 33 <body> 34 <h2>DOM包裹wrap()方法</h2> 35 <div class="left"> 36 <button class="aaron1">点击,通过wrap方法给p元素增加父容器div</button> 37 <button class="aaron2">点击,通过wrap的回调方法给a元素增加父容器div</div> 38 </div> 39 <div class="right"> 40 <p>p元素</p> 41 <p>p元素</p> 42 </div> 43 <div class="left"> 44 <a>a元素</a> 45 <a>a元素</a> 46 </div> 47 <script type="text/javascript"> 48 $(".aaron1").on('click', function() { 49 //给所有p元素,增加父容器div 50 $('p').wrap('<div></div>') 51 }) 52 </script> 53 <script type="text/javascript"> 54 $(".aaron2").on('click', function() { 55 $('a').wrap(function() { 56 return '<div class="' + $(this).text() + '" />'; 57 }) 58 }) 59 </script> 60 </body> 61 62 </html>
15、DOM包裹unwrap()方法
我们可以通过wrap方法给选中元素增加一个包裹的父元素。相反,如果删除选中元素的父元素要如何处理 ?
jQuery提供了一个unwarp()方法 ,作用与wrap方法是相反的。将匹配元素集合的父级元素删除,保留自身(和兄弟元素,如果存在)在原来的位置。
看一段简单案例:
<div> <p>p元素</p> </div>
我要删除这段代码中的div,一般常规的方法会直接通过remove或者empty方法
$('div').remove();
但是如果我还要保留内部元素p,这样就意味着需要多做很多处理,步骤相对要麻烦很多,为了更便捷,jQuery提供了unwarp方法很方便的处理了这个问题
$('p').unwarp();
找到p元素,然后调用unwarp方法,这样只会删除父辈div元素了
结果:
<p>p元素</p>
这个方法比较简单,也不接受任何参数,注意参考下案例的使用即可
1 <!DOCTYPE html> 2 <html> 3 4 <head> 5 <meta http-equiv="Content-type" content="text/html; charset=utf-8" /> 6 <title></title> 7 <script src="http://libs.baidu.com/jquery/1.9.1/jquery.js"></script> 8 <style> 9 .left, 10 .right { 11 width: 250px; 12 height: 120px; 13 } 14 15 .left div, 16 .right div { 17 width: 100px; 18 height: 120px; 19 padding: 5px; 20 margin: 5px; 21 float: left; 22 border: 1px solid #ccc; 23 background: #bbffaa; 24 } 25 26 .right div { 27 background: yellow; 28 } 29 p { 30 border: 1px solid red; 31 } 32 33 a { 34 border: 1px solid blue; 35 } 36 </style> 37 </head> 38 39 40 <body> 41 <h2>DOM包裹unwrap()方法</h2> 42 <div class="left"> 43 <div class="aaron1">点击,通过unwrap方法给p元素删除父容器div</div> 44 <div class="aaron2">点击,通过unwrap的回调方法给a元素删除父容器div</div> 45 </div> 46 <div class="right"> 47 <div> 48 <p>p元素</p> 49 </div> 50 <div> 51 <p>p元素</p> 52 </div> 53 </div> 54 <div class="left"> 55 <div> 56 <a>a元素</a> 57 </div> 58 <div> 59 <a>a元素</a> 60 </div> 61 </div> 62 <script type="text/javascript"> 63 $(".aaron1").on('click', function() { 64 //找到所有p元素,删除父容器div 65 $('p').unwrap('<div></div>') 66 }) 67 </script> 68 <script type="text/javascript"> 69 $(".aaron2").on('click', function() { 70 //找到所有p元素,删除父容器div 71 $('a').unwrap(function() { 72 return '<div></div>'; 73 }) 74 }) 75 </script> 76 </body> 77 78 </html>
16、DOM包裹wrapAll()方法
wrap是针对单个dom元素处理,如果要将集合中的元素用其他元素包裹起来,也就是给他们增加一个父元素,针对这样的处理,JQuery提供了一个wrapAll方法
.wrapAll( wrappingElement ):给集合中匹配的元素增加一个外面包裹HTML结构
简单的看一段代码:
<p>p元素</p> <p>p元素</p>
给所有p元素增加一个div包裹
$('p').wrapAll('<div></div>')
最后的结构,2个P元素都增加了一个父div的结构
<div> <p>p元素</p> <p>p元素</p> </div>
.wrapAll( function ) :一个回调函数,返回用于包裹匹配元素的 HTML 内容或 jQuery 对象
通过回调的方式可以单独处理每一个元素
以上面案例为例,
$('p').wrapAll(function() { return '<div><div/>'; })
以上的写法的结果如下,等同于warp的处理了
<div> <p>p元素</p> </div> <div> <p>p元素</p> </div>
注意:
.wrapAll()函数可以接受任何字符串或对象,可以传递给$()工厂函数来指定一个DOM结构。这种结构可以嵌套多层,但是最内层只能有一个元素。所有匹配元素将会被当作是一个整体,在这个整体的外部用指定的 HTML 结构进行包裹。
17、DOM包裹wrapInner()方法
如果要将合集中的元素内部所有的子元素用其他元素包裹起来,并当作指定元素的子元素,针对这样的处理,JQuery提供了一个wrapInner方法
.wrapInner( wrappingElement ):给集合中匹配的元素的内部,增加包裹的HTML结构
听起来有点绕,可以用个简单的例子描述下,简单的看一段代码:
<p>p元素</p> <p>p元素</p>
给所有p元素增加一个div包裹
$('p').wrapInner('<div></div>')
最后的结构,匹配的p元素的内部元素被div给包裹了
<p> <div>p元素</div> </p> <p> <div>p元素</div> </p>
.wrapInner( function ) :允许我们用一个callback函数做参数,每次遇到匹配元素时,该函数被执行,返回一个DOM元素,jQuery对象,或者HTML片段,用来包住匹配元素的内容
以上面案例为例,
$('p').wrapInner(function() { return '<div><div/>'; })
以上的写法的结果如下,等同于第一种处理了
<div> <p>p元素</p> </div> <div> <p>p元素</p> </div>
注意:
当通过一个选择器字符串传递给.wrapInner() 函数,其参数应该是格式正确的 HTML,并且 HTML 标签应该是被正确关闭的。
1 <!DOCTYPE html> 2 <html> 3 4 <head> 5 <meta http-equiv="Content-type" content="text/html; charset=utf-8" /> 6 <title></title> 7 <script src="http://libs.baidu.com/jquery/1.9.1/jquery.js"></script> 8 <style> 9 .left, 10 .right { 11 width: 250px; 12 height: 130px; 13 } 14 15 .left div, 16 .right div { 17 width: 100px; 18 padding: 5px; 19 margin: 5px; 20 float: left; 21 border: 1px solid #ccc; 22 background: #bbffaa; 23 } 24 25 .right div { 26 background: yellow; 27 } 28 p { 29 border: 1px solid red; 30 } 31 32 a { 33 border: 1px solid blue; 34 } 35 </style> 36 </head> 37 38 39 <body> 40 <h2>DOM包裹wrapInner()方法</h2> 41 <div class="left"> 42 <div class="aaron1">点击,通过wrapInner方法给所有P元素增加内部父容器div</div> 43 <div class="aaron2">点击,通过wrapInner的回调方法给每个a元素增加内部父容器div</div> 44 </div> 45 <div class="right"> 46 <p>p元素</p> 47 <p>p元素</p> 48 </div> 49 <div class="left"> 50 <a>a元素</a> 51 <a>a元素</a> 52 </div> 53 54 55 <script type="text/javascript"> 56 $(".aaron1").on('click', function() { 57 //给所有p元素,增加内部包裹父容器div 58 $('p').wrapInner('<div></div>'); 59 }) 60 </script> 61 <script type="text/javascript"> 62 $(".aaron2").on('click', function() { 63 //wrapInner接受一个回调函数 64 //每一次遍历this都指向了合集中每一个a元素 65 $('a').wrapInner(function() { 66 return '<div></div>' 67 }) 68 }) 69 </script> 70 </body> 71 72 </html>