51工具盒子

依楼听风雨
笑看云卷云舒,淡观潮起潮落

JavaScript - DOM

DOM,全称Document Object Model,中文翻译为文档对象模型。DOM属于Web API的一部分。Web API中定义了非常多的对象,通过这些对象可以完成对网页的各种操作(添加删除元素、发送请求、操作浏览器等)。


什么是DOM {#%E4%BB%80%E4%B9%88%E6%98%AFdom}

DOM中的D意为Document,即文档。所谓文档就是指整个网页,换言之,DOM是用来操作网页的。O意为Object,即对象。DOM将网页中的每一部分内容都转换为了对象,div有div的对象,input有input的对象,甚至一段文本,一段注释也有其所对应的对象。转换为对象干什么?还记得面向对象吗?转换对象以后,我们就可以以面向对象的方式去操作网页,想要操作哪个元素就获取哪个元素的对象,然后通过调用其方法或属性完成各种操作。M意为Model,即模型。模型用来表示对象之间的关系,也就是父子元素、祖先后代、兄弟元素等,明确关系后我们便可以通过任意一个对象去获取其他的对象。

<!DOCTYPE html>
<html lang="zh">
<head>
    <title>My Title</title>
</head>
<body>
    <h1>A Heading</h1>
    <a href="#">Link Text</a>
</body>
</html>

dom-items.webp

>概念 {#%3E%E6%A6%82%E5%BF%B5}

节点(Node) {#%E8%8A%82%E7%82%B9%EF%BC%88node%EF%BC%89}

在DOM标准下,网页中的每一个部分都会转换为对象。这些对象有一个共同的称呼------节点(Node)。一个页面将会由多个节点构成,虽然都称为节点,但是它们却有着不同的类型:

  1. 文档节点

  2. 元素节点

  3. 文本节点

  4. 属性节点

  5. ...

每一个节点都有其不同的作用,文档节点表示整个网页,元素节点表示某个标签,文本节点表示网页中的文本内容,属性节点表示标签中的各种属性。如果从对象的结构上来讲,这些对象都有一个共同的父类Node。总的来说,都是属于节点,但是具体类型不同。

关系 {#%E5%85%B3%E7%B3%BB}

  • 祖先 ------ 包含后代元素的元素是祖先元素

  • 后代 ------ 被祖先元素包含的元素是后代元素

  • 父 ------ 直接包含子元素的元素是父元素

  • 子 ------ 直接被父元素包含的元素是子元素

  • 兄弟 ------ 拥有相同父元素的元素是兄弟元素

小试牛刀 {#%E5%B0%8F%E8%AF%95%E7%89%9B%E5%88%80}

要使用DOM来操作网页,我们需要浏览器至少得先给我一个对象,才能去完成各种操作。所以浏览器已经为我们提供了一个document对象,它是一个全局变量可以直接使用,document代表的是整个的网页。

<button id="btn">点我一下</button>

\<script\>
// 获取btn对象
const btn = document.getElementById("btn")

`// 修改btn中的文字
btn.innerText = "Click ME"
</script>`


>文档节点(document) {#%3E%E6%96%87%E6%A1%A3%E8%8A%82%E7%82%B9%EF%BC%88document%EF%BC%89}

  • document对象表示的是整个网页

  • document对象的原型链

HTMLDocument -> Document -> Node -> EventTarget -> Object.prototype -> null
  • 凡是在原型链上存在的对象的属性和方法都可以通过Document去调用

  • 部分属性:

document.documentElement --> html根元素
document.head --> head元素
document.title --> title元素
document.body --> body元素
document.links --> 获取页面中所有的超链接
...

>元素节点(element) {#%3E%E5%85%83%E7%B4%A0%E8%8A%82%E7%82%B9%EF%BC%88element%EF%BC%89}

  • 在网页中,每一个标签都是一个元素节点

如何获取元素节点对象?

  1. 通过document对象来获取元素节点

  2. 通过document对象来创建元素节点

通过document来获取已有的元素节点:

document.getElementById() {#document.getelementbyid()}

  • 根据id获取一个元素节点对象
<button id="btn">点我一下</button>
<script>
const btn = document.getElementById("btn")
console.log(btn)
</script>

document.getElementsByClassName() {#document.getelementsbyclassname()}

  • 根据元素的class属性值获取一组元素节点对象
<span class="s1">我是span</span>
<span class="s1">我是span</span>
<span class="s1">我是span</span>
<span class="s1">我是span</span>
<span class="s1">我是span</span>

\<script\>


// 返回的是一个类数组对象,该方法返回的结果是一个实时更新的集合
// 当网页中新添加元素时,集合也会实时的刷新。


const spans = document.getElementsByClassName("s1")


console.log(spans) // HTMLCollection(5) \[span.s1, span.s1, span.s1, span.s1, span.s1\]


for (let i = 0; i \< spans.length; i++) {
spans\[i\].innerText = "我是span"+i
}

`</script>`

document.getElementsByTagName() {#document.getelementsbytagname()}

  • 根据标签名获取一组元素节点对象
<div>我是div</div>
<div>我是div</div>
<div>我是div</div>
<div>我是div</div>
<div>我是div</div>

\<script\>


// 返回的结果是可以实时更新的集合
const divs = document.getElementsByTagName("div")


// document.getElementsByTagName("") 获取页面中所有的元素
const divs = document.getElementsByTagName("")

`console.log(divs) // HTMLCollection(5) [div, div, div, div, div]
</script>`

document.getElementsByName() {#document.getelementsbyname()}

  • 根据name属性获取一组元素节点对象
<form>
    <input type="text" name="username">
    <input type="radio" name="gender" value="male"> 男
    <input type="radio" name="gender" value="female"> 女
</form>

\<script\>


// 返回一个实时更新的集合,主要用于表单项。
const genderInput = document.getElementsByName("gender")

`console.log(genderInput) // NodeList(2) [input, input]
</script>`

document.querySelectorAll() {#document.queryselectorall()}

  • 根据选择器去页面中查询元素
<div>我是div</div>
<div>我是div</div>
<div>我是div</div>

\<script\>


// 会返回一个类数组(不会实时更新)
const divs2 = document.querySelectorAll("div")

`console.log(divs2) // NodeList(3) [input, input,input]
</script>`

document.querySelector() {#document.queryselector()}

  • 根据选择器去页面中查询第一个符合条件的元素
<div>我是div</div>
<div>我是div</div>

\<script\>


// 会返回一个类数组(不会实时更新)
const div = document.querySelector("div") // .xx \| #xx


console.log(divs2) // NodeList(2) \[input,input\]

`</script>`

创建一个元素节点

document.createElement() {#document.createelement()}

  • 根据标签名创建一个元素节点对象
const h2 = document.createElement("h2") // 创建了H2,但未添加

>元素的属性和方法 {#%3E%E5%85%83%E7%B4%A0%E7%9A%84%E5%B1%9E%E6%80%A7%E5%92%8C%E6%96%B9%E6%B3%95}

<div id="box1">我是box1 </div>

\<script\>


const box1 = document.getElementById("box1")


cosole.log(box1.proto)

`</script>`

  • div的原型链
HTMLDivElement -> HTMLElement -> Element -> Node -> ...

element.childNodes {#element.childnodes}

  • 获取当前元素的子节点(会包含空白的子节点)
<div id="box1">
    我是box1
    <span class="s1">我是s1</span>
    <span class="s1">我是s1</span>
</div>

\<script\>


const box1 = document.getElementById("box1")


const cns = box1.childNodes


console.log(children.length) // 输出:5 包含空格

`</script>`

element.children {#element.children}

  • 获取当前元素的子元素
<div id="box1">
    我是box1
    <span class="s1">我是s1</span>
    <span class="s1">我是s1</span>
</div>

\<script\>


const box1 = document.getElementById("box1")


const children = box1.children


console.log(children.length) // 输出:2(2个span)

`</script>`

element.firstElementChild {#element.firstelementchild}

  • 获取当前元素的第一个子元素
<p>Hello world! This is HTML5 Boilerplate.</p>
<div id="box1">
    我是box1
    <span class="s1">我是s1</span>
    <span class="s1">我是s1-2</span>
</div>
    <h1>hello,world</h1>

\<script\>


const box1 = document.getElementById("box1")


console.log(box1.firstElementChild) //输出: \<span class="s1"\>我是s1\</span\>

`</script>`

element.lastElementChild {#element.lastelementchild}

  • 获取当前元素的最后一个子元素
console.log(box1.lastElementChild) //输出: <span class="s1">我是s1-2</span>

element.nextElementSibling {#element.nextelementsibling}

  • 获取当前元素的下一个兄弟元素
console.log(box1.nextElementSibling) //输出: <h1>hello,world</h1>

element.previousElementSibling {#element.previouselementsibling}

  • 获取当前元素的前一个兄弟元素
console.log(box1.previousElementSibling) //输出: <p>Hello world! This is HTML5 Boilerplate.</p>

element.parentNode {#element.parentnode}

  • 获取当前元素的父节点
console.log(box1.parentNode) //输出: <body>...</body>

element.tagName {#element.tagname}

  • 获取当前元素的标签名
console.log(box1.tagName) //输出: DIV

>文本节点(Text) {#%3E%E6%96%87%E6%9C%AC%E8%8A%82%E7%82%B9%EF%BC%88text%EF%BC%89}

在DOM中,网页中所有的文本内容都是文本节点对象。

可以通过元素来获取其中的文本节点对象,但是我们通常不会这么做。

我们可以直接通过元素去修改其中的文本

修改文本的三个属性

element.textContent {#element.textcontent}

  • 获取或修改元素中的文本内容
<div id="box1">
    <span style="text-transform: uppercase;">我是box1</span>
</div>

\<script\>


// 获取的是标签中的内容,不会考虑css样式
const box1 = document.getElementById("box1")


box1.textContent = "新的内容"

`</script>`

element.innerText {#element.innertext}

  • 获取或修改元素中的文本内容
<script>

// innerText获取内容时,会考虑css样式
// 通过innerText去读取CSS样式,会触发网页的重排(计算CSS样式)
const box1 = document.getElementById("box1")


box1.innerText = "新的内容"


// 当字符串中有标签时,会自动对标签进行转义
box1.innerText = "\<li\>我是li\</\>" //  \<li\> --\> \&lt;li\&gt;

`</script>`

element.innerHTML {#element.innerhtml}

  • 获取或修改元素中的html代码
<script>

// 可以直接向元素中添加html代码
const box1 = document.getElementById("box1")


box1.innerHTML = "XXX"

`// innerHTML插入内容时,有被xss注入的风险
box1.innerHTML = "<、script src='https://sss/sss.js'></script>"
</script>`

>属性节点(Attr) {#%3E%E5%B1%9E%E6%80%A7%E8%8A%82%E7%82%B9%EF%BC%88attr%EF%BC%89}

在DOM也是一个对象,通常不需要获取对象而是直接通过元素即可完成对其的各种操作。

如何操作属性节点:

方式一 {#%E6%96%B9%E5%BC%8F%E4%B8%80}

  • 读取:元素.属性名(class属性需要使用 className 来读取)

读取一个布尔值时,会返回 true 或 false (如 disabled)

  • 修改:元素.属性名 = 属性名
 <input disabled="disabled" type="text" name="username" value="admin">

\<script\>


const input = document.getElementsByName("username")\[0\]


const input2 = document.querySelector("\[name=username\]")


console.log(input) // console.log(input.type)


input.name = "biu" // 修改:元素.属性名 = 属性名

`</script>`

方式二 {#%E6%96%B9%E5%BC%8F%E4%BA%8C}

  • 读取:元素.getAttribute(属性名)

  • 修改:元素.setAttribute(属性名, 属性值)

  • 删除:元素.removeAttribute(属性名)

 <input disabled="disabled" type="text" name="username" value="admin">

\<script\>


const input = document.getElementsByName("username")\[0\]


const input2 = document.querySelector("\[name=username\]")


input.getAttribute("name") // 读取:元素.getAttribute(属性名)


input.setAttribute("name","大王") // 修改:元素.setAttribute(属性名, 属性值)
input.setAttribute("disabled",true)


input.removeAttribute("disabled") // 删除:元素.removeAttribute(属性名)

`</script>`

>事件(Event) {#%3E%E4%BA%8B%E4%BB%B6%EF%BC%88event%EF%BC%89}

事件就是用户和页面之间发生的交互行为。例如:点击按钮、鼠标移动、双击按钮、敲击键盘、松开按键....

可以通过为时间绑定响应函数(回调函数),来完成和用户之间的交互。

绑定响应函数

直接在元素的属性中设置 {#%E7%9B%B4%E6%8E%A5%E5%9C%A8%E5%85%83%E7%B4%A0%E7%9A%84%E5%B1%9E%E6%80%A7%E4%B8%AD%E8%AE%BE%E7%BD%AE}

<button id="btn" onclick="alert('你点我干嘛~')">点我一下</button>

为元素指定属性设置(回调函数)来绑定事件 (一个事件只能绑定一个响应函数) {#%E4%B8%BA%E5%85%83%E7%B4%A0%E6%8C%87%E5%AE%9A%E5%B1%9E%E6%80%A7%E8%AE%BE%E7%BD%AE(%E5%9B%9E%E8%B0%83%E5%87%BD%E6%95%B0)%E6%9D%A5%E7%BB%91%E5%AE%9A%E4%BA%8B%E4%BB%B6-%EF%BC%88%E4%B8%80%E4%B8%AA%E4%BA%8B%E4%BB%B6%E5%8F%AA%E8%83%BD%E7%BB%91%E5%AE%9A%E4%B8%80%E4%B8%AA%E5%93%8D%E5%BA%94%E5%87%BD%E6%95%B0%EF%BC%89}

<script>
// 获取到按钮对象
const btn = document.getElementById("btn")
// 为按钮对象的事件属性设置响应函数
btn.onclick = function(){
  alert("你点我干嘛~")
}
</script>

通过元素 addEventListener( )方法来绑定事件 (可绑定多个,会依次执行) {#%E9%80%9A%E8%BF%87%E5%85%83%E7%B4%A0-addeventlistener(-)%E6%96%B9%E6%B3%95%E6%9D%A5%E7%BB%91%E5%AE%9A%E4%BA%8B%E4%BB%B6-%EF%BC%88%E5%8F%AF%E7%BB%91%E5%AE%9A%E5%A4%9A%E4%B8%AA%EF%BC%8C%E4%BC%9A%E4%BE%9D%E6%AC%A1%E6%89%A7%E8%A1%8C%EF%BC%89}

<script>
// 通过元素 addEventListener( )方法来绑定事件
btn.addEventListener("click", function(){
  alert("哈哈哈哈~")
})
</script>

>文档加载 {#%3E%E6%96%87%E6%A1%A3%E5%8A%A0%E8%BD%BD}

网页是自上向下加载的,如果将 js 的代码编写到网页的上边,在 js 代码执行时,网页还没有加载完毕,这时候会出现无法获取到 DOM 对象的情况。

如何解决这个问题?

将 script 标签编写到 body 的最后 {#%E5%B0%86-script-%E6%A0%87%E7%AD%BE%E7%BC%96%E5%86%99%E5%88%B0-body-%E7%9A%84%E6%9C%80%E5%90%8E}

<body>

\<button id="btn"\>点我一下\</button\>


\<script\>
const btn = document.getElementById("btn")
console.log(btn)
\</script\>

`</body>
`

将代码编写到 window.onload 的回调函数中 {#%E5%B0%86%E4%BB%A3%E7%A0%81%E7%BC%96%E5%86%99%E5%88%B0-window.onload-%E7%9A%84%E5%9B%9E%E8%B0%83%E5%87%BD%E6%95%B0%E4%B8%AD}

<body>

\<button id="btn"\>点我一下\</button\>


\<script\>
// window.onload 事件会在窗口中的内容加载完毕之后才触发
window.onload = function () {
const btn = document.getElementById("btn")
console.log(btn)
}


window.addEventListener("load", function () {
const btn = document.getElementById("btn")
alert(btn)
})
\</script\>

`</body>`

将代码编写到 document 对象的 DOMContentLoaded 回调函数中 {#%E5%B0%86%E4%BB%A3%E7%A0%81%E7%BC%96%E5%86%99%E5%88%B0-document-%E5%AF%B9%E8%B1%A1%E7%9A%84-domcontentloaded-%E5%9B%9E%E8%B0%83%E5%87%BD%E6%95%B0%E4%B8%AD}

<script>
// document的DOMContentLoaded事件会在当前文档加载完毕之后触发
document.addEventListener("DOMContentLoaded", function () {
    const btn = document.getElementById("btn")
    alert(btn)
})
</script>

将代码编写到外部 js 文件,以 defer 形式引入 {#%E5%B0%86%E4%BB%A3%E7%A0%81%E7%BC%96%E5%86%99%E5%88%B0%E5%A4%96%E9%83%A8-js-%E6%96%87%E4%BB%B6%EF%BC%8C%E4%BB%A5-defer-%E5%BD%A2%E5%BC%8F%E5%BC%95%E5%85%A5}

<script defer src="./script/script.js"></script>

>Dom的修改 {#%3Edom%E7%9A%84%E4%BF%AE%E6%94%B9}

element.appendChild {#element.appendchild}

  • 给一个节点添加子节点
<ul id="list">
    <li id="swk">孙悟空</li>
    <li id="zbj">猪八戒</li>
    <li id="shs">沙和尚</li>
</ul>

\<button id="btn"\>按钮\</button\>


\<script\>
const list = document.getElementById("list")


// 获取按钮
const btn01 = document.getElementById("btn01")
btn01.onclick = function () {


    const li = document.createElement("li")
    // 向li中添加文本
    li.textContent = "唐僧"
    // 给li添加id属性
    li.id = "ts"



`// 用于给一个节点添加子节点
list.appendChild(li)
</script>`

element.insertAdjacentElement(position, element) {#element.insertadjacentelement(position%2C-element)}

  • 可以向元素的任意位置添加元素

参数:

  1. beforeend 标签的最后

  2. afterbegin 标签的开始

  3. beforebegin 在元素的前边插入元素(兄弟元素)

  4. afterend 在元素的后边插入元素(兄弟元素)

<script>
list.insertAdjacentElement("afterend", li)
</script>

element.insertAdjacentHTML(position, text) {#element.insertadjacenthtml(position%2C-text)}

  • 将HTML字符串添加到任意位置

参数:

  1. beforeend 标签的最后

  2. afterbegin 标签的开始

  3. beforebegin 在元素的前边插入元素(兄弟元素)

  4. afterend 在元素的后边插入元素(兄弟元素)

<script>
list.insertAdjacentHTML("beforeend", "<li id='bgj'>白骨精</li>")
</script>

element.replaceWith {#element.replacewith}

  • 使用一个元素替换当前元素
const bt = document.getElementById("btn")
btn02.onclick = function(){

    // 创建一个蜘蛛精替换孙悟空
    const li = document.createElement("li")
    li.textContent = "蜘蛛精"
    li.id = "zzj"

    // 获取swk
    const swk = document.getElementById("swk")

    // replaceWith() 使用一个元素替换当前元素
    swk.replaceWith(li)



`}`

element.remove {#element.remove}

  • 用来删除一个元素
<script>
swk.remove()
</script>

>小练习 {#%3E%E5%B0%8F%E7%BB%83%E4%B9%A0}

>节点的复制 {#%3E%E8%8A%82%E7%82%B9%E7%9A%84%E5%A4%8D%E5%88%B6}

cloneNode() {#clonenode()}

  • 对节点的所有属性进行复制(只会复制当前节点,而不会复制节点的子节点)
<!DOCTYPE html>
<html lang="zh">
    <head>
        <meta charset="UTF-8" />
        <meta http-equiv="X-UA-Compatible" content="IE=edge" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>Document</title>
    </head>
    <body>
        <button id="btn01">点我一下</button>

        &lt;ul id="list1"&gt;
            &lt;li id="l1"&gt;孙悟空&lt;/li&gt;
            &lt;li id="l2"&gt;猪八戒&lt;/li&gt;
            &lt;li id="l3"&gt;沙和尚&lt;/li&gt;
        &lt;/ul&gt;

        &lt;ul id="list2"&gt;
            &lt;li&gt;蜘蛛精&lt;/li&gt;
        &lt;/ul&gt;

        &lt;script&gt;
            /* 点击按钮后,将id为l1的元素添加list2中 */
            const list2 = document.getElementById("list2")
            const l1 = document.getElementById("l1")
            const btn01 = document.getElementById("btn01")
            btn01.onclick = function () {
                // 用来对节点进行复制的,true作为参数,该方法将子节点一起复制
                const newL1 = l1.cloneNode(true) 
                newL1.id = "newL1"
                list2.appendChild(newL1)
            }
        &lt;/script&gt;
    &lt;/body&gt;



`</html>`

>修改CSS样式 {#%3E%E4%BF%AE%E6%94%B9css%E6%A0%B7%E5%BC%8F}

元素.style.样式名 = 样式值 {#%E5%85%83%E7%B4%A0.style.%E6%A0%B7%E5%BC%8F%E5%90%8D-%3D-%E6%A0%B7%E5%BC%8F%E5%80%BC}

如果样式里含有-,则需要将样式表修改为驼峰命名法

background-color --> backgroundColor

<button id="btn">点我一下</button>
<div class="box1"></div>
<script>

    const btn = document.getElementById("btn")
    const box1 = document.querySelector(".box1")

    btn.onclick = function () {
        // 修改box1的样式
        // 修改样式的方式:元素.style.样式名 = 样式值
        // 如果样式名中含有-,则需要将样式表修改为驼峰命名法
        // background-color --&gt; backgroundColor
        box1.style.width = "400px"
        box1.style.height = "400px"
        box1.style.backgroundColor = "yellow"
    }



`</script>`

>读取CSS样式 {#%3E%E8%AF%BB%E5%8F%96css%E6%A0%B7%E5%BC%8F}

getComputedStyle() {#getcomputedstyle()}

  • 返回一个包含当前元素所有的生效样式的对象

参数:

1.要获取样式的对象

2.要获取的伪元素

返回值:

返回的一个对象,对象中储存了当前元素的样式

<button id="btn">点我一下</button>
<div class="box1"></div>
<script>
    /* 
        点击按钮后,读取元素的css样式
    */

    const btn = document.getElementById("btn")
    const box1 = document.querySelector(".box1")

    btn.onclick = function () {

        const styleObj = getComputedStyle(box1)

        console.log(styleObj.width)
        console.log(styleObj.left)

        // console.log(parseInt(styleObj.width) + 100)
        // box1.style.width = parseInt(styleObj.width) + 100 + "px"

        // console.log(styleObj.backgroundColor)

        const beforeStyle = getComputedStyle(box1, "::before")
        // console.log(beforeStyle.color)

        console.log(box1.firstElementChild)
    }



`</script`

element.clientHeight / Width {#element.clientheight-%2F-width}

  • 获取元素内部的宽度和高度(包括内容区和内边距)

element.offsetHeight / Width {#element.offsetheight-%2F-width}

  • 获取元素的可见框大小(包括内容区、内边距和边框)

element.scrollHeight / Width {#element.scrollheight-%2F-width}

  • 获取元素滚动区域的大小

element.offsetParent {#element.offsetparent}

  • 获取元素的定位父元素

当前元素最近的开启了定位的祖先元素,如果定位的元素都没有开启定位,则返回 body。

element.offsetTop / Left {#element.offsettop-%2F-left}

  • 获取元素相对于其定位父元素的偏移量

element.scrollTop / Left {#element.scrolltop-%2F-left}

  • 获取或设置元素滚动条的偏移量
 <button id="btn">点我一下</button>
 <hr>
 <div>
     <div id="box1">
         <div id="box2"></div>
     </div>
</div>
<script>

    const btn = document.getElementById("btn")
    const box1 = document.getElementById("box1")

    btn.onclick = function(){
        // console.log(box1.scrollHeight)
        // console.log(box1.offsetParent)
        console.log(box1.scrollTop)
    }</code></pre>



 
### \>修改操作Class {#%3E%E4%BF%AE%E6%94%B9%E6%93%8D%E4%BD%9Cclass}


 
#### element.classList {#element.classlist}


 
>   这是一个对象,并提供了对当前元素的类的各种操作方法
>
>  

 
#### element.classList.add( ) 向元素添加一个或多个Class {#element.classlist.add(-)-%E5%90%91%E5%85%83%E7%B4%A0%E6%B7%BB%E5%8A%A0%E4%B8%80%E4%B8%AA%E6%88%96%E5%A4%9A%E4%B8%AAclass}


 
#### element.classList.remove( ) 移除元素中的一个或多个Class {#element.classlist.remove(-)-%E7%A7%BB%E9%99%A4%E5%85%83%E7%B4%A0%E4%B8%AD%E7%9A%84%E4%B8%80%E4%B8%AA%E6%88%96%E5%A4%9A%E4%B8%AAclass}


 
#### element.classList.toggle( ) 切换元素的Class {#element.classlist.toggle(-)-%E5%88%87%E6%8D%A2%E5%85%83%E7%B4%A0%E7%9A%84class}


 
#### element.classList.replace( ) 替换Class {#element.classlist.replace(-)-%E6%9B%BF%E6%8D%A2class}


 
#### element.classList.contains( ) 检查Class {#element.classlist.contains(-)-%E6%A3%80%E6%9F%A5class}


 
```vbscript-html
<!DOCTYPE html>
<html lang="zh">
    <head>
        <meta charset="UTF-8" />
        <meta http-equiv="X-UA-Compatible" content="IE=edge" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>Document</title>
        <style>
            .box1 {
                width: 200px;
                height: 200px;
                background-color: #bfa;
            }

            .box2{
                background-color: yellow;
                width: 300px;
                height: 500px;
                border: 10px greenyellow solid;
            }
        &lt;/style&gt;
    &lt;/head&gt;
    &lt;body&gt;
        &lt;button id="btn"&gt;点我一下&lt;/button&gt;

        &lt;hr /&gt;

        &lt;div class="box1 box3 box4"&gt;&lt;/div&gt;

        &lt;script&gt;
            /* 
                点击按钮后,修改box1的宽度
            */
            const btn = document.getElementById("btn")
            const box1 = document.querySelector(".box1")

            btn.onclick = function () {

                // box1.className += " box2"
                // box1.classList.add("box2", "box3", "box4")
                // box1.classList.add("box1")

                // box1.classList.remove("box2")
                // box1.classList.toggle("box2")
                // box1.classList.replace("box1", "box2")
                let result = box1.classList.contains("box3")
                console.log(result) 
            }
        &lt;/script&gt;
    &lt;/body&gt;



`</html>`

```


<br />



 
### \>事件对象 {#%3E%E4%BA%8B%E4%BB%B6%E5%AF%B9%E8%B1%A1}


 
>   
> #### 简介(Event) {#%E7%AE%80%E4%BB%8B(event)}
>
>
>   
>
>    
> * 事件对象就是有浏览器在事件触发时所创建的对象,这个对象中封装了时间相关的各种信息。
>
>
>
>    
> * 通过事件对象可以获取到事件的详细信息,比如:鼠标的坐标、键盘的按键...
>
>
>
>    
> * 浏览器在创建时间后,会将事件对象作为响应函数的参数传递,所以我们可以在事件的回调函数中定义一个形参来接收事件对象。
>
>
>
>    
> * 在DOM中存在着多种不同类型的事件对象,它们有着共同的祖先,就是 Event。

>
>
>   
>  

 
```vbscript-html
<!DOCTYPE html>
<html lang="zh">
    <head>
        <meta charset="UTF-8" />
        <meta http-equiv="X-UA-Compatible" content="IE=edge" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>Document</title>
        <style>
            #box1{
                width: 300px;
                height: 300px;
                border: 10px greenyellow solid;
            }

        &lt;/style&gt;
    &lt;/head&gt;
    &lt;body&gt;
        &lt;div id="box1"&gt;&lt;/div&gt;

        &lt;script&gt;
            const box1 = document.getElementById("box1")

            // box1.onmousemove = event =&gt; {
            //     console.log(event)
            // }

            box1.addEventListener("mousemove", event =&gt; {
                console.log(event.clientX, event.clientY)

                box1.textContent = event.clientX + "," + event.clientY
            })
        &lt;/script&gt;
    &lt;/body&gt;



`</html>`

```


<br />



 
### 冒泡(bubble) {#%E5%86%92%E6%B3%A1(bubble)}


 
>   事件的冒泡就是指事件的向上传导。
>
>   
> 当元素上的某个事件被触发后,其祖先元素上的相同事件也会被同时触发。
>
>   
> 冒泡的存在大大的简化了代码的编写,但是在一些场景下我们并不希望冒泡存在,所以我可以通过时间对象来取消冒泡
>
>  

 
#### event.target 触发事件的对象 {#event.target-%E8%A7%A6%E5%8F%91%E4%BA%8B%E4%BB%B6%E7%9A%84%E5%AF%B9%E8%B1%A1}


 
#### event.currentTarget 绑定事件的对象(同this) {#event.currenttarget-%E7%BB%91%E5%AE%9A%E4%BA%8B%E4%BB%B6%E7%9A%84%E5%AF%B9%E8%B1%A1(%E5%90%8Cthis)}


 
#### event.stopPropagetion( ) 停止事件传导 {#event.stoppropagetion(-)-%E5%81%9C%E6%AD%A2%E4%BA%8B%E4%BB%B6%E4%BC%A0%E5%AF%BC}


 
#### event.preventDefault( ) 取消默认行为 {#event.preventdefault(-)-%E5%8F%96%E6%B6%88%E9%BB%98%E8%AE%A4%E8%A1%8C%E4%B8%BA}


 
````vbscript-html
<!DOCTYPE html>
<html lang="zh">
    <head>
        <meta charset="UTF-8" />
        <meta http-equiv="X-UA-Compatible" content="IE=edge" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>Document</title>
        <style>
            #box1 {
                width: 300px;
                height: 300px;
                background-color: greenyellow;
            }

            #box2 {
                width: 250px;
                height: 250px;
                background-color: #ff0;
            }

            #box3 {
                width: 200px;
                height: 200px;
                background-color: orange;
            }
        &lt;/style&gt;
    &lt;/head&gt;
    &lt;body&gt;
        &lt;div id="box1"&gt;
            &lt;div id="box2"&gt;
                &lt;div id="box3"&gt;&lt;/div&gt;
            &lt;/div&gt;
        &lt;/div&gt;

        &lt;a id="chao" href="https://parlo.cc"&gt;超链接&lt;/a&gt;

        &lt;script&gt;
            // 事件对象
            const box1 = document.getElementById("box1")
            const box2 = document.getElementById("box2")
            const box3 = document.getElementById("box3")
            const chao = document.getElementById("chao")

            chao.addEventListener("click", (event) =&gt; {

                event.preventDefault() // 取消默认行为

                alert("被点了~~~")

            })

            box1.addEventListener("click", function (event) {
                // alert(event)
                // console.log(event.target)
                // console.log(this)

                console.log(event.currentTarget)

                // alert("Hello 我是box1")
            })

            // box2.addEventListener("click", function(event){
            //     event.stopPropagation()
            //     alert("我是box2")
            // })</code></pre>



 
### \>事件委派 {#%3E%E4%BA%8B%E4%BB%B6%E5%A7%94%E6%B4%BE}


 
委派就是将本该绑定给多个元素的事件,统一绑定给 document,这样可以降低代码复杂度,方便维护。

 
```vbscript-html
<!DOCTYPE html>
<html lang="zh">
    <head>
        <meta charset="UTF-8" />
        <meta http-equiv="X-UA-Compatible" content="IE=edge" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>Document</title>
    </head>
    <body>
        <button id="btn">点我一下</button>

        &lt;hr /&gt;

        &lt;ul id="list"&gt;
            &lt;li&gt;&lt;a href="javascript:;"&gt;链接一&lt;/a&gt;&lt;/li&gt;
            &lt;li&gt;&lt;a href="javascript:;"&gt;链接二&lt;/a&gt;&lt;/li&gt;
            &lt;li&gt;&lt;a href="javascript:;"&gt;链接三&lt;/a&gt;&lt;/li&gt;
            &lt;li&gt;&lt;a href="javascript:;"&gt;链接四&lt;/a&gt;&lt;/li&gt;
        &lt;/ul&gt;

        &lt;script&gt;
            /* 
                我一个希望:
                    只绑定一次事件,既可以让所有的超链接,包括当前的和未来新建的超链接都具有这些事件

                思路:
                    可以将事件统一绑定给document,这样点击超链接时由于事件的冒泡,
                        会导致document上的点击事件被触发,这样只绑定一次,所有的超链接都会具有这些事件
            */

            const list = document.getElementById("list")
            const btn = document.getElementById("btn")

            // 获取list中的所有链接
            const links = list.getElementsByTagName("a")


            document.addEventListener("click", (event) =&gt; {
                // 在执行代码前,先来判断一下事件是由谁触发
                // 检查event.target 是否在 links 中存在

                // console.log(Array.from(links))

                if([...links].includes(event.target)){
                    alert(event.target.textContent)
                }                
            })

            // 点击按钮后,在ul中添加一个新的li
            btn.addEventListener("click", () =&gt; {
                list.insertAdjacentHTML(
                    "beforeend",
                    "&lt;li&gt;&lt;a href='javascript:;'&gt;新超链接&lt;/a&gt;&lt;/li&gt;"
                )
            })
        &lt;/script&gt;
    &lt;/body&gt;



`</html>`

```


<br />



 
### \>事件的捕获 {#%3E%E4%BA%8B%E4%BB%B6%E7%9A%84%E6%8D%95%E8%8E%B7}


 
>   在 DOM 中,事件的传播主要分为三个阶段
>
>   
>
>    
> * 捕获阶段(从祖先元向目标元素进行事件的捕获)
>
>
>
>    
> * 目标阶段(触发事件的对象)
>
>
>
>    
> * 冒泡阶段(由目标元素向祖先元素进行事件的冒泡)

>
>
>   
>  

 
当前元素触发事件后,会先从当前元素最大的祖先元素开始向当前元素进行事件的捕获。默认情况下,事件不会在捕获阶段触发。

 
如果希望在捕获阶段触发事件,可以将 addEventListener 的第三个参数设置为 true。一般情况下我们不希望事件在捕获阶段实现,所以通常我们并不需要设置第三个参数。

 
#### event.Phase 表示事件触发的阶段 {#event.phase-%E8%A1%A8%E7%A4%BA%E4%BA%8B%E4%BB%B6%E8%A7%A6%E5%8F%91%E7%9A%84%E9%98%B6%E6%AE%B5}


 
>   1 捕获阶段,2 目标阶段,3 冒泡阶段
>
>  

 
```vbscript-html
<!DOCTYPE html>
<html lang="zh">
    <head>
        <meta charset="UTF-8" />
        <meta http-equiv="X-UA-Compatible" content="IE=edge" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>Document</title>
        <style>
            #box1 {
                width: 300px;
                height: 300px;
                background-color: greenyellow;
            }

            #box2 {
                width: 200px;
                height: 200px;
                background-color: orange;
            }

            #box3 {
                width: 100px;
                height: 100px;
                background-color: tomato;
            }
        &lt;/style&gt;
    &lt;/head&gt;
    &lt;body&gt;
        &lt;div id="box1"&gt;
            &lt;div id="box2"&gt;
                &lt;div id="box3"&gt;&lt;/div&gt;
            &lt;/div&gt;
        &lt;/div&gt;

        &lt;script&gt;
            const box1 = document.getElementById("box1")
            const box2 = document.getElementById("box2")
            const box3 = document.getElementById("box3")

            box1.addEventListener("click", event =&gt; {
                alert("1" + event.eventPhase)
            })

            box2.addEventListener("click", event =&gt; {

                alert("2" + event.eventPhase)
            })

            box3.addEventListener("click", event =&gt; {
                alert("3" + event.eventPhase)
            })

        &lt;/script&gt;
    &lt;/body&gt;



`</html>`

```


<br />



 
<br />




````

赞(3)
未经允许不得转载:工具盒子 » JavaScript - DOM