是JS操作HTML和CSS的桥梁;
基本概念
Document Object Model文档对象模型;是JS操作HTML文档的接口
最大的特点:将文档表示为节点树;“节点思维”
节点分类
元素节点、属性节点、文本节点
访问节点
指得到/获取页面上的元素节点
document对象
DOM的功能几乎都封装在了document对象中
也表示整个HTML文档
是DOM节点树的根
常用方法
方法 | 功能 | 兼容性 |
---|---|---|
document.getElementById() | 通过id得到元素 | IE6 |
document.getElementsByTagName() | 通过标签名得到元素数组 | IE6 |
document.getElementsByClassName() | 通过类名得到元素数组 | IE9 |
document.queryselector() | 通过选择器得到元素 | IE8部分兼容、IE9完全兼容 |
document.querySelectorAll() | 通过选择器得到元素数组 | IE8部分兼容、IE9完全兼容 |
getElementById()
若有多个相同id的元素只能得到第一个
<body>
<div id='box1'>我是盒子1</div>
<div id='box2'>我是盒子2</div>
<script>
//得到盒子1
var box1 = document.getElementById('box1');
//得到盒子2
var box2 = document.getElementById('box2');
</script>
</body>
getElementsByTagName()
得到数组
方便批量操控元素节点
<body>
<div id='box1'>
<p>我是段落1</p>
<p>我是段落2</p>
<p>我是段落3</p>
</div>
<div id='box2'>
<p>我是段落4</p>
<p>我是段落5</p>
<p>我是段落6</p>
</div>
<script>
//1)得到所有p标签数组
var ps = document.getElementsByTagName('p');
console.log(ps);
//2)得到box1中的p标签数组:先得到box1
var box1 = document.getElementById('box1');
var pss = box1.getElementsByTagName('p');
console.log(pss);
</script>
</body>
getElementsByClassName()
querySelector()
只能得到一个元素
若有多个元素符合条件,则只能得到第一个
<div id="box">
<p>我是段落</p>
<p class="spec">我是段落2</p>
<p class="spec">我是段落3</p>
<p>我是段落</p>
</div>
<script>
// 只能选择到第一个spec
var the_p = document.querySelector('#box .spec');
// 如何选择第二个spec
// 方法一:CSS3中的序号选择器
var the_p = document.querySelector('#box p:nth-child(2)');
// 方法二:得到数组
var the_p = document.querySelector('#box p');
console.log(the_p[1]);
</script>
querySelectorAll()
得到元素数组
注:
延迟运行
在测试DOM代码时,通常JS代码一定要写到HTML节点的后面,否则JS无法找到相应HTML节点
window.οnlοad=function(){}事件可使页面加载完毕后,再执行指定的代码
<script>
//给window对象添加onload事件监听;
//onload表示页面加载完毕;
//BOM中介绍window对象
Window.onload = function () {
//得到盒子1
var box1 = document.getElementById('box1');
//得到盒子2
var box2 = document.getElementById('box2');
console.log(box1);
console.log(box2);
}
</script>
<body>
<div id='box1'>我是盒子1</div>
<div id='box2'>我是盒子2</div>
</body>
节点关系
关系 | 考虑所有(文本、元素、属性、注释等)节点 | 只考虑元素节点,IE9开始兼容 |
---|---|---|
子节点 | childNodes | children |
父节点 | parentNode | 同 |
第一个子节点 | firstchild | firstElementChild |
最后一个子节点 | lastchild | lastElementChild |
前一个兄弟节点 | previoussibling | previousElementsibling |
后一个兄弟节点 | nextsibling | nextElementsibling |
注:
在标准的W3C规范中,空白文本节点是节点,但IE8及以前不是
<div id="box">
<p>我是段落A</p>
<p id=para>我是段落B</p>
<p>我是段落C</p>
</div>
<script>
var box = document.getElementById('box');
var para = document.getElementById('para');
// box所有子节点
console.log(box.childNodes);//NodeList(7)
// box所有子元素节点
console.log(box.children);//HTMLCollection(3)
// para的所有父节点
console.log(para.parentNode);//div完整内容
// box第一个子节点
console.log(box.firstChild);//#text
// box第一个子元素节点
console.log(box.firstElementChild);//<p>我是段落A</p>
// box最后一个子节点
console.log(box.lastChild);//#text
// box最后一个子元素节点
console.log(box.lastElementChild);//<p>我是段落C</p>
// para前一个兄弟节点
console.log(para.previousSibling);//#text
// para前一个兄弟元素节点
console.log(para.previousElementSibling); //<p>我是段落A</p>
// para后一个兄弟节点
console.log(para.nextSibling);//#text
// para后一个兄弟元素节点
console.log(para.nextElementSibling);//<p>我是段落C</p>
</script>
常见的节点关系函数
<div id="box">
<p>我是段落1</p>
<p>我是段落2</p>
<p id="fpara">我是段落3</p>
我是文本
<!-- 我是注释-->
<p id="para">
我是段落4
<span>41</span>
<span>42</span>
<span>43</span>
</p>
<p>我是段落5</p>
<p>我是段落6</p>
</div>
<script>
var box = document.getElementById("box");
var para = document.getElementById("para");
var fpara = document.getElementById("fpara");
</script>
封装函数-返回所有子元素节点(兼容到IE6)
类似children(兼容到IE9)的功能
function getChildren(node) {
// 结果数组
var children = [];
// 遍历node节点的所有子节点
// 判断其nodeType属性是否为1,是1意味是元素节点,推入结果数组
for (var i = 0; i < node.childNodes.length; i++) {
if (node.childNodes[i].nodeType == 1)
children.push(node.childNodes[i]);
}
return children;
}
// 不要带引号,否则传入的不是节点而是字符串
console.log(getChildren(box));
console.log(getChildren(para));
封装函数-返回前面所有的元素兄弟节点(兼容到IE6)
类似previousElementSibling(兼容到IE9)的功能
function getElePresSibling(node) {
var pres = [];
// o-object对象,浅克隆,仅复制所考虑的对象,而不复制它所引用的对象
// 即仅复制node中的第一层节点,而不复制其下边的子节点
var o = node;
// 非null:前面有节点,也就是没有到头
// 遍历node的前面节点
while (o.previousSibling != null) {
if (o.previousSibling.nodeType == 1) {
pres.unshift(o.previousSibling);
}
// 让o成为它的第一个节点,类似递归,前一个的前一个往前找
// 最终前面所有节点都被找到并验证
o = o.previousSibling;
}
return pres;
}
console.log(getElePresSibling(para));
console.log(getElePresSibling(fpara));
封装函数-返回所有的元素兄弟节点
两种思路
思路一: 先找该元素父节点, 再找其所有元素子节点;
思路二: 找其前面的兄弟元素节点, 并找其后面的兄弟元素节点
function getAllEleSibling(node) {
// 前面的元素兄弟节点
var pres = [];
// 后面的元素兄弟节点
var nexts = [];
var o = node;
// 遍历node的前面节点
while (o.previousSibling != null) {
if (o.previousSibling.nodeType == 1) {
// unshift前端插入,push后端推入
pres.unshift(o.previousSibling);
}
o = o.previousSibling;
}
// o再次赋值
o = node;
// 遍历node的后面节点
while (o.previousSibling != null) {
if (o.previousSibling.nodeType == 1) {
// unshift前端插入,push后端推入
nexts.push(o.previousSibling);
}
o = o.previousSibling;
}
//前后两个数组合并并返回, concat数组合并
return pres.concat(nexts);
}
console.log(getAllEleSibling(para));
</script>
节点属性
nodeName
节点类型 | nodeName属性值 |
---|---|
元素节点 | 与标签名相同 |
属性节点 | 属性的名称 |
文本节点 | #text |
文档节点 | #document |
nodeValue
节点类型 | nodeValue属性值 |
---|---|
元素节点 | undefined 或 null |
文本节点 | 文本自身 |
属性节点 | 属性的值 |
nodeType
显示节点具体的类型
nodeType属性值 | 节点类型 |
---|---|
1 | 元素节点,例:<p> 、<div> |
3 | 文字节点 |
8 | 注释节点 |
9 | document对象/节点 |
10 | DTD节点 |
改变节点的HTML内容
两个相关属性:
innerHTML以HTML语法设置节点中的内容
innerText以纯文本的形式设置节点中的内容
<div id="box"></div>
<script>
var oBox = document.getElementById('box');
//1.1 改变节点中的纯文本内容
o.Box.innerHTML = '慕课网';
//1.2 可解析HTML格式(切记不能换行),以改变节点中的内容
o.Box.innerHTML = '<ul><li>牛奶</li><li> 咖啡</li></ul >';
// 2.1改变节点中的纯文本内容
o.Box.innerText = '慕课网';
// 2.2不能解析HTML格式,会直接输出
o.Box.innerText = '<ul><li>牛奶</li><li> 咖啡</li></ul >';
</script>
改变节点的CSS样式
实现形式:增添行内样式
// CSS属性写成驼峰形式
o.Box.style.backgroundColor = 'red';
// CSS属性值设置成完整形式
o.Box.style.backgroundImage = 'url(images/1.jpg)';
// 注意带单位
o.Box.style.fontsize = '32px';
改变节点的HTML属性
W3C属性
例:src、href等
实现形式:打点
<img id='pic' src="images/1.jpg" alt="">
<a id='link' href="http://www.baidu.com">去百度</a>
<script>
var opic = document.getElementById('pic');
var olink = document.getElementById('link');
opic.src = 'images/2.jpg';
olink.herf = 'http://www.imooc.com';
olink.innerText = '去慕课网';
</script>
非W3C属性
实现形式:setAttribute()设置、getAttribute()读取
<div class="box"></div>
<script>
var obox = document.getElementById('box');
// 直接打点方式失效
// obox.data - n='10';
// 设置自定义属性
obox.setAttribute('data-n', 10);
// 读取自定义属性
var n = obox.getAttribute('data-n');
alert(n);
</script>
创建节点
创建指定tagname的HTML元素
创建方法:document.createElement()
孤儿节点
新创建出的节点是“孤儿节点",需要挂载到DOM树上
挂载节点
appendChild()
挂载到最后
语法:父节点.appendChild(孤儿节点);
insertBefore()
挂载到“标杆子节点”之前
语法:父节点.insertBefore(孤儿节点,标杆节点);
<div id="box">
<p>我是原段落1</p>
<p>我是原段落2</p>
<p>我是原段落3</p>
</div>
<script>
var oBox = document.getElementById('box');
var oPs = document.getElementsByTagName('p');
// 1:创建孤儿节点
var oP = document.createElement('p');
// 设置内部文字
oP.innerText = '我是新段落';
// 2:挂载,只能挂载一次
// 追加到最后
oBox.appendChild(oP);
// 插入到最前
// oBox.insertBefore(oP, oPs[0]);
// 插入到第2个p之前
// oBox.insertBefore(oP, oPs[1]);
</script>
移动节点
两种方法:
新父节点.appendChild(已经有父亲的节点);
新父节点.insertBefore(已经有父亲的节点,标杆子节点);
意味着节点只能挂载一次
<div id="box1">
<p id="para">
我是box1的段落
</p>
</div>
<div id="box2">
<p>我是box2的原段落1</p>
<p>我是box2的原段落2</p>
</div>
<script>
var box1 = document.getElementById('box1');
var box2 = document.getElementById('box2');
var para = document.getElementById('para');
// 获取元素范围是box2
var ps_inbox2 = box2.getElementsByTagName('p');
// box2.appendChild(para);
box2.insertBefore(para, ps_inbox2[0]);
</script>
删除节点
父节点.removeChild(要删除子节点);
要由父节点删除它
<div id="box">
<p>我是段落1</p>
<p>我是段落2</p>
<p>我是段落3</p>
</div>
<script>
var box = document.getElementById('box');
// 删除段落1
var the_first_p = box.getElementsByTagName('p')[0];
box.removeChild(the_first_p);
</script>
克隆节点
cloneNode()
语法:var 孤儿节点=老节点.cloneNode(true);其中参数为true采用深度克隆;为false,则只克隆该节点本身
得到的节点依然是“孤儿节点"
<div id="box1">
<ul>
<li>牛奶</li>
<li>咖啡</li>
<li>酒</li>
</ul>
</div>
<div id="box2"></div>
<script>
var box1 = document.getElementById('box1');
var box2 = document.getElementById('box2');
// 注意[0]很有必要
var theul = box1.getElementsByTagName('ul')[0];
// 克隆节点- 浅克隆
var new_ul = theul.cloneNode();
// 克隆节点-深克隆
// var new_ul = theul.cloneNode(true);
box2.appendChild(new_ul);
</script>
案例1-创建新节点&改变CSS样式
<body>
<button id="btn">按我添加新的li列表项</button>
<ul id="list">
<li>默认项</li>
<li>默认项</li>
<li>默认项</li>
</ul>
<script>
var oBtn = document.getElementById("btn");
var oList = document.getElementById("list");
oBtn.onclick = function () {
// 创建一个新的li
var oLi = document.createElement("li");
oLi.innerHTML = "我是列表项";
oList.appendChild(oLi);
oLi.onclick = function () {
// 改变CSS样式
this.style.color = "red";
};
};
</script>
</body>
案例2-动态创建20行12列的表格
<style>
td {
width: 20px;
height: 20px;
border: 1px solid black;
}
</style>
<body>
<table id="mytable"></table>
<script>
var oMytable = document.getElementById("mytable");
for (var i = 0; i < 20; i++) {
var tr = document.createElement("tr");
for (var j = 0; j < 12; j++) {
var td = document.createElement("td");
tr.appendChild(td);
}
oMytable.appendChild(tr);
}
</script>
</body>
案例3-动态创建乘法表
<style>
td {
width: 20px;
height: 20px;
border: 1px solid black;
}
</style>
<body>
<table id="mytable"></table>
<script>
var oMytable = document.getElementById("mytable");
for (var i = 1; i <= 9; i++) {
var tr = document.createElement("tr");
for (var j = 1; j <= i; j++) {
var td = document.createElement("td");
// 设置td内部的文字
td.innerText = i + "*" + j + "=" + i * j;
tr.appendChild(td);
}
oMytable.appendChild(tr);
}
</script>
</body>
指用户与网页的交互动作
例如:
·当用户点击元素时
·当鼠标移动到元素上时
·当文本框的内容被改变时
·当键盘在文本框中被按下时
·当网页已加载完毕时
……