这里有新鲜出炉的 Javascript 教程,程序狗速度看过来!
Javascript 是一种由 Netscape 的 LiveScript 发展而来的原型化继承的基于对象的动态类型的区分大小写的客户端脚本语言,主要目的是为了解决服务器端语言,比如 Perl,遗留的速度问题,为客户提供更流畅的浏览效果。
这篇文章主要介绍了 JavaScript 中对 DOM 节点的访问、创建、修改、删除, 是 JavaScript 入门学习中的基础知识, 需要的朋友可以参考下
DOMDOM 就是 Document object Model 的缩写。文档对象模型是把 XML 或 html 以树节点为表现形式的文档。用 DOM 方法和属性,你可以访问,修改,删除页面上任意一个元素,也是可以添加一个元素。DOM 是独立于语言的 API,可以被任意语言所实现,当然也包括了 Javascript 看看下面的一个文本。
- <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
- <html>
- <head>
- <title>
- My page
- </title>
- </head>
- <body>
- <p class="opener">
- first paragraph
- </p>
- <p>
- <em>
- second
- </em>
- paragraph
- </p>
- <p id="closer">
- final
- </p>
- </body>
- </html>
我们来看看第二段
- <p>
- <em>
- second
- </em>
- paragraph
- </p>
可以看到这是个 p 标签。它被包含在 body 标签中。所以说 body 是 p 的父节点,p 是子节点。第一段和第三段也是 body 的子节点。它们都是第二段的兄弟节点。这个 em 标签是第二段 p 的子节点。因此 p 就是它的父节点。父子节点关系能描绘出像树一样的关系。所以叫做 DOM 结构树 (DOM tree). Core DOM 和 HTML DOM 我们已经知道 DOM 可以描绘出 HTML 和 XML 文档。事实上 HTML 文档就是 XML 文档,只不过更为规范些。因此作为 DOM Level 1 的一部分,Core DOM 规范适用于所有 XML 文档以及 HTML DOM 规范扩展了 Core DOM. 当然 HTML DOM 不能适用于所有的 XML 文档,仅仅适用于 HTML 文档。让我们来看看 Core DOM 和 HTML DOM 的构造器。 构造器关系
访问 DOM 节点当要验证表单或者更换图片之前,我们要知道怎么样访问元素 (element.)。有很多方法获取元素。 Document 节点通过 document 我们可以访问当前的文档。我们可以通过 firebugs(火狐插件),来查看 document 的属性和方法。 所有的节点都有 nodeType,nodeName,nodeValue 的属性。我们来看看 document 的 nodeType 是什么
- document.nodeType;//9
一共有 12 节点类型。document 是 9。常用的是元素(element:1), 属性(attribute:2), 文本(text:3)。 节点还有名称。对于 HTML 标签。节点名称就是标签名称。文本节点 (text) 的名字是 #text. 文档节点 (document) 的名字是#document. 节点也有值。对于文本节点,值就是文本。document 的值为 null documentElementXML 都会有个 ROOT 节点来包文档包含起来。对于 HTML 文档。ROOT 节点就是 html 标签。访问 root 节点。可以用 documentElement 的属性。
- document.documentElement; //<html>
- document.documentElement.nodeType; //1
- document.documentElement.nodeName; //HTML
- document.documentElement.tagName; //对于element,nodeName和tagName相同
Child Nodes 为了确定是否包含子节点我们可以用如下方法
- document.documentElement.hasChildNodes();//true
HTML 有两个子节点。
- document.documentElement.childNodes.length;//2
- document.documentElement.childNodes[0];//<head>
- document.documentElement.childNodes[1];//<body>
也可以通过子节点访问父节点
- document.documentElement.childNodes[1].parentNode;//<html>
我们把 body 的引用赋值变量
- var bd = document.documentElement.childNodes[1];
- bd.childNodes.length;//9
让我们看看 body 的结构
- <body>
- <p class="opener">
- first paragraph
- </p>
- <p>
- <em>
- second
- </em>
- paragraph
- </p>
- <p id="closer">
- final
- </p>
- <!-- and that's about it -->
- </body>
为什么子节点个数为 9 个呢。 首先是 4 个 P 还有一个注释一共 4 个。 4 个节点包含了 3 个空白的节点。这就 7 个。 第 8 个在 body 和第一个 p 之间的空白节点。 第 9 个就是在注释与之间的空白节点。 一共 9 个节点。 属性因为第一节点是空白节点,所以第二个节点才是第一个 p 标签。
- bd.childNodes[1];// <p class="opener">
可以查看它是否有属性
- bd.childNodes[1].hasAttributes();//true
也可以查看 attributes 的个数
- bd.childNodes[1].attributes.length;//1
- //可以用index和名字来访问属性,也可以用getAttribute方法。
- bd.childNodes[1].attributes[0].nodeName;//class
- bd.childNodes[1].attributes[0].nodeValue;//opener
- bd.childNodes[1].attributes['class'].nodeValue;//opener
- bd.childNodes[1].getAttribute('class');//opener
访问标签里的内容让我们看看第一个标签 p 你可以用 textContent 属性来访问。要注意的是,在 IE 浏览器中并不存在 textContent,请用 innerText 来替换,结果都是一样的。
- bg.childNodes[1].textContent;// "first paragraph"
还有一个属性是 innerHTML. 这并不是 DOM 的规范。但是主流浏览器都支持这个属性。它返回的是 HTML 代码。
- bg.childNodes[1].innerHTML;// "first paragraph"
第一段没有 html 代码,所以结果和 textContent(IE 里是 innerText) 是一样的。来看下第二段包含 HTML 代码的标签
- bd.childNodes[3].innerHTML;//"<em>second</em> paragraph"
- bd.childNodes[3].textContent;//second paragraph
另一种方法可以获取文本节点,然后再取 nodeValue 属性,代码如下
- bd.childNodes[1].childNodes.length;//1 子节点个数
- bd.childNodes[1].childNodes[0].nodeName;// 节点名称 #text
- bd.childNodes[1].childNodes[0].nodeValue;//节点值 first paragraph
快速访问 DOM 通过 childNodes,parentNode,nodeName,nodeValue 以及 attributes, 可以访问文档任意的节点了。但是在实际运用过程中,文本节点是比较讨厌的。如果文本改变了,有可能就影响脚本了。还有如果 DOM 树足够的深入,那么访问起来的确有些不方便。幸好我们可以用更为方便的方法来访问节点。这些方法是
- getElementsByTagName()
- getElementsByName()
- getElementById()
首先说下 getElementsByTagName() 通过一个标签名称 (tag name) 来获取一个 html 元素的集合。例子如下
- document.getElementsByTagName('p').length;//3
因为返回的是个集合,我们可以用过数组下标的形式来访问或者通过 item 方法。比较一下还是推荐用数组的访问方法。更简单一些。
- document.getElementsByTagName('p')[0];// <p class="opener">
- document.getElementsByTagName('p').item(0);//和上面的结果一样
- document.getElementsByTagName('p')[0].innerHTML;//first paragraph
访问元素的属性,可以用 attributes 集合。但是更简单的方法是直接作为一个属性来访问就行。看个例子
- document.getElementsByTagName('p')[2].id;//closer
要注意的是,class 属性不能正常的使用。。要用 className。因为 class 在 javascript 规范中是保留字。
- document.getElementsByTagName('p')[0].className;//opener
我们可以用如下方法访问页面所有元素
- <span style="color: #ff0000;">
- document.getElementsByTagName('*').length;//9
- </span>
注意:在 IE 早期的版本不支持上述方法。可以用 document.all 来取代。IE7 已经支持了,但是返回的是所有节点 (node),而不仅仅是元素节点 (element nodes)。 Siblings, Body, First, Last ChildnextSibling 和 previousSibling 是两个比较方便访问 DOM 的方法。用来访问相邻的节点的。例子如下
- var para = document.getElementById('closer')
- para.nextSibling;//"\n"
- para.previousSibling;//"\n"
- para.previousSibling.previousSibling;//<p>
- para.previousSibling.previousSibling.previousSibling;//"\n"
- para.previousSibling.previousSibling.nextSibling.nextSibling;// <p id="closer">
body 用来访问 body 元素的。
- document.body;//<body>
firstChild 和 lastChild 。firstChild 是和 childNodes[0] 一样. lastChild 和 childNodes[childNodes.length - 1] 一样。 遍历 DOM 通过以上的学习,我们可以写个函数,用来遍历 DOM
- function walkDOM(n) {
- do {
- alert(n);
- if (n.hasChildNodes()) {
- walkDOM(n.firstChild)
- }
- } while (n = n.nextSibling)
- }
- walkDOM(document.body);//测试
修改节点下面来看看 DOM 节点的修改。 先获取要改变的节点。
- var my = document.getElementById('closer');
非常容易更改这个元素的属性。我们可以更改 innerHTML.
- my.innerHTML = 'final';//final
因为 innerHTML 可以写入 html,所以我们来修改 html。
- my.innerHTML = '<em>my</em> final';//<em>my</em> fnal
em 标签已经成为 dom 树的一部分了。我们可以测试一下
- my.firstChild;//<em>
- my.firstChild.firstChild;//my
我们也可以通过 nodeValue 来改变值。
- my.firstChild.firstChild.nodeValue = 'your';//your
修改样式大部分修改节点可能都是修改样式。元素节点有 style 属性用来修改样式。style 的属性和 CSS 属性是一一对应的。如下代码
- my.style.border = "1px solid red";
CSS 属性很多都有破折号 ("-"),如 padding-top,这在 javascript 中是不合法的。这样的话一定要省略波折号并把第二个词的开头字母大写,规范如下。 margin-left 变为 marginLeft。依此类推
- my.style.fontWeight = 'bold';
我们还可以修改其他的属性,无论这些属性是否被初始化。
- my.align = "right";
- my.name = 'myname';
- my.id = 'further';
- my;//<p id="further" align="right" style="border: 1px solid red; font-weight: bold;">
创建节点
为了创建一个新的节点,可以使用 createElement 和 createTextNode. 如果新建完成,可以用 appendChild() 把节点添加到 DOM 树中。 创建一个元素 P,并把设置 innerHTML 属性
- var myp = document.createElement('p');
- myp.innerHTML = 'yet another';
元素 P 建完成了,就可以随意修改添加属性了
- myp.style.border = '2px dotted blue'
接下来可以用 appendChild 把新的节点添加到 DOM 树中的。
- document.body.appendChild(myp)
使用 DOM 的方法用 innerHTML 方法的确很简单,我们可以用纯的 dom 方法来实现上面的功能。
- // 创建p
- var myp = document.createElement('p');
- // 创建一个文本节点
- var myt = document.createTextNode('one more paragraph')
- myp.appendChild(myt);
- // 创建一个STRONG元素
- var str = document.createElement('strong');
- str.appendChild(document.createTextNode('bold'));
- // 把STRONG元素添加到P中
- myp.appendChild(str);
- // 把P元素添加到BODY中
- document.body.appendChild(myp);
- //结果<p>one more paragraph<strong>bold</strong></p>
- cloneNode()
另一种新建节点的方法是,我们可以用 cloneNode 来复制一个节点。cloneNode() 可以传入一个 boolean 参数。如果为 true 就是深度复制,包括他的子节点,false,仅仅复制自己。 首先获取要复制的元素。
- var el = document.getElementsByTagName('p')[1];//<p><em>second</em> paragraph</p>
先不用深度复制。
- document.body.appendChild(el.cloneNode(false))
我们发现页面并没有变化,因为仅仅复制的是元素 p。和下面的效果一样。
- document.body.appendChild(document.createElement('p'));
如果用深度复制,包括 p 下面所有的子节点都会被复制。当然包括文本节点和 EM 元素。
- document.body.appendChild(el.cloneNode(true))
insertBefore() 用 appendChild,就是把元素添加到最后。而 insertBefore 方法可以更精确控制插入元素的位置。
- elementNode.insertBefore(new_node,existing_node)
实例
- document.body.insertBefore(
- document.createTextNode('boo!'),
- document.body.firstChild
- );
意思就是新建一个文本节点,把它作为 body 元素的第一个节点。 删除节点
要从 DOM 树删除一个节点,我们可以使用 removeChild(). 我们来看看要操作的 HTML
- <body>
- <p class="opener">
- first paragraph
- </p>
- <p>
- <em>
- second
- </em>
- paragraph
- </p>
- <p id="closer">
- final
- </p>
- <!-- and that's about it -->
- </body>
来看看下面代码,删除第二段
- var myp = document.getElementsByTagName('p')[1];
- var removed = document.body.removeChild(myp);
removed 节点就是删除的节点。以后还可以用这删除的节点。 我们也可以用 replaceChild() 方法。这个方法是删除一个节点,并用另一个节点替代。当执行上个删除节点操作之后,结果如下
- <body>
- <p class="opener">
- first paragraph
- </p>
- <p id="closer">
- final
- </p>
- <!-- and that's about it -->
- </body>
我们来看看 replaceChild 的使用。我们把上一个删除节点来替代第二个 p
- var replaced = document.body.replaceChild(removed, p);
和 removeChild 返回一样。replaced 就是移除的节点。现在结果为
- <body>
- <p class="opener">
- first paragraph
- </p>
- <p>
- <em>
- second
- </em>
- paragraph
- </p>
- <!-- and that's about it -->
- </body>
来源: http://www.phperz.com/article/17/0413/268713.html