第十八节:DOM 对象(重点)
浏览器加载整个HTML文档形成Document 对象,Document 对象可以访问和操作HTML文档中的所有元素。
Document Object Model, 文档对象模型, 也叫DOM树
简单理解: 把HTML页面加载到内存后形成的DOM树状结构, 也叫DOM树
在DOM树中, 标签, 属性, 文本都是节点(对象), 我们可以通过操作节点来实现修改HTML页面的
树状结构特点:
- 有且只有一个根节点
- 每个节点都有一个父节点及任意个子节点(根节点)
- 没有子节点的节点叫做: 叶子节点
在DOM树中:
-
元素用:Element 表示
-
属性用:Attribute 表示
-
文本用:Text 表示
元素、属性、文本统称为:节点(Node)
DOM中,文档(document)表示 HTML 文件,文档中的标签称为元素(element),文档中所有的内容称为节点(node)
- 节点可以分为:标签节点(元素节点)、文本节点、属性节点,注释单独称为 注释节点
document 和 Element 对象的不同
<div id="test"> </div>
<script>
let test = document.getElementById('test');
console.log(test.nodeName); // 通过节点方式获取节点名:DIV
console.log(test.tagName); // 通过元素方式获取节点名 DIV
console.log(document.nodeName); // document 属性节点 #document
console.log(document.tagName); // document 不属于元素 undefined
</script>
nodeName 是 Node 对象的共有属性,tagName 是 Element 对象的共有属性
- Element 对象 继承了 Node 对象,也拥有 nodeName 属性
- document 对象 没有继承 Element 对象,没有 tagName 属性
3.6.1 document 文档对象
属性 | 说明 |
---|---|
document.body | 返回文档的 body 元素 |
document.documentElement | 返回文档的 html 元素 |
document.forms | 返回对文档中所有的 Form 对象引用 |
document.images | 返回对文档中所有 image 对象引用 |
let body = document.getElementsByTagName('body');
let html = document.getElementByTagName('html');
// 两个写法都可以
document.body === body;
document.dicumentElement === html
获取元素的方法:
-
querySelector(“选择器”);
选择器:id、类、标签、*、后代选择器 ···
-
根据选择器查找第一次出现的元素
只能匹配第一个元素
返回值是元素对象,找不到元素,返回值为 null
语法格式: document.querySelector("选择器"); / 选择器可以使用 id class 标签名 document.querySelector(".list"); document.querySelector("#list"); document.querySelector("div");
-
根据选择器获取全部符合的元素集合
返回值 是以伪数组的形式存放,找不到元素,返回值为空的伪数组
语法格式: document.querySelectorAll("选择器");
-
-
获取元素的 id 属性
document.getElement("元素的id属性"); // 根据 id 获取对应的元素(标签),获取一个
当变量名为 id 时,可以直接访问
<div id="time"> 时间 </div> <script> console.log(time); // 时间 </script>
-
获取元素的 class 名
document.getElementsByClassName("元素的class属性"); // 根据元素的 class 属性,获取元素(标签),获取一堆
-
获取元素的 标签名
参数: 标签名不区分大小写,推荐小写
返回值:元素对象集合,以伪数组的形式保存,根据标签选择器查不到时,返回值是空的伪数组
document.getElementsByTagName("元素的标签名"); // 根据元素的 标签名,获取元素(标签),获取一堆
-
获取元素的 name 属性
document.getElementsByName("元素的name属性"); // 根据元素的 name 属性值,获取元素(标签)获取一堆
-
HTML Collection 对象
通过 document 对象或 Element 对象调用 getElementsByClassName()方法、getElementsByTagName()方法、children 属性 等返回的对象集合,实际上是一个 HTMLCollection 对象;
HTMLCollection 与 NodeList 的区别:
- HTMLCollection 用于元素操作
- NodeList 用于节点操作
操作元素内容
分类 | 名称 | 说明 |
---|---|---|
属性 | innerHTML | 设置或返回元素开始和结束标签之间的 HTML |
innerText | 设置或返回元素中去除所有标签的内容 | |
textContent | 设置或返回指定节点的文本内容 | |
方法 | document.write() | 向文档写入指定的内容 |
document.writeln() | 向文档写入指定的内容后并换行 |
标签体的获取与设置(修改):innerHTML innerText textContent
作用:获取 DOM 节点内容,或者修改 DOM 节点内容
区别:
- innerHTML 会保留空格和换行,能识别 html 标签
- innerText 不会保留空格和换行,不能识别 html 标签
- textContent 会保留空格和换行,不能识别 html 标签
**获取标签体:**对象名.innerHTML 对象名.innerText
<script>
var odiv = document.querySelector('.box');
console.log(odiv.innerHTML);
console.log(odiv.innerText);
console.log(odiv.textContent);
</script>
<div class="box"> 获取当 前文本 </div>
**设置(修改)标签体:**对象名.innerHTML = 标签体;
<div class="box"> 修改前的文本 </div>
<script>
var odiv = document.querySelector('.box');
odiv.innerHTML = '修改后的文本';
console.log(odiv);
odiv.innerText = '修改后的文本';
console.log(odiv);
odiv.textContent = '修改后的文本';
console.log(odiv);
</script>
操作属性的方法:
-
获取属性值
<input type="text" id="userName" name="userName" placeholder="用户名" > <script> var oinput = document.querySelector('#userName'); // 获取表单类型 console.log(oinput.type); // 获取输入框的值 console.log(oinput.value); </script>
获取自定义属性
getAtrribute(name);
<input type="text" id="userName" name="userName" data-index="1" placeholder="用户名" > <script> let oinput = document.querySelector('input'); oinput.getAtrribute('data-index'); </script>
-
设置属性的值
setAtrribute(name, value);
<input type="text" id="userName" name="userName" placeholder="用户名" > <script> setAtrribute(name, value); </script>
-
删除某个属性
removAtrribute(name);
<input type="text" id="userName" name="userName" placeholder="用户名" > <script> removAtrribute(name); </script>
H5新增操作自定义属性方法
H5 新增自定义属性以 data- 开头作为属性名并赋值
- 只能获取data-开头的自定义属性
- 如果自定义属性里面有多个链接的单词,获取的时候采取 驼峰命名法
<div id="box" data-index="1" data-text="文本" > </div>
<script>
// 获取自定义属性
let odiv = document.querySelector('#box');
console.log(odiv.dataset.index);
/ dataset 获取到的是一个对象
console.log(odiv.dataset); // {index: 1, text: '文本'}
</script>
区别:
- getAttribute 可以获取所有属性的值
- 自定义属性只能通过
- 元素对象. getAttribute(‘自定义属性名’);
- 元素对象.dataset.自定义属性名
3.6.2 创建元素节点
作用:动态创建元素节点
createElement:方法通过指定名称创建一个元素
appendChild:从后添加元素
insertBefore:从前添加元素
<!-- 语法格式 -->
createElement('标签类型');
<script>
// 创建ul元素 createElement(标签类型)
let ul = document.createElement('ul');
// 2. 给ul设置内容
ul.innerHTML = `
<li>追加文本</li>
<li>追加文本</li>
<li>追加文本</li>
`;
// 给body追加ul appendChild从后添加元素
document.body.appendChild(ul);
</script>
从后添加
<script>
let odiv = document.createElement("p");
</script>
3.6.3 节点关系操作
获取子节点
children 是一个伪数组
/ 语法格式:
元素名.children;
// 获取第一个子节点
console.log(元素名.firstElementChild);
// 获取最后一个子节点
console.log(元素名.lastElementChild);
// 获取 body 所有子元素
let bodyList = document.body.children;
<div class='wrapper'>
<div class='list'>
<div class="item"> item1 </div>
<div class="brother"> brother1 </div>
</div>
<div class='list'>
<div class="item"> item1 </div>
<div class="brother"> brother1 </div>
</div>
</div>
<script>
let owrap = document.querySelector('wrapper');
// 查找所有子节点
console.log(owrap.children);
// 获取第一个子节点
console.log(owrap.firstElementChild);
// 获取最后一个子节点
console.log(owrap.lastElementChild);
// list1
let list1 = owrap.children(owrap.children[0]);
// list1 下面的item
let item1 = list1.children[0];
// list2
let list2 = owrap.children(owrap.children[1]);
// 遍历 wrapper
for (let i=0; i<owrapper.children.length; i++) {
// 访问每一个子元素
console.log(owrap.children[i]);
}
</script>
获取父亲节点
变量名.parentNode
获取兄弟节点
找不到 上/ 下 一个兄弟节点,返回 null
/ 获取下一个兄弟节点
变量名.nextElementSibling;
/ 获取上一个兄弟节点
变量名.previousElementSibling;
删除元素节点
removeChild();
没有子元素就会报错
/ 语法格式:
父元素.removeChild(第几个子元素);
<ul>
<li> day day up1 </li>
<li> day day up2 </li>
<li> day day up3 </li>
</ul>
<script>
let ul = document.querySelector('ul');
// 删除li
ul.removeChild(ul.children[0]); // 删除当前的第0项
ul.removeChild(ul.children[0]); // 再次删除当前的第0项
/* 结果:day day up3 */
let r = ul.removeChild(ul.children[1]);
console.log(r); // 返回值是删除的元素
</script>
remove();
没有子元素不会报错,避免删除元素时没有子元素
<ul>
<li> day day up1 </li>
<li> day day up2 </li>
<li> day day up3 </li>
</ul>
<script>
let ul = document.querySelector('ul');
// 删除li
ul.remove();
</script>
复制元素节点
/ 语法格式:
元素名.cloneNode(true);
<div> day day up </div>
<script>
let div = document.querySelector('div');
// 只能复制内容,事件不能复制过来
let newDiv = div.cloneNode(true);
document.body.appendChild(newDiv);
</script>
【案例】渲染效率测试
<button>点击</button>
<script>
// 准备数据源 | 实际开发中利用数据
let list = [];
for (let i=0; i<1000; i++) {
list.push(i);
}
// 获取按钮
let btn = document.querySelector('button');
// 点击事件
btn.onclick = function () {
// 创建开始时间
let start = +new Date();
// map 遍历数据源
document.body.innerHTML += list.map(function (item) {
return `<div>${item}</div>`;
}).join('');
// 创建结束时间
let end = +new Date();
// 打印耗时
console.log(`耗时:${end - start}`);
}
</script>
3.6.4 添加类名
classList.add()
/ 语法格式:
节点.classList.add("类名");
3.6.5 删除类名
/ 语法格式:
节点.classList.remove("类名");
3.6.6 window 对象
浏览器顶级对象 window
window 全局可以省略,直接写下面的事件方法
窗口(页面)加载事件
窗口(页面)加载事件:当页面中的内容完全加载完毕后才会执行
需要等待 dom、图片、css、flash 加载完毕之后才会执行 load的事件处理程序
window.onload
<!-- 场景:script 写在HTML上面,会报错 -->
<script>
// 使用 onload,当页面加载完后再加载 js
window.addEventListener('load', function () {
let div = document.querySelector('div');
div.onclick = function () {
alert(123);
}
});
</script>
<div></div>
window.DOMContentLoaded (开发常用)
DOMContentLoaded 事件触发时,仅当DOM加载完成,不包括样式表,图片、flash 等等
IE9 以上才支持!
<!-- 场景:图片、flash 等元素很多 -->
<script>
// 使用 DOMContentLoaded,dom 加载完毕,立刻执行
window.addEventListener('DOMContentLoaded', function () {
let div = document.querySelector('div');
console.log('div');
});
</script>
<div></div>
窗口大小:window.onresize
onresize 事件会在窗口或框架被调整大小时发生
参数:
- innerWidth:当前宽度
<!-- 场景:当页面宽度小于 800,隐藏div -->
<div>123</div>
<script>
// 1. 获取div元素
let div = document.querySelector('div');
// 方法一:简单写法:添加 resize 事件
window.addEventListener('resize', function () {
// 页面宽度小于 800,隐藏div
window.innerWidth < 800 && box.style.display = 'none';
window.innerWidth >= 800 && box.style.display = 'block';
});
// 方法二:复杂写法 添加 resize 事件
window.onresize = function () {
// 页面宽度小于 800,隐藏div
if (window.innerWidth < 800) {
box.style.display = 'none';
} else {
box.style.display = 'block';
}
}
</script>
3.6.7 定时器
setInterval 会不停调用函数,setTimeout 可以设置重复执行次数
setInterval
setInterval() 方法可按照指定的周期(以毫秒计)来调用函数或计算表达式
大白话解释:方法会不停地调用函数,直到 clearInterval 被调用或窗口被关闭
/ 语法格式:
setInterval(fn, 毫秒);
清除定时器 clearInterval
window.clearInterval
/ 语法格式:
window.clearInterval(要结束的定时器名字);
/ 实例
// 为了方便清除定时器,定义一个变量接收
let timeId = setInterval(function () {
console.log(1);
}, 1000);
// 清除定时器
clearinterval(timeId);
setTimeout
setTimeout() 方法用于在指定的毫秒数后调用函数或计算表达式
大白话解释: 如果你只想执行一次可以使用 setTimeout 方法
/ 语法格式:
setTimeout(fn, 毫秒);
清除定时器 clearTimeout
window.clearTimeout 只会执行一次,一般不需要清除
/ 语法格式:
window.clearInterval(要结束的定时器名字);
<!-- 实例 -->
<button>开启定时器</button>
<script>
let btn = document.querySelector('button');
// 开启定时器
btn.onclick = setTimeout(function () {
console.log(1);
}, 1000);
// 清除定时器
clearTimeout(timeId);
</script>