参考资料:《JavaScript DOM 编程艺术》
1.DOM提供的四种方法
- getElementsById()
- getElementsByTagName()
- getAttribute()
- setAttribute()
简单示例代码:
Test
This is a paragraph.
- 1
- 2
- 3
1.1 getElementById()
document.getElementById(id)
用于返回给定id属性值的元素节点相对应的对象,可以用typeof验证alert(typeof document.getElementById("test"));
typeof操作符会告诉我们它的操作数是字符串/数值/函数/对象等等。
在此处id值为“test”的是ul,它是一个对象,于是能看到显示着“object”的弹出框。
1.2 getElementsByTagName()
element.getElementsByTagName(tag)
getElementsByTagName()将返回一个对象数组
var item = document.getElementsByTagName('li'); //即将这个数组赋给一个变量
for(var i = 0; i < item.length; i++) {
alert(typeof item[i]); //有三个li对象,数组长度即为3,出现三次显示“object”的弹出框。
}
alert(item.length); //弹出框显示3
通配符的使用:
将通配符“*”作为参数,意味着文档里的每个元素都在函数所返回的数组里占有一席之地。
如可使用alert(document.getElementsByTagName("*").length);
知道文档里共有多少个元素节点。
1.3 getAttribute()
找到元素后,可利用getAttribute()将元素各个属性的值查询出来。此方法是一个函数,参数为你打算查询的属性的名字。
object.getAttribute(attribute)
var para = document.getElementsByTagName('p');
for(var i = 0; i < para.length; i++) {
var title_text = para[i].getAttribute('title');
if(title_text)
alert(title_text);
1.4 setAttribute()
setAttribute()与上面三个方法的不同之处在于它可以对属性节点的值做出修改,与getAttribute()一样,只能在找到元素后使用。
setAttribute()方法有两个参数
object.setAttribute(attribute, value)
var test = document.getElementById('line1');
alert(test.getAttribute("title")); //弹出框提示“null”
test.setAttribute("title", "just a test"); //此处对li的title值做出修改
alert(test.getAttribute("title")); //弹出框提示“just a test”
需要注意的是,setAttribute()做出的修改不会体现在源代码里,这种现象是由DOM的工作模式决定的:先加载文档的静态内容,再以动态形式进行刷新,动态的刷新不能影响文档的静态内容。
2.通过简单的案例了解DOM提供的其他属性
这里用到几个属性:
- childNodes属性
- nodeType属性
- nodeValue属性
- firstChild 和 lastChild属性
示例代码:
Visit Gallery
Where do you want to go?
Choose a place you want to go.
JS部分代码:
window.onload = showpic;
function showpic(whichpic) {
var source = whichpic.getAttribute("href");
var placeholder = document.getElementById("placeholder");
placeholder.setAttribute("src", source);
var text = whichpic.getAttribute("title");
var description = document.getElementById("description");
description.firstChild.nodeValue = text;
}
2.1 childNodes属性
childNodes属性让我们可以从给定文档的节点树中把任何一个元素的所有子元素检索出来,它将返回一个数组,这个数组包含给定元素节点的所有子元素。
假如我们检索某个文档body元素的全体子元素,首先通过getElementByTagName()的方法得到body元素。
var body_element = document.getElementByTagName('body')[0];
alert(body_element.childNodes.length);
将弹出一个提示框,显示body元素的子元素的总数,这个数字很大,因为ChileNodes属性返回的数组中包含所有类型的节点,甚至连空格和换行都会被解释为节点。但是怎么得到一个有用的数值呢,于是就用到了下面的nodeType属性。
2.2 nodeType属性
节点 | 属性值 |
---|---|
元素节点 | 1 |
属性节点 | 2 |
文本节点 | 3 |
nodeType的调用语法:node.nodeType
我们可以用nodeType属性来区分文档里的各个节点,因为nodeType的返回值是数字,不同的数字代表不同的含义。
节点 | 属性值 |
---|---|
元素节点 | 1 |
属性节点 | 2 |
文本节点 | 3 |
这意味着,可以让函数只对某种特定类型的节点进行处理。
2.3 nodeValue属性
如果要改变某个文本节点的值,就要使用nodeValue属性,它的用途是检索和设置节点的值。需要注意的是,在用nodeValue属性检索某个对象的值时,比如alert(description.nodeValue);我想要这个
里面的文本值,但这个调用会返回一个NULL的空值。
包含在
里面的文本是另一种节点,它在DOM里是
元素的第一个子节点,所以想获得
元素的文本内容,就要检索它的第一个子节点的nodeValue属性值。
下面才是正确的用法:
alert(description.childNodes[0].nodeValue);
这个调用的返回值是“Choose a place you want to go.”
2.4 firstChild 和 lastChild属性
数组元素node.childNodes[0] = firstChild
数组元素node.childNodes[node.childNodes.length-1] = lastChild
在示例代码中:
function showpic(whichpic) {
var source = whichpic.getAttribute("href");
var placeholder = document.getElementById("placeholder");
placeholder.setAttribute("src", source);
var text = whichpic.getAttribute("title");
var description = document.getElementById("description");
description.firstChild.nodeValue = text;
}
实现了:
1.点击链接,就能在此页面中显示对应的图片,并且不会跳转到新的页面去。
在这里,定义了两个变量source,placeholder。
source存储被点击的链接所对应的图片地址,通过getAttribute()方法获得;placeholder代表着要展示图片的占位图,通过getElementById()方法获得。
第四行中,使用了setAttribute()方法对placeholder元素的src属性进行刷新,给它赋予了新值,即为被选中图片的地址。
为什么不会跳转到新界面:在HTML中使用了事件处理函数onclick(),在点链接的时候触发函数showpic();并且return false,使得这个链接在被点击时的默认行为不会发生。
2.点击链接的同时,在最下方显示相应的文本。
在这里也定义了两个变量,text和description,text保存着对应的title值,description通过getElementById()方法获得,代表着返回的
元素。
在点击链接触发相应函数时,
中第一个子元素(即文本)的nodeValue值就会被更新为text代表的文本值,于是可以在下方显示出不同的文本。
3.Others
在DOM编程中用到的原则和良好的习惯:
- 预留退路
- 分离JavaScript
- 向后兼容性
把多个JavaScript函数绑定到onload事件处理函数中:
如果写成
window.onload = afunction;
window.onload = bfunction;
第二条指令会取代第一条指令。所以可以下面的写法,用一个匿名函数来容纳这两个函数:
window.onload = function() {
afunction();
bfunction();
}
还有一个方法,利用addLoadEvent函数:
addLoadEvent(afunction);
addLoadEvent(bfunction);
这个函数完成的操作是:{
把现有的window.onload事件处理的函数存入变量oldonload;
->如果在这个处理函数上还没有绑定任何函数,就把新函数添加给它
->如果在这个处理函数上已经绑定了函数,就把新函数追加到现有指令的末尾。
}
addLoadEvent函数的代码清单是:
function addLoadEvent(func) {
var oldonload = window.onload;
if(typeof oldonload != 'function') {
window.onload = func;
}
else {
window.onload = function() {
oldonload();
func();
}
}
}
4.动态创建HTML内容
4.1 document.write()
document对象的write()方法可以方便快捷地把字符串插入到文档里。
4.2 innerHTML属性
可以用来读,写某给定元素里的HTML内容。
在需要把一大段HTML内容插入一个网页时,innerHTML更适用。
4.3 DOM提供的其他方法
方法 | 用途 |
---|---|
createElement() | 创建新元素 |
appendChild() | 让新创建的节点成为其他元素的子节点 |
createTextNode() | 创建文本节点 |
insertBefore() | 把一个新元素插入到现有元素的前面 |
示例:
在HTML文档中存在着一个空的div元素,怎样利用JavaScript在其中添加一行文本“Hello World”?
按照思路,可分为如下几个步骤:
1.创建一个元素p节点
2.创建一个文本节点
3.把这个文本节点追加到第一步产生的p节点中
4.把这个p节点追加到文档中的div元素里
function CreatP() {
var para = document.createElement("p");
//用para来存储生成的p节点,相当于一个指针
var text = document.createTextNode("Hello World!");
para.appendChild(text);
//生成一个文本节点,并将它添加到p节点中
var testdiv = document.getElementById("testdiv");
//得到div元素
testdiv.appendChild(para);
//把p节点添加到div中
}
注意:
在使用createElement()和createTextNode()方法创建出的节点只是JavaScript世界里的“孤儿”,必须还要用appendChild()或insertBefore()方法把它们插入某个文档的节点树才能让他们呈现在浏览器窗口里。
insertBefore():
在调用此方法时需要明确三件事:
1.想插入的元素(newElement)
2.插入到哪个目标元素的前面(targetElement)
3.这两个元素共同点父元素
调用语法:parentElement.insertBefore(newElement, targetElement)
利用上面的提到的方法,用JavaScript创建p和img对象,并且插入到ul元素的前面:
function Create() {
var placeholder = document.createElement("img");
placeholder.setAttribute("id", "placeholder");
placeholder.setAttribute("src", "../image/placeholder.jpg");
placeholder.setAttribute("alt", "placeholder");
var description = document.createElement("p");
var text = document.createTextNode("Choose a place you want to go.");
description.appendChild(text);
description.setAttribute("id", "description");
var gallery = document.getElementById("imageGallery");
gallery.parentNode.insertBefore(description, placeholder);
gallery.parentNode.insertBefore(placeholder, description);
//insertAfter(placeholder, gallery);
//insertAfter(description, placeholder);
//insertAfter函数是自己编写的函数,作用是把新元素插入到目标元素后面
}
insertAfter函数:
function insertAfter(newElement, targetElement) {
var parent = targetElement.parentNode;
if(parent.lastChild == targetElement) {
parent.appendChild(newElement);
}
else {
parent.insertBefore(newElement, targetElement.nextSibling);
}
}
5. 充实文档的内容
今天遇到一个问题,关于window.onload的用法。
根据示例敲出一段代码,HTML部分如下:
Definition table
To Create A Definition Table
Such as W3C means...
Such as BM means...
Such as JS means...
JS部分如下:
window.onload = display;
function display() {
var abbreviations = document.getElementsByTagName("abbr");
// if(abbreviations.length < 1)
// return false;
var dfs = new Array();
for(var i = 0; i < abbreviations.length; i++) {
var definition = abbreviations[i].getAttribute("title");
var key = abbreviations[i].lastChild.nodeValue;
dfs[key] = definition;
}
var dlist = document.createElement("dl");
for(key in dfs) {
var definition = dfs[key];
var dtitle = document.createElement("dt");
var dtitle_text = document.createTextNode(key);
dtitle.appendChild(dtitle_text);
var ddesc = document.createElement("dd");
var ddesc_text = document.createTextNode(definition);
ddesc.appendChild(ddesc_text);
dlist.appendChild(dtitle);
dlist.appendChild(ddesc);
}
var header = document.createElement("h2");
var head_tetx = document.createTextNode("Abbreviations:");
header.appendChild(head_tetx);
document.body.appendChild(header);
document.body.appendChild(dlist);
}
这里实现的作用是,在页面中生成一个缩略表,显示缩略词和其含义。用到的方法都是前面提到过的,就不分析了。
问题是在用到window.onload时,写成了window.onload = display();
这时整个页面都加载不出来,而把display后面的括号去掉后,就可以加载出来了。
一个括号的作用还是蛮大的,最后我的理解是:
window.onload是在整个页面加载完成时,才会使用其绑定的函数,而加了括号之后,表示“立刻调用”,但是这个时候页面还没有加载完,全部的DOM节点也没有形成,在函数中对元素的使用和修改都是无法进行的,所以页面无法加载。
参考博客