JavaScript DOM笔记02

DOM 基本操作

系列文章

获取结点

有3种方式可以获取结点,分别通过元素ID、标签名和类名。

DOM提供了 getElementById(name) 方法,该方法返回那个与对应 id 属性值匹配的元素结点对应的唯一结点对象。

它是 document 对象包含的方法,包含的唯一参数是需要获取的 id 值字符串。

以下是一个示例:

document.getElementById("content")

可以获取到 id 为 "content" 的结点元素。

可以通过 getElementsByTagName(tag) 方法获取所有标签为 tag 的元素。

该方法返回的是数组,数组内的元素个数可能是0个、1个或多个。

标签名可以是具体的HTML标签,也可以是通配符 "*" ,注意它们总是放在引号内。

注意:.getElementById() 方法需要由 document 对象调用,但 .getElementsByTagName() 方法可以由包括 document 及其 .getElementById() 方法返回的对象调用。

以下代码分别用于统计整篇文章的结点(包括 <html> 结点)个数,以及遍历 id 为 "navbar" 中的列表项:

var nodes_count = document.getElementsByTagName("*").length;
var items = document.getElementById("navbar").getElementsByTagName("li");;
for (var i = 0; i < items.length; i++) {
    /* ... */
}

类似通过 id 获取结点,同样可以使用 getElementsByClassName(class) 方法获取所有具有相同类名的元素。该方法自然返回数组。

使用该方法还能获取具有多个类名的元素,只需要在参数字符串内用空格将多个类名隔开就行了,这和HTML标签的表现一致。

部分旧的浏览器可能不支持该方法,以下同名函数实现了相同的功能,可以兼容旧的浏览器,如果浏览器已经支持该方法,则优先调用它:

function getElementsByClassName(node, classname) {
    if (node.getElementsByClassName) {  // using current method
        return node.getElementsByClassName(classname);
    }
    else {
        var results = new Array();
        var elems = node.getElementsByTagName("*");
        for (var i = 0; i < elems.length; i++) {
            if (elems[i].className.indexOf(classname) != -1) {
                results[results.length] = elems[i];
            }
        }
        return results;
    }
}

获取和设置属性

得到了需要的结点以后可以对结点进行操作,例如获取和设置它的属性。

使用结点对象的 .getAttribute(attribute) 可以获取结点属性对应的值,参数 attribute 为查询的属性名。该方法只能由结点对象调用,不能由 document 对象调用。

如果查询的结点不存在该属性,则该方法会返回 null 值。null 是JavaScript中的一个特殊值,含义是“空值”。

类似地可以使用 .setAttribute(attribute, value) 来为节点设置属性值。如果该方法作用在一个本身具有属性的元素结点上,这个属性的值就会被直接覆盖。

以下代码为文章中的所有可用链接添加一个 title 属性:

var links = document.getElementsByTagName('a');
for (var i = 0; i < links.length; i++) {
    if (links[i].getAttribute("href") != null) {
        links[i].setAttribute("title", links[i].getAttribute("href"));
    }
}

通过 .setAttribute() 对文档进行修改后,如果通过浏览器查看源代码会发现源文档没有被改变。DOM的工作方式是:先加载文档的静态内容,再动态刷新,这种对页面内容的刷新不需要重新加载页面。

事件处理函数

事件处理函数的作用是在特定事件发生时调用相应的JavaScript代码。

例如,如果想在光标悬浮到某一元素时触发一个动作,需要使用 onmouseover 事件处理函数;如果想在光标离开到某一元素时触发,需要使用 onmouseout ;在用户点击某个链接时触发,需要使用 onclick

可以将这些事件处理函数放在元素结点中,通过属性添加事件处理函数的语法为:

<tag event="statements">...</tag>

例如:

<ul>
    <li><a href="./img01" onclick="showPic();">show first picture</a></li>
    <li><a href="./img02" onclick="showPic();">show second picture</a></li>
</ul>

使用 this 关键字可以指代当前对象。如果将其放入结点的事件处理函数中,this 指代“当前结点”。

当点击链接时,默认的点击行为就会被调用,跳转到链接页面中。如果要拦截这种默认行为,可以在事件处理函数中返回 false ,这样 onclick 事件处理函数就会认为这个链接没有被调用。

以下是改进后的代码:

<ul>
    <li><a href="./img01" onclick="showPic(this); return false;">show first picture
        </a></li>
    <li><a href="./img02" onclick="showPic(this); return false;">show second picture
        </a></li>
</ul>

结点对象的属性

结点元素对象的 childNodes 属性可以用来获取任何一个元素的所有子元素,是一个包含这个元素全部子元素的数组。它不包含嵌套的结点。

如果要让函数在页面加载时执行,需要使用窗口对象 windowonload 事件处理函数。

childNodes 属性返回的数组包含所有类型的结点,而不仅仅是元素结点。文档里几乎每一个东西都是一个结点,包括空白符,而它们也全部包含在 childNodes 属性所返回的数组中。

每一个结点都有一个 nodeType 属性,它的值是一个数字,其含义如下:

结点的 nodeValue 属性用来获取和设置一个结点的值。

结点对象本身的 nodeValuenull 空值,元素包含的文本是另一种结点,且是元素的第一个子结点。

因此,如果想得到每个段落的文本,可以使用:

var paragraphs = document.getElementsByTagName('p');
for (var i = 0; i < paragraphs.length; i++) {
    var content = paragraphs[i].childNodes[0].nodeValue;
    /* ... */
}

可以通过结点对象的 firstChild 访问第一个子结点对象,或通过 lastChild 访问最后一个子结点对象。即有如下关系:

node.lastChild == node.childNodes[node.childNodes.length - 1];
node.firstChild == node.childNodes[0];