Web页面(Web Page)(也称为文档Document)
网页是一个动态的数据结构,可以通过JavaScript与之交互:访问并读取网页中的元素内容;修改网页的内容或结构等
使用文档对象模型DOM(Document Object Model),能够与代码所属的网页交互,从而能够编写出动态的网页
JavaScript与网页的交互——文档对象模型DOM
JavaScript与HTML是不同的事物:JavaScript是代码,HTML是标记
它们如何交互?——通过网页的表示,即文档对象模型DOM实现
在浏览器内部,使用文档对象模型DOM来表示网页
- 浏览器在加载并分析HTML时,还会创建DOM,并将一系列表示标记的对象存储在DOM中。
- JavaScript可与DOM交互,修改其中的元素对象
- JavaScript修改DOM时,浏览器动态地更新网页,从而用户看到动态变化的网页
文档对象模型DOM是一颗树:
根部为document
对象
其余部分为HTML标记中的各个元素对象
在HTML中,网页由元素组成(
<div>
、<h1>
、<h2>
、<p>
等)
可以使用id唯一标识一个元素;使用类(class)标识一组元素
在JavaScript和CSS中,可以根据id或类选择特定的元素,并对其进行操作
确保网页(和DOM)加载完毕后再运行代码
使用JavaScript处理DOM时,确保在网页完全加载后再运行JavaScript代码(这意味这DOM一定已经被创建)
解决方案一:将<script>
元素放在<body>
末尾
不要将包含JavaScript代码的<script>
元素放在网页的<head>
元素中!
务必将<script>
元素放在<body>
元素的末尾,以确保在网页完全加载后(这意味这DOM一定已经被创建),再修改DOM
解决方案二:事件处理程序(回调函数)(详见文末)
window
是JavaScript内置对象,表示浏览器窗口
window.onload()
方法,用于指定[仅在网页加载完毕后才会运行]的代码
网页加载完毕后,将立即自动调用window
对象的onload
属性指向的事件处理程序
利用这一特性,将需要等待网页加载完毕后才执行的代码封装到一个函数(事件处理程序)中,并将这个函数(事件处理程序)赋给对象window
的属性onload
<script>
function init(){
//init函数中包含所有[需要在网页加载完毕后才执行]的代码
//与处理DOM有关的代码,都需要在网页加载完毕后才执行
var mood = document.getElementById("boy");
mood.innerHTML = "I am happpy!";
}
window.onload = init;//将init函数赋值给属性window.onload
</script>
document对象
- 在JavaScript代码中,使用
document
对象来访问DOM document
对象包含用来访问和修改DOM的属性和方法
document.getElementById
方法:根据id选择元素
传入某个元素的id(一个字符串),返回网页中相应的那个元素对象
当传入的id不存在,返回null
document.getElementsByClassName
方法:根据类选择元素
传入类名,返回属于这个类的元素集合
document.getElementsByTagName
方法:根据标签名选择元素
传入标签名,返回与这个标签名匹配的元素集合
document.getElementsByName
方法:根据name选择元素
document.querySelector
方法:用选择器查找元素
传入一个选择器(类似于CSS选择器),返回匹配的第一个元素
例如var li = document.querySelector("playlist .song");
查找id为playlist的元素,再在其中查找第一个class特性为song的元素
document.querySelectorAll
方法:用选择器查找元素
传入一个选择器,以Nodelist返回匹配的所有元素
注意,后面两个名称中带Elements
(而非Element
)的方法,可能返回多个元素
具体是返回NodeList
对象,访问元素的方法类似数组,但添加和删除元素时NodeList
与数组则完全不同
NodeList
对象是一个Node
集合, 而Node
就是DOM树中的element
对象
元素对象
这里所说的“元素内容”、“元素特性”,都是对于HTML的各种标签元素(
div
、h
等)而言的
在JavaScript中,我们统一化地处理:将HTML元素(通过DOM)化为对象,称为元素对象
牢记:元素对象本质是一个对象
i.e.元素对象包含一些属性和方法,可以使用它们来读取和修改元素的内容
因此,后文的id
“元素特性”、innerHTML
“元素内容”、 getAttribute
方法…等等关于元素的一切,它们本质上都是元素对象的属性,并非高深莫测的东西,不要被迷惑!
因此,用getAttribute方法“获取
元素
的id特性
的值”,等价于访问(元素)对象
的id属性
i.e.elem.getAttribute("id")
等效于elem.id
(有细微差别,见后文getAttribute)
注意:每当获取值时,先确认获得了期望的值
getElementById
、getAttribute
当目标不存在时都会返回null
因此,获取元素时,务必检查返回的是否是null
设置元素内容:innerHTML属性
innerHTML
包含元素的文本内容和全部嵌套的HTML元素
i.e.innerHTML
表示元素内部的HTML(如<p>
元素可能包含文本和<img>
元素)- 修改元素对象的
innerHTML
属性的值,可修改元素的内容 - 通过修改
innerHTML
来修改元素时,所做的修改将立即在网页中反映出来
var mood = document.getElementById("boy");//获取元素对象
mood.innerHTML = "I am happpy!";//修改元素对象的innerHTML属性
innerHTML
直接照搬从该元素起始标签<p>
到终止位置</p>
的全部内容(包含html标签和换行符、制表符)
另有innerText
方法,提取从元素起始标签终止位置的全部文本内容
获得元素特性:getAttribute方法/句点表示法
Object.getAttribute(要获取的特性的名称)
getAttribute
方法用于获取元素的特性值
元素对象的特性也是属性,即elem.getAttribute(“id”)等效于elem.id
当传入的特性不存在, getAttribute
返回null
当传入的属性名不存在,elem.属性名
返回undefined
设置元素特性:setAttribute方法
setAttribute
方法用于设置元素的特性值
Object.setAttribute(要修改的特性的名称,要设置的特性值)
当传入特性不存在,将自动在元素中创建它
(1)设置元素特性
Elem.setAttribute("id","1")
(2)设置对象属性Elem.id="1"
这两种方式有什么区别?
结论:统一用setAttribute()
更好
详解:见JavaScript学习笔记——HTML中的元素与JavaScript中的对象,有何区别?
删除元素:removeNode和removeChild方法
要删除的元素.removeNode(true);
removeChild()
方法删除父元素下的某个子元素
要删除的元素.parentNode.removeChild(要删除的元素);删除某个元素本身
ps. 删除元素时,将同时删除其所有子元素
添加新元素:createElement、appendChild方法
已有的父元素.removeNode(要添加的子元素);
var newItem=document.createElement("li");
newItem.innerHTML="Something New";//新建一个<li>元素,内容为字符串
var ul=document.getElementById("playlist");
ul.appenChild(newItem);//新元素作为子节点加入
获取某个元素的子元素、兄弟元素、父元素等
childNodes
属性返回节点的子节点集合(NodeList
对象)
children
属性返回节点的子节点集合(数组
)
还有firstChild
、firstElementChild
、lastChild
等
注意,
childNodes
、firstChild
、lastChild
等返回的结果中包含了很多意想不到的东西,最好通过nodeType
将返回集合过滤一遍再进行使用
元素.parentNode.children[]
数组含有所有兄弟节点
previousSibling
、previousElementSibling
获取上一个兄弟节点
nextSibling
、nextElementSibling
获取下一个兄弟节点
parentNode
、parentElement
获取父节点
offsetParent
获取所有父节点
事件处理程序(回调函数)
在JavaScript中,在某事件(如网页加载完毕)发生后,能够“感应”到事件发生的对象能够在第一时间通知程序员
这种通知的具体实现方式:了解事件的对象提供一个函数,事件发生后,这个对象将通过调用这个函数来通知我们,而我们可以自定义这个函数
这就是回调函数(callback),也称事件处理程序(event handler)
由此我们可以处理很多不同类型的事件
例如
可使用window
对象的onload
属性给加载事件指定事件处理程序(回调函数)
网页加载完毕后,将立即调用window
对象的onload
属性指向的事件处理程序
验证一下所学知识
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Just a Generic Page</title>
</head>
<body>
<h1>Just a generic heading</h1>
<p id="msg">//id为"msg"的元素
I'm just an obligatory paragraph.
</p>
<script>
function init(){//处理DOM有关的代码,用事件处理程序确保在网页加载后运行
var elem=document.getElementById("msg");
//验证:元素对象的特性也是属性,即elem.getAttribute("id")等效于elem.id
var attr1=elem.getAttribute("id");
console.log(attr1);//输出"msg"
var attr2=elem.id;
console.log(attr2);//输出"msg"
var attr3=elem[id];
console.log(attr3);//报错,应该写为var attr3=elem["id"];
//未解决的问题
//attr1.test=false;
//console.log(attr1.test);
//为什么显示undefined?
//显示元素对象的所有属性
for (var prop in elem){
console.log(prop+": "+elem[prop]);
}
//部分输出:
//id: msg
//
//innerHTML:
// I'm just an obligatory paragraph.
//
//outerHTML: <p id="msg">
// I'm just an obligatory paragraph.
// </p>
//innerText: I'm just an obligatory paragraph.
//outerText: I'm just an obligatory paragraph.
};
window.onload=init;//网页加载完后执行事件处理程序init
function wakeUpUser() {//与DOM无关的代码,不必放入事件处理程序
alert("Are you going to stare at this boring page forever?");
}
setTimeout(wakeUpUser, 5000);
</script>
</body>
</html>
注意最后控制台的输出:
innerHTML
直接照搬从该元素起始标签<p>
到终止位置</p>
的全部内容(包含html标签和换行符、制表符)
innerText
提取从该元素起始标签<p>
到终止位置</p>
的全部文本内容(不包含html标签和换行符、制表符)
outerHTML
与outerText
同理