内容摘录自锋利的JQuery一书
一. DOM操作的分类
一般来说,DOM操作分为3个方面,即DOM Core(核心)、HTML-DOM和CSS-DOM。
1. DOM Core
DOM Core并不专属于javascript,任何一种支持DOM的程序设计语言都可以使用它。它的用途并非仅限于处理网页,也可以用来处理任何一种使用标记语言编写出来的文档,如XML。
JavaScript中的getElementById()、getElementsByTagName()、getAttribute()和setAttribute()等方法,这些都是DOM Core的组成部分。
例如,使用DOM Core来获取表单对象的方法:
document.getElementsByTagName('form');
使用DOM Core来获取某元素的src属性的方法:
element.getAttribute('src');
2. HTML_DOM
提供一些更简明的记号来描述各种HTML元素的属性。
例如:
使用HTML-DOM来获取表单对象的方法:
document.forms //获取一个forms对象
使用HTML-DOM来获取某元素的src属性的方法:
element.src //获取元素的src属性
HTML_DOM的代码通常比较简短,不过它只能用来处理Web文档。
3. CSS_DOM
CSS_DOM是针对CSS的操作。在JavaScript中,CSS_DOM技术的主要作用是获取和设置style对象的各种属性。
例如:设置某元素style对象字体颜色的方法:
element.style.color = "red";
二.jQuery中的DOM操作
2.1 查找节点
1. 查找元素节点
使用jQuery在文档树上查找节点可能通过jQuery选择器来完成。
2. 查找属性节点
使用attr()方法完成。attr()方法的参数可以是一个也可以是两个,是一个的时候是要查询的属性的名字,是两个的时候则是设置该元素的属性值,有则替换,没有则添加。
2.2 创建节点
节点类型:元素节点,文本节点,属性节点。
创建文本节点和创建属性节点都是直接在创元素节点时一起创建的。
创建节点可以使用jQuery的工厂函数$()来完成。格式如下:
$(html);
$(html)方法会根据传入的HTML标记字符串,创建一个DOM对象,并将这个DOM对象包装成一个jQuery对象后返回。
无论$(html)中HTML代码多么复杂,都可以使用相同的方式来创建。
例如:
var $li_ = $("<li title='雪梨'>雪梨</li>");
然后可以使用jQuery中的append()等方法将元素插入文档中。
2.3 插入节点
动态创建HTML元素并没有实际用处,还需要将新创建的元素插入文档中。
在jQuery中,提供了几种将新创建的节点插入某个文档中的方法,如下表所示:
方法 | 描述 | 示例 |
append() | 向每个匹配的元素内部追加内容 | HTML代码: <p>我想说:</p> jQuery代码: $("p").append("<b>你好</b>"); 结果: <p>我想说:<b>你好</b></p>
|
appendTo() | 将所有匹配的元素追加到指定的元素中。 实际上,使用该方法是颠倒了常规的$(A).append(B)的操作,即不是将B追加到A中,而是将A追加到B中 |
HTML代码: <p>我想说:</p>
jQuery代码: $("<b>你好</b>").appendTo("p"); 结果: <p>我想说:<b>你好</b></p>
|
prepend() | 向每个匹配的元素内部前置内容 | HTML代码: <p>我想说:</p>
jQuery代码: $("p").prepend("<b>你好</b>");
结果: <p><b>你好</b>我想说:</p>
|
prependTo() | 将所有匹配的元素前置到指定的元素中。 实际上,使用该方法是颠倒了常规的$(A).prepend(B)的操作,即不是将B前置到A中,而是将A前置到B中 |
HTML代码: <p>我想说:</p>
jQuery代码: $("<b>你好</b>").prependTo("p");
结果: <p><b>你好</b>我想说:</p>
|
after() | 向每个匹配的元素之后插入内容 | HTML代码: <p>我想说:</p>
jQuery代码: $("p").after("<b>你好</b>");
结果: <p>我想说:</p><b>你好</b>
|
insertAfter() | 将所有匹配的元素插入到指定的元素的后面。 实际上,使用该方法是颠倒了常规的$(A).after(B)的操作,即不是将B插入到A的后面,而是将A插入到B的后面 |
HTML代码: <p>我想说:</p>
jQuery代码: $("<b>你好</b>").insertAfter("p");
结果: <p>我想说:</p><b>你好</b>
|
before() | 在每个匹配的元素之前插入内容。 | HTML代码: <p>我想说:</p>
jQuery代码: $("p").before("<b>你好</b>"); 结果: <b>你好</b><p>我想说:</p>
|
insertBefore() | 将所有匹配的元素插入到指定的元素的前面。 实际上,使用该方法是颠倒了常规的$(A).before(B)的操作,即不是将B插入到A的前面,而是将A插入到B的前面 |
HTML代码: <p>我想说:</p>
jQuery代码: $("<b>你好</b>").insertBefore("p");
结果: <b>你好</b><p>我想说:</p>
|
2.4 删除节点
jQuery提供了三种删除节点的方法,即remove(),detach()和empty()。
1. remove()方法
作用是从DOM中删除所有匹配的元素,传人的参数用于根据jQuery表达式来筛选元素。例如:
$("ul li:eq(1)").remove(); //获取第2个li元素节点后,将它从网页中删除
当某个节点用remove()方法删除后,该节点所包含的所有后代节点将同时被删除。该方法的返回值是一个指向已被删除的节点的引用,因此可以在以后再使用这些元素。例如可以删除某个节点之后在需要的2时候再添加进去,如下所示:
var $li=$("ul li:eq(1)").remove(); //获取第2个li元素节点后,将它从网页中删除 $li.appendTo("ul");
可以直接使用appendTo()方法的特性来简化以上的代码:
$("ul li:eq(1)").appendTo("ul"); //appendTo()方法也可以用来移动元素 //移动元素时首先从文档上删除此元素,然后将该元素插入到文档中的指定节点
remove()方法也可以通过传递参数来选择性的 删除元素,如下代码所示:
$("ul li").remove("li[title!='菠萝']"); //将<li>元素中属性title不等于"菠萝"的<li>元素删除
2.detach()方法
该方法和remove()方法一样,也是从DOM中去掉所有匹配的元素。但需要注意的是,这个方法不会把匹配的元素从jQuery对象中删除,因而可以在将来再使用这些匹配的元素。与remove()方法不同的是,所有绑定的事件,附加的数据等都会保留下来。如下代码所示:
$("ul li").click(function(){ alert($(this).html()); }) var $li=$("ul li:eq(1)").detach();//删除元素 $li.appendTo("ul");//重新追加此元素,发现它之前绑定的事件还在,如果使用remove()方法删除元素的话,那么它之前绑定的事件将失效
3.empty()方法
empty()方法不是删除节点,只是清空节点,它能清空元素中的所有后代节点。代码如下:
$("ul li:eq(1)").empty();//获取第2个li元素后,清空此元素里面的内容,注意是元素里
2.5 复制节点
jQuery提供clone()方法来完成节点复制。购物车里面的商品拖动功能就是用到的复制节点。将用户选择的商品所处的节点元素复制一次,并将其跟随鼠标移动,从而达到购物效果。
如果单击li元素后需要再复制一个<li>元素,代码如下所示:
$("ul li").click(function(){ $(this).clone().appendTo("ul");//复制当前单击的节点,并将它追加到<ul>元素中 })
复制节点后,被复制的新元素并不具有任何行为。如果需要新元素也具有复制功能,可以使用如下jQuery代码:
$(this).clone(true).appendTo("ul");//注意参数true
如果在clone()方法中传递了一个参数true,它的含义是复制元素的同时复制元素中所绑定的事件。
2.6 替换节点
如果要替换某个节点,jQuery提供了相应的方法,即replaceWith()和replaceAll()。例如将网页中"<p title="选择你最喜欢的水果">你最喜欢的水果是?</p>"替换成"<strong>你最不喜欢的水果是?</strong>",可以使用下面的代码:
replaceWith()方法的作用是将所有匹配的元素都替换成指定的HTML或者DOM元素。
$("p").replaceWith("<strong>你最不喜欢的水果是?</strong>");
replaceAll()方法与replaceWith()方法的作用相同,只是颠倒了replaceWith()操作。
$("<strong>你最不喜欢的水果是?</strong>)".replaceAll("p");
如果在替换之前,已经为元素绑定事件,替换后原先绑定的事件将会替换的元素一起消失,需要在新元素上重新绑定事件。
2.7 包裹节点
如果要将某个节点用其他标记包裹起来,jQuery提供了相应的方法,即wrap(),该方法对于需要在文档中插入额外的结构化标记非常有用,而且它不会破坏原始文档的语义。如下代码所示:
$('strong').wrap("<b></b>");//用<b>标签把<strong>元素包裹起来
得到的结果是:
<b><strong>你最不喜欢的水果是?</strong></b>
包裹节点操作还有其他两个方法,即wrapAll()和wrapInner()。
wrap()是将所有的元素进行单独的包裹,而wrapAll()是将所有元素包裹在一起。wrapInner()将每一个匹配的元素的子内容(包括文本节点)用其他结构化的标记包裹起来。代码如下所示:
html代码如下所示:
<strongtitle="选择你喜欢的水果">选择你喜欢的水果</strong> <strongtitle="选择你喜欢的水果">选择你喜欢的水果</strong> <ul> <li title="苹果">苹果</li> <li title="橘子">橘子</li> <li title="菠萝">菠萝</li> </ul>
使用wrap()方法包裹<strong>元素,代码如下:
$("strong").wrap("<b></b>");
wrap()效果:
<b><strong title="选择你喜欢的水果">选择你喜欢的水果</strong></b>
<b><strong title="选择你喜欢的水果">选择你喜欢的水果</strong></b>
使用wrapAll()方法包裹<strong>元素,代码如下:
$("strong").wrapAll("<b></b>");
wrapAll()效果:
<b><strong title="选择你喜欢的水果">选择你喜欢的水果</strong>
<strong title="选择你喜欢的水果">选择你喜欢的水果</strong></b>
使用wrapInner()方法包裹<strong>元素,代码如下:
$("strong").wrapInner("<b></b>");
wrapInner()效果:
<strong title="选择你喜欢的水果"><b>选择你喜欢的水果</b></strong>
<strong title="选择你喜欢的水果"><b>选择你喜欢的水果</b></strong>
2.8 属性操作
在jQuery中,用attr()方法来获取和设置元素属性,removeAttr()方法来删除元素属性。
2.8.1 attr()方法来获取和设置元素属性
如果要获取元素属性,只需要给attr()方法传递一个参数,即属性名称。代码如下所示:
var $para=$("p");//元素<p>节点 var p_txt=$para.attr('title');//获取<p>元素节点属性title
如果要设置元素属性,需要给attr()方法传递二个参数,即属性名称和对应的值。代码如下所示:
$("p").attr("title","your title");//设置单个的属性值
如果需要一次性为同一个元素设置多个属性,可以使用下面的代码实现:
$("p").attr("title":"your title","name":"test");//将一个"名/值"形式的对象设置为匹配元素的属性
jQuery中的很多方法都是同一个函数实现获取(getter)和设置(setter)的,例如上面的attr()方法,既能设置元素的值,也能获取元素的值。类似的还有html(),text(),height(),width(),val()和css()等。
2.8.2 删除元素属性
使用removeAttr()方法删除文档特定属性。如下代码所示:
$("p").removeAttr("title");//删除<p>元素的属性title
jQuery1.6中新增了prop()和removeProp(),分别用来获取在匹配的元素集中的第一个元素的属性值和为匹配的元素删除设置的属性。
2.9 样式操作
2.9.1 获取和设置样式
html代码如下:
<p class="myClass" title="选择你最喜欢的水果">你最喜欢的水果是?</p>
在上面的代码中,class也是<p>元素的属性,因此获取class和设置class都可以使用attr()方法来完成。
2.9.2 追加样式
jQuery提供了addClass()方法来追加样式。
首先在style标签中添加一组样式,代码如下所示:
<style> .another{ font-style:italic; color:red; } </style>
然后可以在网页中追加一个样式,如下代码所示:
$("p").addClass("another");//给<p>元素追加"another"类
attr()和addClass()的区别:
2.9.3 移除样式
jQuery中使用removeClass()来移除样式。
删除<p>元素中值为"high"的class,代码如下:
$("p").removeClass("high");//移除<p>元素中值为"high"的class
如果想要删除两个class,代码如下所示:
$("p").removeClass("high").removeClass("another");
jQuery提供了更加简单的方法,可以以空格的方式删除多个class名,代码如下:
$("p").removeClass("high another");
另外,还可以使用removeClass()方法的一个特性来完成同样的效果,当它不带参数时,就会将class的值全部删除,代码如下:
$("p").removeClass();//移除<p>元素的所有class
2.9.4 切换样式
toggle(fn,fn,...):交替执行代码,主要是控制行为上的重复切换。代码如下所示:
$toggleBtn.toggle(function(){ //显示元素 },function(){ //隐藏元素 });
toggle()方法此处的作用是交替执行两个函数,如果元素原来是显示的,则隐藏它,如果元素原来是隐藏的,则显示它。
jQuery还提供了toggleClass()函数控制样式上的重复切换。如果类名存在则删除它,如果类名不存在则添加它。代码如下所示:
$("p").toggleClass("another");//重复切换类名"another"
2.9.5 判断是否含有某个样式
hasClass()可以用来判断元素中是否含有某个class,如果有,则返回true,否则返回false。代码如下所示:
$("p").hasClass("another");//判断<p>元素是否含有"another"的class
这个方法是为了增加代码可读性产生的,实际在jQuery内部是调用了is()方法来完成这个功能的。
该方法等价于如下代码:
$("p").is(".another") //is("." + class)
2.10 设置和获取HTML、文本和值
2.10.1 html()方法
html()类似于JavaScript中的innerHTML属性,可以用来读取或者设置某个元素中上的HTML内容。代码如下:
var $p_html=$("p").html();//获取<p>元素的html代码 alert($p_html);//打印<p>元素的hml代码
设置<p>元素的HTML代码如下所示:
$("p").html("<strong>你最喜欢的水果是?</strong>");//设置<p>元素的HTML代码
可以用于XHTML文档,但是不能用于XML文档。
2.10.2 text()方法
text()类似于JavaScript中的innerText属性,可以用来读取或者设置某个元素中的文本内容。代码如下:
var $p_text=$("p").text();//获取<p>元素的text代码 alert($p_text);//打印<p>元素的text代码
设置<p>元素的text代码如下所示
$("p").text("你最喜欢的水果是?");//设置<p>元素的text代码
1)JavaScript中的innerText属性并不能在Firefox浏览器下运行,而jQuery的text()方法支持所有的浏览器。
2)text()方法对HTML文档和XML文档都有效。
2.10.3 val()方法
val()类似于Javascript中的value属性,可以用来设置和获取元素的值。如果元素为多选,则返回一个包含所有有选择的值的数组。
val()还能使得select、checkbox、radio相应的选项被选中。
defaultValue属性包含表单元素的初始值。
2.11 遍历节点
children()用来取得匹配元素的“直接”子元素集合。只考虑直接子元素而不考虑任何后代元素。
next()取得匹配元素后面紧邻的同辈元素。
prev()取得匹配元素前面紧邻的同辈元素。
silibings()取得匹配元素前后所有的同辈元素,如果匹配则直接返回元素本身,如果不匹配则向上查找父元素,逐级向上直到找到匹配选择器的元素。如果什么都没有找到则返回一个空的jQuery对象。
closest()取得最近的匹配元素
parent,parents,closest的区别:
除上面列举的,jQuery还有很多遍历节点的方法,例如find(),filter(),nextAll()和prevAll()等。
2.12 CSS-DOM操作
CSS-DOM技术简单来说就是读取和设置style对象的各种属性。style无法提取到通过外部CSS设置的样式信息,然而在jQuery中,用css()可以完成。
在css()方法中,如果属性中没有带有"-"符号,则该符号后面的单词要大写代替"-"。
建议都加上引号,养成良好的习惯。
例如:
$("p").css("font-size", "30px") $("p").css("fontSize", "30px") $("p").css(fontSize: "30px") //错误,不存在这样的函数 $("p").css(fontSize, "30px") //错误,css(name) //name类型为String $("p").css({"font-size": "30px"}) //驼峰法 css(properties) $("p").css({fontSize: "30px"}) //驼峰法 css(properties) //大写代替"-"
height()方法可以用来获取window和document的高度。
css("height")获取的高度值与样式的设置有关,可能会得到"auto",也可能得到"10px"之类的字符串;而height()方法获取的高度值则是元素在页面中的实际高度,与样式的设置无关,并且不带单位。
offset()获取元素在当前视窗的相对偏移,其中返回的对象包含两个属性,即top和left,它只对可见元素有效。
position()获取元素相对于最近的一个position样式属性设置为relative或者absolute的祖父节点的相对偏移,与offset()一样,它返回的对象也包括两个属性,即top和left。
scrollTop()和scrollLeft()
这两个方法的作用分别是获取元素的滚动条距顶端的距离和距左侧的距离。
可以为这两个方法指定一个参数,控制元素的滚动条滚动到指定位置。
3.3 案例研究 某网站的超链接和图片提示效果
几个问题:
1. 首先是当鼠标滑过后,<a>标签中的title属性的提示也会出现;
解决方法:
在鼠标滑入时,保存对象title属性值,然后置空title属性值或者移除title属性。
在鼠标滑出时,再重新设置对象title属性值。
2. 其次是设置x坐标和y坐标的问题,由于自制的提示与鼠标的距离太近,有时候会引起无法提示的问题(鼠标焦点变化引起mouseout事件)。
解决办法:
重新设置提示元素的top和left值,为top增加了10px,为left增加了20px。
3. 最后当鼠标在超链接上移动时,提示效果跟随问题。为超链接添加一个mousemove事件。