12day-DOM
认识 DOM
-
全称:Document Object model 文档对象模型
- 私人:一整套操作文档流的属性和方法
- 其实就是在操作页面的元素
-
DOM 以树状结构出现
- 顶层是 document
- 最大的标签是 html
- 下面分成 head 和 body
- body 里面对应就是元素标签
-
操作 DOM 就是对这个树上的某个树杈进行修剪或修饰
-
操作 DOM 过程:
- 找到你要操作的“树杈”:获取元素
- 对这个树杈进行各种操作:操作 api
获取元素
- 用一个变量来表示页面中的某个标签
- 当我们用这个变量来操作的时候,实际上就是在操作这个标签
- id 直接使用
- 给元素一个 id
- id 名在 js 内可以直接当作一个变量来使用
- 这个变量表示的就是这个标签
- 强烈不推荐使用
缺点:
- 兼容性较差,在一些低版本浏览器中不可用
- 起名问题,因为 id 在我们的页面中只能有一个,起名困难是一点,如果大范围使用 id 获取元素,到后期获取也不太友好。
- 有自己的获取元素的方式
- 获取非常规标签(html. body、head)
- 获取常规标签(所有标签)
获取非常规标签
- html
document.documentElement
- body
document.body
- head
document.head
- console.log(document.documentElement);
- console.log(document.body);
- console.log(document.head);
获取常规标签(重要)
<div class="box" id="box">我是div标签</div>
<p class="box">我是p标签</p>
<input type="text" name="phone" />
<input type="text" name="username" />
<div name="phone" id="box">我是第二个div标签</div>
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
<li>6</li>
<li>7</li>
<li>8</li>
<li>9</li>
<li>10</li>
</ul>
1. 根据 id 获取元素
- 语法:document.getElementById(“id 名”)
- 返回值:
- 如果页面中有,就是这个元素
- 如果没有,那就会得到一个 null
// 根据 id 获取元素
let ele = document.getElementById("box");
console.log(ele);
// 当页面出现有多个相同的id元素,则只会获取到第一个id对应的元素。
2. 根据类名获取元素
- 语法:document.getElementByClassName(“类名”)
- 返回值:一定是一个伪数组
- 如果页面上有 类名 对应的元素,有多少返回多少,放在伪数组里面返回,如果没有一个空的伪数组
- 注意:你拿到的不是这个元素,而是一个集合,集合内的[n]才是元素
let ele2 = document.getElementsByClassName("box");
console.log(ele2);
for (let i = 0; i < ele2.length; i++) {
console.log(ele2[i]);
}
3. 根据 标签名 获取元素
- 语法:document.getElementByTagName(“标签名”)
- 返回值:同上
// 3. 根据 标签名 获取元素
let ele = document.getElementsByTagName("li");
console.log(ele);
4. 根据 name 属性来获取元素
- 语法:document.getElementByName(“name 属性”);
- 返回值:同上
// 4. 根据 name 属性来获取元素
let ele2 = document.getElementsByName("phone");
console.log(ele2);
5. 根据 选择器 获取元素
- 语法:document.querySelector(“选择器语法”)
- 返回值:
- 如果有,那就是满足条件的第一个
- 如果没有,那就是 null
// 根据 选择器 获取元素
let ele = document.querySelector("#box");
console.log(ele);
let ele2 = document.querySelector("ul>li:nth-child(3)");
console.log(ele2);
6. 根据 选择器 获取一组元素
- 语法:document.querySelectorAll(“选择器语法”);
- 返回值:一个伪数组
因为是 NodeList,所以可以用 forEach
// 获取所有li
let ele3 = document.querySelectorAll("li");
console.log(ele3);
// 获取页面所有元素
let ele4 = document.querySelectorAll("*");
console.log(ele4);
操作元素内容
1. innerText
- 是一个读写的属性
- 读:
- 得到:该元素内的所有文本内容
- 语法:ele.innerText
- 注意:不会解析标签
- 写:
- 语法:ele.innerText = “值”
- 作用:完全覆盖的书写该 ele 内的文本
- 注意:如果写入 HTML 字符串,不会被解析成标签
<div>
hello
<p>你好世界</p>
world
</div>
<input type="text" value="中午吃啥" name="" id="" />
<script>
let ele = document.querySelector("div");
//读
console.log(ele.innerText);
//能够拿到元素内部包括子元素的所有文本内容
//注意:不会解析标签
ele.innerText = "<h1> 这是我写入的内容</h1>";
//会将元素原本内容覆盖掉,包括里面的子元素
</script>
let ele = document.getElementsByClassName("box");
// 读:
console.log(ele);
console.log(ele[0].innerText);
// 能够拿到元素内部包括子元素的所有文本内容
// 注意:不会解析标签
ele[0].innerText = "<h1>这是我写入的内容</h1>";
// 会将元素原本内容覆盖掉,包括里面的子元素
2. innerHTML
- 是一个读写属性
- 读:
- 语法:ele.innerHTML
- 得到:该元素下的所有内容
- 注意:会把元素内的标签当作字符串给你
- 写:
- 语法:ele.innerHTML = “值”
- 作用:完全覆盖掉 ele 内的所有内容
- 注意:能够解析 HTML 字符串
let ele = document.querySelector("div");
console.log(ele.innerHTML);
console.log(ele.innerText);
ele.innerHTML = "<h1>这是我写入的内容</h1>";
3. value
- 读写属性
- 读:
- 语法:表单元素.value
- 得到:该元素的 value 值
- 写:
- 语法:表单元素.value = “值”
- 作用:覆盖掉表单元素的 value 值
- 读:
//读
let ipt = document.querySelector("input");
console.log(ipt.value);
//写
ipt.value = "今天麦当劳,明天肯德基";
console.log(ipt.value);
操作元素的属性
- 一个元素的属性由 属性名 = “属性值” 组成的
在 html 页面中, 元素的属性大致分成三类
1. 原生属性,在 html 规范内的属性
- id、class、type、src…
- 特点:对于标签有着特殊的意义
2. 自定义属性,在 html 规范内 没有的属性
- 只是为了标注一些内容在标签上
3. H5 自定义属性 data-
- 书写规则是 data-xxx 开头
- 例如:
data-yh = "100"
- 属性名:yh
- 属性值:100
<div class="a b" id="box" style="color:red;" haha="789" data-yh="100">
你好世界
</div>
<input type="text" value="123" />
操作原生属性
直接使用 ele.属性名的形式进行操作即可。
- 读:
ele.属性名
- 写:
ele.属性名=属性值
let box = document.querySelector("div");
let ipt = document.querySelector("input");
// 读:
console.log(box.id);
console.log(ipt.type);
console.log(ipt.value);
// 写:
box.id = "container";
ipt.type = "radio";
box.style = "font-size:30px;"; // 一般也不这么做来改变样式
box.class = "yh"; // 修改不了
操作自定义属性
-
获取自定义属性的值
-
语法:ele.getAttribute(“属性名”);
-
设置自定义属性
-
语法:ele.setAttribute(“属性名”,“属性值”)
-
修改与新增语法一样
-
删除自定义属性
-
语法:ele.removeAttribute(“属性名”);
// 获取自定义属性
// 语法:ele.getAttribute("属性名");
console.log(box.getAttribute("haha"));
// 设置自定义属性
// 语法:ele.setAttribute("属性名","属性值")
box.setAttribute("qx", "200");
// 删除自定义属性
// 语法:ele.removeAttribute("属性名");
box.removeAttribute("haha");
// 修改自定义属性
box.setAttribute("qx", "1000");
操作 H5 的自定义属性
- 在元素身上有一个叫做 dataset 的成员
- 是一个类似对象的数据类型
- 里面存储着所有的 data-开头的自定义属性
- 我们操作 H5 自定义属性,就是操作 dataset
// 看一下dataset
console.log(box.dataset);
// 获取属性值
console.log(box.dataset.yh);
// 修改
box.dataset.yh = 200;
console.log(box.dataset);
// 增加
box.dataset.yh2 = 300;
console.log(box.dataset);
// 删除
delete box.dataset.yh;
console.log(box.dataset);
**注意:**以上所有操作元素属性的方法,一般不用于操作元素的 类名 和 样式
DOM,02
操作元素的样式
在 js 中操作元素样式分为 3 种
- 设置元素的行内样式
- 获取元素的行内样式
- 获取元素的 非行内样式,不是只能获取非行内,而是所有的样式都能拿到
设置元素的行内样式
- 语法:ele.style.样式名 = 样式值
- 作用:给元素设置行内样式
- 注意:在 css 中以 - 连接的多个单词样式,需写成驼峰语法,或者数组关联语法
<div class="box">132</div>
<script>
let box = document.querySelector(".box");
// 设置行内样式
box.style.color = "red";
box.style.backgroundColor = "skyblue";
box.style["background-color"] = "green";
box.style.fontSize = "50px";
</script>
获取元素的行内样式
- 语法:ele.style.样式名
- 得到:该元素指定样式对应的值
- 注意:只能拿到行内样式的值,非行内拿不到
- 在 css 中以 - 连接的多个单词样式,需写成驼峰语法,或者数组关联语法
<div class="box">132</div>
<script>
let box = document.querySelector(".box");
// 设置行内样式
box.style.color = "red";
box.style.backgroundColor = "skyblue";
box.style["background-color"] = "green";
//点语法--括号语法
box.style.fontSize = "50px";
console.log(box.style["font-size"]); // 50px
console.log(box.style.border); // ""
console.log(box.style);
</script>
获取元素的非行内样式
-
标准浏览器
- 语法:window.getComputedStyle(需要获取样式的元素).样式名
- 返回值:该元素中指定样式对应的值
- 注意:在 css 中以 - 连接的多个单词样式,需写成驼峰语法,或者数组关联语法
- 注意:行内和非行内都会拿到
-
IE 低版本
- 语法:ele.currentStyle.样式名
- 得到:该元素指定样式对应的值
- 注意:行内和非行内都能拿到,需要写成驼峰/数组关联语法
- 注意:只能在 IE 低版本浏览器下使用
let res = window.getComputedStyle(box);
console.log(res.border);
console.log(res.color);
console.log(res);
res.color = "pink";
操作元素的类名
- className
- 读:ele.className
- 写:ele.className = 值
- 追加:ele.className += 值
- 注意:值的位置要书写一个空格
let res = box.className;
// 返回是一个字符串类型
console.log(res);
// 修改类名
box.className = "BOX";
// 做追加类名时 className需要在被添加的类名前 加多一个空格
box.className += " box";
- classList
每个元素都有一个属性叫做 classList
是一个类数组集合,里面记录着元素的所有类名
- 添加
- 语法:ele.classList.add(“要添加的类名”)
- 删除
- 语法:ele.classList.remove(“要删除的类名”)
- 切换
- 语法:ele.classList.toggle(“要切换的类名”)
- 作用:有就删除,没有就是添加
// 添加
// box.classList[2] = "a";
// console.log(box.classList);
// 通过add方法添加类名
box.classList.add("a");
box.classList.add("zd");
// 删除
// let arr = [1,2,3,4,5];
// delete arr[0];
// console.log(arr);
// delete box.classList[0]
// 通过 remove 方法删除类名
box.classList.remove("a");
// 切换
// 作用:有就删除,没有就添加
// 通过 toggle 方法进行类名切换
box.classList.toggle("zd");
box.classList.toggle("zd");
获取元素的尺寸
一个元素在页面中占多少位置
占地面积
- offsetWidth 和 offsetHeight
语法:ele.offsetWidth/ele.offsetHeight
- 得到:该元素的内容 + padding + border 的尺寸
注意:display:none 时拿不到
- clientWidth 和 clientHeight
语法:box.clientWidth/box.clientHeight
- 得到的是该元素内容 + padding 的尺寸
注意:display:none 时拿不到
获取元素的偏移量
偏移量:相对参考元素的 左边和上边的距离,这个距离我们就叫他偏移量。
一个元素结构有两个父级
- 结构父级:书写在这个标签外边面的标签
- 定位父级:当你给 p 设置绝对定位,根据谁来定位,谁就是他的定位父级;如果到了窗口以后,那定位父级就是 body
- 元素偏移量的参考元素是谁?
-
就是这个元素的 定位父级
-
就是假设需要给这个元素设置绝对定位的时候,根据谁来定位
-
获取到的偏移量,就是参考谁的
-
获取元素的偏移量
- offsetLeft/offsetTop
- 相对于参考元素的左边和上边的距离
<style>
* {
margin: 0;
padding: 0;
}
div {
width: 500px;
height: 500px;
overflow: hidden;
margin: 50px;
background-color: pink;
position: relative;
}
p {
margin-left: 60px;
width: 300px;
height: 300px;
background-color: skyblue;
}
</style>
<div>
<p></p>
</div>
<script>
let p = document.querySelector("p");
// div设置position: relative;时
console.log(p.offsetLeft); // 50
// div没有设置position: relative;时
console.log(p.offsetLeft); // 100
</script>
获取窗口尺寸
-
BOM 级别的获取
- window.innerWidth/innerHeight
- 得到的是窗口的宽度和高度
- 是包含了视口宽高和滚动条的尺寸
-
DOM 级别获取
- document.documentElement.clientWidth
- document.documentElement.clientHeight
- 得到的是视口的宽高,不包含滚动条
DOM 节点
dom 节点操作
-
什么是节点?
页面组成的最小单元 -
注意:
- 标签是一个节点
- 但节点不一定是标签
-
在页面中
- 所有的内容都是一个个的节点
- document
- 元素节点(标签)
- 文本节点(文本内容)
- 注释节点(注释内容)
- 属性节点:一个标签身上书写的属性(包含自定义属性和原生属性),不会作为独立节点出现
。。。
- 节点的操作:对节点的增删改查
- 获取节点
- 创建节点
- 插入节点
- 删除节点
- 替换节点
- 克隆节点
- 所有的内容都是一个个的节点
<div id="numNode">
hello
<span>你好</span>
<!-- 我是一段注释 -->
<span>世界</span>
world
</div>
<!--
1. 文本节点:一个换行 + 四个空格 + hello + 换行 + 四个空格
2. 元素节点:span标签
3. 一个换行 + 四个空格
4. 注释节点:注释内容
5. 文本节点:一个换行 + 四个空格
6. 元素节点:span标签
7. 文本节点:一个换行 + 四个空格 + world + 一个换行 + 两个个空格
-->
<script>
let numNodes = document.querySelector("#numNode");
console.log(numNodes.childNodes); // NodeList(7) [text, span, text, comment, text, span, text]
</script>
获取节点
- 元素节点
- 笔记有
- 包含但不限于元素节点
-
childNodes
-
语法:父节点.childNodes
-
得到:是一个类数组集合,包含该父节点下所有的一级子节点
-
children
-
语法:父节点.children
-
得到:是一个类数组集合,包含了该父节点下所有的一级子元素节点
-
firstChild
-
语法:父节点.firstChild
-
得到:该父节点下第一个字节点。
-
firstElementChild
-
语法:父节点.firstElementChild
-
得到:该父节点下第一个子元素节点
-
lastChild
-
语法:父节点.lastChild
-
得到:该父节点下最后一个字节点
-
lastElementChild
-
语法:父节点.lastElementChild
-
得到:该父节点下最后一个子元素节点
-
previousSibling
-
语法:节点.previousSibling
-
得到:该节点的上一个兄弟节点
-
previousElementSibling
-
语法:语法:节点.previousElementSibling
-
得到:该节点的上一个兄弟元素节点
-
如果没有返回 null
-
nextSibling
-
得到:下一个兄弟节点
-
nextElementSibling
-
得到:下一个兄弟元素节点
-
parentNode
-
得到:父节点
-
parentElement
-
得到:父元素
-
attributes
-
所有属性节点
1 childNodes 所有子节点
3 firstChild 第一个子节点
5 lastChild 最后一个子节点
7 previousSibling 上一个兄弟节点
9 nextSibling 下一个兄弟节点
11 parentNode 父节点
13 attributes 所有属性节点
主要要记的
2 children 所有的子元素
4 firstElmentChild 第一个子元素
6 lastElementChild 最后一个子元素
8 previousElementSibling 上一个兄弟元素节点
10 nextElementSibling 下一个兄弟元素
12 parentElement 父元素
创建节点
- 创建元素节点
语法:document.createElement(“你要创建的元素名称”); - 创建文本节点
语法:document.createTextNode(“文本内容”);
let div = document.createElement("div");
// 现在这个div是一个孤儿节点
console.log(div);
let text = document.createTextNode("我是一个文本节点");
console.log(text);
插入节点
- appendChild
- 语法:父节点.appendChild(“子节点”)
- 语法:被插入的节点.appendChild(“你要插入的节点”)
- 作用:把字节点插入到父节点内部,并且排列在最后面
- inserBefore
- 语法:父节点.inserBefore(字节点,谁的前面)
- 作用:把该字节点插入到父节点的内部,可以选择具体位置
let div = document.createElement("div");
// 现在这个div是一个孤儿节点
console.log(div);
let text = document.createTextNode("我是一个文本节点");
console.log(text);
let box = document.querySelector(".box");
// 开始插入
box.appendChild(div);
box.appendChild(text);
div.appendChild(text);
let div2 = document.createElement("div");
div2.innerText = "我是插入者";
// 插入到3的前面2的后面
box.insertBefore(div2, box.children[3]);
删除节点
- removeChild
- 语法:父节点.removeChild(“子节点”)
- 作用:把该子节点从父节点中删除
- remove
- 语法:节点.remove()
- 作用:自杀,直接把自己删除
box.removeChild(box.children[0]);
box.children[2].remove();
let p = document.querySelector("p");
// 自杀
// p.remove()
// 谋杀
box.removeChild(p);
替换节点
- replaceChild
- 语法:父节点.replaceChild(换上节点,换下节点)
// 获取要被替换的元素
let boxdiv = document.querySelector(".box div");
// 创建一个代替的元素
let div3 = document.createElement("div");
div3.innerText = "我是代替他的人";
// 进行替换
box.replaceChild(div3, boxdiv);
克隆节点
cloneNode
- 语法:被克隆的元素.cloneNode(参数)
- 参数:选填
- 默认为 false,表示不克隆后代节点
- 选填为 true,表示克隆后代节点
- 返回值:该节点复制一摸一样的节点
- 参数:选填
// 克隆box 什么都不填
let res = box.cloneNode();
console.log(res); // 只复制了box本身
console.log(box);
// true
let res2 = box.cloneNode(true);
console.log(res2); // 复制了box包括其所有子代节点
// 完全克隆
console.log(res2.childNodes);
console.log(box.childNodes);
// 深克隆
console.log(res2 == box); // false
document.body.appendChild(res2);
let res3 = box;
console.log(res3 === box);
// 无事发生
document.body.appendChild(res3);
document.body.appendChild(res2);