《JavaScript DOM 编程艺术》读书笔记
文章目录
事件处理函数
在预定事件发生时让预先安排好的JavaScript代码开始执行,即“触发一个动作”。
例如:onclick,onmouseover,onmouseout等等。
语法:event = "JavaScript statement(s)"
, JavaScript代码是包含在双引号
中的,可以把任意数量的JavaScript语句放在这对引号之间,分号
隔开即可。
机制:给某个元素添加事件处理函数后,一旦发生预定事件,相应的JavaScript代码就执行,执行后可以返回一个结果
,这个结果被传递回事件处理函数
。
利用这个机制,我们可以让动作没有触发,但是却能执行触发之后的JavaScript代码。比如书中的“JavaScript美术馆例子”:onclick事件中,点击链接执行一段预定代码,在代码后加上"return false;"
,那么代码依旧被执行,但是页面却不会跳转,因为返回false给事件处理函数,认为“这个链接没有被点击”。代码如下。
<body>
<h1>Snapshots</h1>
<ul>
<li><a href="F:\壁纸\973279.jpg" onclick="showPic(this); return false;">Aquaman</a></li>
<li><a href="F:\壁纸\923047.jpg" onclick="showPic(this); return false;">Forest</a></li>
<li><a href="F:\壁纸\486147.jpg" onclick="showPic(this); return false;">Boat</a></li>
<li><a href="F:\壁纸\340480.jpg" onclick="showPic(this); return false;">Cat</a></li>
</ul>
<img src="F:\壁纸\973279.jpg" id="placeholder">
</body>
getElementsByTagName()方法
- 返回
对象数组
:数组每个元素都是一个对象,含有属性
和方法
- 利用
length属性
:getElementsByTagName().length得知数组元素个数 - 通配符
*
的使用:某个文档的总元素节点个数:document.getElementsByTagName(“*”) 具体元素
包含元素个数:同理可以联合getElementById()或者其他DOM选取元素
的方法,得知某个具体元素包含多少元素节点.
例子:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<div id="first">
<span></span>
<span></span>
<span></span>
<span></span>
</div>
<div id="second">
<ul>
<li></li>
<li></li>
<li></li>
</ul>
<ul>
<li></li>
<li></li>
<li></li>
</ul>
<ul>
<li></li>
<li></li>
<li></li>
</ul>
<ul>
<li></li>
<li></li>
<li></li>
</ul>
</div>
<script type="text/javascript">
//javascript here
</script>
</body>
</html>
var total = document.getElementsByTagName("*");
console.log("the number of nodes: " + total.length);
//28 整个文档的所有节点,包括根节点html
var div$first =document.getElementById("first");
var total = div$first.getElementsByTagName("*");
console.log(total.length);
//4 #first节点包含的元素个数,不包括#first节点自己
childNodes
- 返回
对象数组
:数组包含给定元素节点
的全体子元素
- 语法:
element.childNodes
- 返回所有类型的节点:包括
元素节点
、属性节点
和文本节点
- 快速选择body元素:
document.body
,代替document.getElementsByTagName("body")[0]
事实上,文档里几乎所有东西都是一个节点,甚至空格和换行符都被解释为节点,而它们都包含在childeNodes返回的数组当中,所以childNodes返回的结果可能和我们预想的不一样。
使用nodeType属性
区分文档里的各个节点。
nodeType
nodeType属性总共有12种可取值,但仅有3中有使用价值:
元素节点
返回1属性节点
返回2文本节点
返回3
nodeValue与innerHTML的区别
nodeValue
是节点的值,其中属性节点
和文本节点
是有值的,而元素节点没有值
。innerHTML
以字符串形式返回该节点的所有子节点及其值
例子:
<p id="example" title="texts">
这是一段文本
<span></span>
</p>
var p = document.getElementById("example");
console.log(p.nodeValue); //null p是元素节点,没有节点值
console.log(p.innerHTML); //p标签内部的所有子节点和值
这里又会牵涉到innerHTML和document.write()的区别:
innerHTML
是在元素中添加HTML文档的内容,只改变选中的元素内部
,不会覆盖整个文档document.write()
是写进整个文档,覆盖原来整个文档
的内容
把多个JavaScript函数绑定到onload上
有时候函数func1()会对DOM文档树进行操作,如果DOM不完整
,则函数不能正常执行,必须要让函数在网页加载完成之后
才能执行,而网页加载完毕时会触发一个onload事件
。
window.onload = func1;
即可解决问题,不过如果有多个函数func2()、func3()…
window.onload = func1; window.onload = func2;
func2将会取代func1,
因为每个事件处理函数只能绑定一条指令。
于是可以创建一个匿名函数
来包含这些函数:
window.onload = function() {
func1();
func2();
}
也可以使用更加通用的方法——addLoadEvent()
,这是个自编的函数:
function addLoadEvent(func) {
var oldonload = window.onload;
if (typeof window.onload != 'function')
window.onload = func;
else {
window.onload = function() {
oldonload();
func();
}
}
}
相当于把那些将在页面加载完毕时执行的函数创建为一个队列,把刚刚那两个函数加入到队列里,即
addLoadEvent(func1);
addLoadEvent(func2); //不加(),因为不是调用,而是引用这个函数名
DOM Core 和 HTML-DOM
获取和设置元素属性的时候,我发现,有些属性可以直接使用ele.propertyname
的方式获取和设置,有些则不行,要通过getAttribute()和setAttribute()进行操作,现在可以对这个进行解释了。
诸如
getElementById()/getElementsByTagName()/setAttribute()/getAttribute()
等方法都是DOM Core
的组成部分。它们并不专属于JavaScript
,支持DOM的任何一种程序设计语言都可以使用它们。
而在使用JavaScript和DOM编写脚本时,还有许多属性可以选用,这些属性专属于HTML-DOM
,也就是之前讲的简化书写方式
,诸如document.body/document.forms/document.images/element.src
等等。
DOM 操作节点
一个文档就是一个DOM节点树,在节点树上增加内容,就必须插入新的节点,而对DOM节点树的操作是以动态的方式
创建HTML内容——并不是真的“物理上”创建HTML内容,而是修改DOM节点树
。
关于节点,回顾有三种:元素节点、属性节点、文本节点。
创建元素节点:createElement()
- 创建一个
元素节点
:document.creatElement("p");
创建文本节点:createTextNode()
- 创建一个
文本节点
:document.creatTextNode(text);
插入到DOM节点树中:appendChild()
- 把新元素插入节点树:
parent.appendChild(child);
例如:
和下面这种不赋值变量引用是等价的:var para = document.creatElement("p"); var target = document.getElementById("target"); target.appendChild(para);
可知使用document.getElementById("target").appendChild(document.creatElement("p"));
一些变量引用父节点和子节点
更加容易阅读和理解。
如何设置属性节点?
-
setAttribute()
直接在DOM节点添加属性,用法比较简单:
element.setAttribute(attributename,attributevalue)
例子:
<p > <span>1</span>, <span>2</span> <span>3</span> <span>4</span> <span>5</span> </p>
在p元素节点添加title属性:
var p=document.getElementsByTagName('p')[0]; p.setAttribute('title','one to five');
-
creatAttribute()
效果一样,但是用法复杂些:element.setAttributeNode(attributenode)
例子:
var ti=document.createAttribute('title');//创建独立的属性节点 ti.nodeValue='one to five';//设置属性节点值 ti.value也行 var p=document.getElementsByTagName('p')[0]; p.setAttributeNode(ti)//追加的设置属性节点
insertBefore()方法
DOM提供的方法,将一个元素插入到一个现有元素前面,调用时需要知道三个节点:
- 父节点
- 新节点
- 目标节点
语法:parentElement.insertBefore(newElement, targetElement);
例子:
var gallery = document.getElementById("imagegallery");
gallery.parentNode.insertBefore(placeholder, gallery);
其中parentNode属性
返回父元素。
insertAfter()方法
DOM本身没有提供insertAfter()方法,但是我们可以自己写一个:
function insertAfter(newElement, targetElement) {
var parent = targetElement.parentNode;
if(parent.lastChild == targetElement) {
parent.appendChild(newElement);
}
else {
parent.insertBefore(newElement, targetElement.nextSibling);
}
}
其中,nextSibling属性
返回相邻下一个兄弟节点,lastChild
返回最后一个孩子节点,同理firstChild
返回第一个孩子节点。
cloneNode()
var node=document.getElementById("myList2").lastChild.cloneNode(true);
document.getElementById("myList1").appendChild(node);
参数true:
可选。该方法将复制并返回调用它的节点的副本。如果传递给它的参数是 true,它还将递归复制当前节点的所有子孙节点。否则,它只复制当前节点。
className和classList
-
className 属性
设置或返回
元素的 class 属性。还可以添加class。返回值为字符串
。
例如:element.className += “test1 test2”; -
classList 属性返回元素的类名,作为 DOMTokenList
对象
。该属性用于在元素中添加,移除及切换 CSS 类。
classList 属性是只读的,但可以使用
add()
和remove()
方法修改它。例如:element.classList.add(“class1”, “class2”, “class3”);
<body>
<div class="haha look another"></div>
<script type="text/javascript">
var div = document.getElementsByTagName("div")[0];
console.log(div.classList);
</script>
</body>
结果为:
【待更新…】