JQuery学习笔记整理:操作DOM
在使用jQuery时,改变HTML文档本身的结构(也就是操作DOM)是在所难免的,那么JQuery提供了哪些方法供我们操作DOM呢?
- 创建新元素
- 添加子元素或后代元素(append()、prepend()、appendTo()、prependTo())
- 封装(包裹)元素(wrap()、wrapAll()、wrapInner())
- 插入兄弟元素(after()、before()、insertAfter()、insertBefore())
- 替换元素(replaceWith()、replaceAll())
- 删除元素(detach()、remove()、empty()、unwrap())
var newElement = $('<div class="item"><span>文本</span></div>');
/<div class="example">
/ <div class="item"><span>123</span></div>
/</div>
var newElement = $('.example .item').clone();
$('.example').append(newElement);
// 结果
//<div class="example">
// <div class="item"><span>123</span></div>
// <div class="item"><span>123</span></div>
//</div>
var divElem = document.createElement('div');
divElem.className = 'item';
var newElem = $(divElem)
append(html)、append(jQuery)、append(HTMLElement) 把参数指定的元素插入到每个匹配元素内部的末尾,成为它们的最后一个子元素。
prepend(html)、prepend(jQuery)、prepend(HTMLElement) 把参数指定的元素插入到每个匹配元素内部的起始位置,成为它们的第一个子元素
appendTo(jQuery)、appendTo(HTMLElement) 将当前所有匹配元素插入到指定元素内部的末尾位置。
prependTo(html)、prependTo(jQuery)、prependTo(HTMLElement) 将当前所有匹配元素插入到指定元素内部的起始位置。
append(function)、prepend(function) 把参数函数的返回值插入到所有匹配元素内部的起始位置或末尾,成为它们的子元素。
(1)append()、prepend()
append()是把参数指定的元素插入到每个匹配元素内部的末尾,成为它们的最后一个子元素。
<div class="example">
<div class="item1"></div>
</div>
var newElem = $('<div class="item2"></div>');
var btn = document.createElement('button');
btn.innerHTML = '发布';
newElem.append('<input type="text"/>').append(btn);
$('.example').append(newElem);
// 结果
//<div class="example">
// <div class="item1"></div>
// <div class="item2">
// <input type="text"><button>发布</button>
// </div>
//</div>
在上面的代码中,我展示了append方法的三种用法。第一种用法是给append传递一个html,第二种是用DOM API创建一个新元素,然后append到jQuery对象(newElem)中,第三种是append一个jQuery对象。
注意:虽然多次调用append方法往jQuery对象(newElem)插入元素,但是最后返回的jQuery对象内包含的元素始终是不变的,一直是最初的div.item2元素。
还有一点注意,即使这些新创建的元素没有添加到页面,我们也可以用jQuery访问并修改它们。比如:设置样式:
newElem.css('background','red');
prepend()方法和append()方法的用法是一样的,只不过它是把参数指定的元素插入到每个匹配元素内部的起始位置,成为它们的第一个子元素。
<div class="example">
<div class="item"></div>
</div>
$('.example').prepend('<input type="text" />');
// 结果
//<div class="example">
// <input type="text" />
// <div class="item"></div>
//</div>
append()和prepend()方法还可以支持多个参数,可同时插入多个元素。
append(content1,content2...contentN)
prepend(content1,content2...contentN)
content参数可以是String/HTMLElement/jQuery,第一个参数content1还可以是函数(1.4新增)
再看一个例子:
<div class="example">
<div class="item1"></div>
</div>
var newElem = $('<div class="item2"></div>');
$('.example').append(newElem).prepend(newElem);
// 结果
//<div class="example">
// <div class="item2"></div>
// <div class="item1"></div>
//</div>
上面的代码中,我们本意是将jQuery对象(newElem)先append到div.example里,然后再prepend到div.example里,那么div.example里就应该头尾各有一个div.item2,可是结果却意料之外。
这是为什么呢?
因为jQuery规定一个新元素只能插入到页面一次,也可以这样理解,如果将页面已存在的元素再传入append和prepend方法,那么就不是插入新元素,而是 移动元素 了,也就是已存在的元素会从原位置消失,会移动到新位置。
如果你想添加多个相同的新元素,你可以使用clone方法克隆元素,然后插入:
$('.example').append(newElem).prepend(newElem.clone());
上面的代码就会往div.example内部的头尾各插入一个div.item2了。
(2)appendTo()、prependTo()
appendTo()和prependTo()方法会改变元素之间的关系。
<div class="example">
<div class="item1"></div>
</div>
var newElem = $('<div class="item2"></div>');
$('.item1').appendTo(newElem);
$('.example').append(newElem);
// 结果
//<div class="example">
// <div class="item2">
// <div class="item1"></div>
// </div>
//</div>
从上面代码的执行结果中,我们可以看到两个信息:第一个就是div.item1被插入到div.item2中,第二个就是原来的div.item1消失了,是消失了吗?其实不是,它只是移动了,移到div.item2中了。
prependTo()方法和appendTo()用法一样,只不过它是将当前所有匹配元素插入到指定元素内部的起始位置。
(3)append()和prepend()还可传入函数
当传入参数函数时,会给函数传递两个参数,第一个参数是当前元素在匹配元素中的索引,第二个参数就是该元素当前的内部html内容(innerHTML),函数中的this对象被设置为对应当前元素的HTMLElement对象。
$('p').append( function(index,html){
return '<span>' + (index+1) +'</span>';
});
上面的代码是为每个p元素内部的末尾位置追加一个span元素。
注意:append()、prepend()、appendTo()、prependTo()这四个方法,如果传入的是页面已存在的元素,那么就不会添加了,而是移动元素。
3、封装(包裹)元素
我们还可以将新元素作为现有元素的父元素或祖先元素插入到页面中,也就是新元素包裹住已存在元素。
wrap(html)、wrap(jQuery)、wrap(HTMLElement[]) 在每个匹配元素的周围包裹一个指定的元素。
wrapAll(html)、wrapAll(jQuery)、wrapAll(HTMLElement[]) 在所有匹配元素的外面包裹一个指定的元素
wrapInner(html)、wrapInner(jQuery)、wrapInner(HTMLElement[]) 在每个匹配元素的所有子节点外面包裹指定的元素。
wrap(function)、wrapInner(function) 使用函数动态地包裹元素
(1)wrap()
wrap方法是在每个匹配元素的周围包裹一个指定的元素,这个元素可以是单层元素,也可以多层嵌套的元素,返回一个jQuery对象。
<div class="example">
<div class="item1"></div>
<div class="item3"></div>
</div>
<div class="item3"><span></span></div>
<div class="item1"></div>
<div class="item4"></div>
var newElem = $('<div class="item2"></div>');
$('.item1').wrap(newElem);
$('.item4').wrap('<div><span></span></div>');
$('.example').wrap($('.item3'));
$('.item1').wrap(function(index){
return '<div class="wrap-' + index + '"></div>';
});
// 结果
//<div class="item3">
// <div class="example">
// <div class="item2"><div class="wrap-0"><div class="item1"></div></div></div>
// <div class="item3"></div>
// </div>
//</div>
//<div class="item3"><span></span></div>
//<div class="item2"><div class="wrap-1"><div class="item1"></div></div></div>
//<div><span><div class="item4"></div></span></div>
从上面代码运行结果中,我们可得到(后面的wrapAll和wrapInner方法也会遵循着下面四点):
- 如果参数匹配多个元素,则只将第一个元素作为包裹元素(看item3)。
- 即使参数是当前页面中的元素,该元素不会从原位置上消失,因为wrap()使用的是该元素的克隆副本来充当包裹。(看item3)
- 可采用多层嵌套的元素包裹元素(看item4)
- 如果传入的是参数函数,那么将根据匹配的所有元素遍历执行该函数,函数中的this将指向对应的DOM元素,还会给函数传入一个参数,即当前元素在匹配元素中的索引(从0开始)。
(2)wrapAll()
wrapAll()用来在所有匹配元素的外面包裹一个指定的元素,返回一个jQuery对象。
<div class="example">
<div class="item1"></div>
</div>
<div class="item1"></div>
var newElem = $('<div class="box"></div>');
$('.item1').wrapAll(newElem);
// 结果
//<div class="example">
// <div class="box"><div class="item1"></div><div class="item1"></div></div>
//</div>
wrapAll()除了和wrap()遵循三点规则外,还有一个 特殊规则 :如果参数不是函数,那么所有匹配的元素都会被移动到第一个匹配元素的位置,然后用指定的元素将它们包裹起来。
那如果是函数参数,结果会是怎样呢?
$('.item1').wrapAll(function(){
return newElem;
});
// 结果
//<div class="example">
// <div class="box"><div class="item1"></div></div>
//</div>
//<div class="box"><div class="item1"></div></div>
从上面代码的执行结果来看,当wrapAll传入的是参数函数时,实质上和wrap()传入参数函数一样,并不会移动匹配元素的位置。
(3)wrapInner()
wrapInner方法和wrap方法类似,只不过前者并不会包裹匹配元素的顶级元素,而是包裹顶级元素内部的所有元素,也是返回一个jQuery对象。
<div class="example">
<div class="item1"></div>
</div>
var newElem = $('<div class="box"></div>');
$('.example').wrapInner(newElem);
// 结果
//<div class="example">
// <div class="box"><div class="item1"></div></div>
//</div>
wrapInner也遵循wrap中的四点。
4、插入兄弟元素
after(content[,content]) 在每个匹配元素之后插入指定的元素,作为其兄弟节点
before(content[,content]) 在每个匹配元素之前插入指定的元素,作为其兄弟节点
insertAfter(content[,content]) 将当前所有匹配元素插入到指定元素之后
insertBefore(content[,content]) 将当前所有匹配元素插入到指定元素之前
after(function)、before(function) 使用回调函数添加兄弟元素
(1)after()、before()
after()和before()方法用来在每个匹配元素之后或之前插入指定的元素,作为其兄弟元素。
<div class="box">
<div class="item"></div>
<div class="item"></div>
</div>
var newElem = $('<div class="after"></div>');
$('.item').after(newElem);
var newElem2 = $('<div class="before"/>');
$('.item').before(newElem2);
// 结果
//<div class="box">
// <div class="before"></div>
// <div class="item"></div>
// <div class="after"></div>
// <div class="before"></div>
// <div class="item"></div>
// <div class="after"></div>
//</div>
after()和before()也可以支持多个参数:
after(content[,content2,....])
before(content[,content2,....])
注意:只能第一个参数是函数,当传入的是函数时,还会为函数传入两个参数,第一个参数就是当前元素在匹配元素中的索引,第二个参数是该元素的内部html内容(innerHTML),返回值就是需要插入的内容。
after(function(index,html){})
还有一点要注意:如果插入的内容是当前页面中的元素,那这些元素将从原位置上消失,移动到新位置,也就是说,并不是简单的插入,而是移动。
(2)insertAfter()、insertBefore()
insertAfter()和insertBefore()是将当前所有匹配元素插入到指定元素之后或之前。
<div class="box">
<div class="item"></div>
<div class="item"></div>
</div>
var newElem = $('<div class="after"></div>');
newElem.insertAfter($('.item'));
// 结果
//<div class="box">
// <div class="item"></div>
// <div class="after"></div>
// <div class="item"></div>
// <div class="after"></div>
//</div>
注意:如果插入的内容是当前页面中的元素,那这些元素将从原位置上消失,移动到新位置,也就是说,并不是简单的插入,而是移动。
<div class="box">
<div class="before"></div>
<div class="item"></div>
</div>
$('.before').insertAfter($('.item'));
// 结果
//<div class="box">
// <div class="item"></div>
// <div class="before"></div>
//</div>
(3)after()和before() 与 insertAfter()和insertBefore()的区别
这四个方法都是将一个元素插入另一个元素之前或之后,当然还是有区别的。
- 目标元素的位置不一样
- 返回值不一样
A.after(B); //将B插入到A之后,返回A的jQuery对象
A.insertAfter(B) //将A插入到B之后,返回表示插入元素的jQuery对象
实例:
<div class="box">
<div class="item"></div>
</div>
var newElem = $('<div class="after"></div>');
var A = newElem.insertAfter($('.item'));
var newElem = $('<div class="after"></div>');
var B = $('.item').after(newElem);
上面最后两行代码都是在div.item后插入元素div.after,但它们的目标元素位置不一样,而且A是包含着div.after元素的jQuery对象,B是包含着div.item元素的jQuery对象。
5、替换元素
使用一些元素替换已有元素
replaceWith(html)、replaceWith(jQuery)、replaceWith(HTMLElement[]) 使用指定的元素替换每个匹配的元素
replaceAll(jQuery)、replaceAll(HTMLElement[]) 使用当前匹配元素替换所有的目标元素
replaceWidth(function) 使用回调函数替换元素
(1)replaceWith()
replaceWith()是使用指定元素替换掉每个匹配的元素,而且返回被删除的元素的集合。
<div class="item1"></div>
<div class="box"><div class="item2"></div></div>
$('.item2').replaceWith('<span class="item3"></span>');
$('.item3').replaceWith($('.item1'));
// 结果
//<div class="box"><div class="item1"></div></div>
在上面的代码中,首先用span.item3替换div.item2,然后用div.item1替换span.item3,由于在执行第二步时,span.item3已经是页面中的元素了,所以这里就不是简单的替换了,而是移动替换。
replaceWidth()方法也可以传入函数,该函数还会传入两个参数,第一个参数是当前元素在匹配元素中的索引,第二个参数就是该参数当前的内部html内容(innerHTML),返回值就是用于替换的内容。
(2)replaceAll()
replaceAll()方法是将当前匹配元素替换所有的目标元素,返回替换内容的jQuery对象。
<div class="item1"></div>
$('<span class="item3" />').replaceAll($('.item1'));
// 结果
//<span class="item3"></span>
(3)replaceWith()和replaceAll()的区别
replaceWidth()和replaceAll()都是用来替换元素的,它们有几个共同点:
- 如果传入的页面已存在的元素,元素会从原位置消失,移动并替换到目标元素
- 如果匹配多个元素,只会将第一个元素用做替换元素
- 目标元素位置不一样
- 返回值不一样
A.replaceAll(B) //将A替换B,并返回替换内容(A)的jQuery对象
A.replaceWith(B) //将B替换A,并返回目标元素(A)的jQuery对象
6、删除元素
detach()、detach(selector) 从DOM中删除元素
empty() 清空所有匹配元素中的所有内容
remove()、remove(selector) 删除元素
unwrap() 删除所有匹配元素的父元素
(1)detach()、remove()
detach()方法是从DOM中删除元素
<span></span>
<div class="box">
<span></span><span></span>
<b class="item"></b><b></b>
</div>
$('span').detach();
$('b').detach('.item');
// 结果
// <div class="box"><b></b></div>
在上面的代码中,第一行是从DOM中删除所有的span,第二行是从DOM中删除具有类名为item的b元素。
remove()方法和detach()方法的工作方式完全相同,只不过前者会移除与元素相关联绑定的附加数据(data()函数)和事件处理器,而后者不会。
注意:使用remove()和detach()方法,虽然目标元素已经从文档中被移除,可是不会将其从jQuery中移除,我们依旧可以访问到被移除的元素,不过remove()只会保留元素本身,而detach()还保留着附加数据和事件处理器。
<div class="box">
<span class="item1">remove</span>
<span class="item2">detach</span>
</div>
$('.item1,.item2').on('click',function(){
alert(1);
});
var item1 = $('.item1');
var item2 = $('.item2');
item1.remove();
item2.detach();
$(".box").append(item1,item2);
在上面的代码中,给span.item1和span.item2都注册了点击事件,然后分别使用remove()和detach()方法删除了span.item1和span.item2,最后又将这两个元素添加回div.box中,当你再去点击span.item1和span.item2时,会发现前者没有反应,而后者却依旧响应点击事件。
如果元素上没有附加数据和事件处理器,两者方法没有区别,两者都会返回jQuery对象本身。
(2)empty()
empty()用于清空匹配元素内的所有内容,返回jQuery对象本身。
<div class="box">
<span></span>234<!--注释-->
</div>
$('.box').empty();
// 结果
//<div class="box"></div>
作用和html('')一样。
(4)unwrap()
unwrap()方法用于移除每个匹配元素的父元素,但会保留其所有的后代元素,正好和wrap()方法相反,它返回jQuery对象本身。
<div class="box"></div>
$('.box').wrap('<div class="parent"></div>').unwrap();
// 结果
//<div class="box"></div>
注意:unwrap()不会移除body元素,也就是说,如果当前匹配元素的父元素是body,则不会移除。
更多建议: