前端 --- WEB APIS (Dom / Bom 操作)

0.简介

0.1 干什么的?

DOM (Document Object Model --- 文档对象模型),是浏览器提供的一套专门用来操作网页内容的功能

0.2 DOM树

将HTML文档以树状结构直观的表现出来,称之为文档树或DOM树,用以描述网页内容关系的名词,文档树直观的体现了标签与标签之间的关系

0.2 DOM对象

浏览器根据html标签生成的JS对象,所有的标签属性都可以在这个对象上面找到,修改这个对象的属性会自动映射到标签身上,即当网页内容当做对象来处理

1. 获取DOM元素

1.1 css 选择器

1. 获取一个

document.querySelector("ul li:nth-child(1)")

2. 获取所有

document.querySelectorAll("ul li")

2. 操作DOM元素

2.1 文本内容

1. innerText

innerText 不识别字符串中的标签

const li1 = document.querySelector("ul li:first-child")
i1.innerText = "<strong>hello</strong>"

2. innerHTML

innerHTML 识别字符串中的标签

const li1 = document.querySelector("ul li:first-child")
i1.innerHTML = "<strong>hello</strong>"

2.2 标签的 CSS 样式

1. 手动添加

const box = document.querySelector(".box")
box.style.height = "200px"
box.style.width = "200px"
box.style.backgroundColor = "orange"

2. 添加类名,覆盖之前

<style>
    .box {
        width: 200px;
        height: 200px;
        background-color: gray;
    }
</style>

<div>1</div>

<script>
    const box = document.querySelector("div")
    box.className = "box"  // 给div标签添加box类名,就有了这些CSS属性,注意会覆盖之前的所有类名
</script>

3. 追加类名,不覆盖

const box = document.querySelector("div")

// 追加类名
box.classList.add("box")

// 删除类名
box.classList.remove("box")

// 切换类名 -- 有box类名,则删除这个类名,没有就追加
box.classList.toggle("box")

// 是否有类名
box.classList.contains("box")

2.3 表单属性

0. 表单代码示例

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

<form action="#">
    <!-- 文本输入框 -->
    <label for="userName">用户名:</label>
    <input id="userName" type="text">
    <br>
    <!-- 密码输入框 -->
    <label for="pwd">密码:</label>
    <input id="pwd" type="password">
    <br>
    <!-- 单选框 -->
    <input type="radio" name="sex">男
    <input type="radio" name="sex">女
    <br>
    <!-- 多选框 -->
    <input type="checkbox" name="hobby">抽烟
    <input type="checkbox" name="hobby">喝酒
    <input type="checkbox" name="hobby">烫头
    <br>
    <!-- 单选下拉框 -->
    <select name="city" id="city">
        <option value="1">北京</option>
        <option value="2">上海</option>
        <option value="3">广州</option>
    </select>
    <br>
    <!-- 多选下拉框 -->
    <select name="tag" id="tag" multiple>
        <option value="1">宅男</option>
        <option value="2">二次元</option>
        <option value="3">直男</option>
    </select>
</form>

</body>
</html>

1. 获取输入框的值

const uName = document.querySelector("#userName")
uName.value

2. 设置输入框的值

const uName = document.querySelector("#userName")
uName.value  = 123

3. 修改输入框的属性

1. 修改输入框的类型

const uName = document.querySelector("#userName")
uName.type = "password"  // 将文本输入框改为密码输入框

2. 输入框 / 选择框的禁用效果

const uName = document.querySelector("#userName")
uName.disabled = true   // 禁用
uName.disabled = false  // 取消禁用

3. 单选框 / 多选框 的选中效果

// 单选框
const sexSelector = document.querySelectorAll("[name='sex']")
sexSelector[0].checked = true   // true为选中,false为不选中

// 多选框
const hobby = document.querySelectorAll("[type='checkbox']")
hobby[0].checked = true  	    // true为选中,false为不选中
hobby[1].checked = true         // true为选中,false为不选中

4. 单选下拉框 / 多选下拉框 的选中效果

// 单选下拉框
const city = document.querySelector("#city")
city[2].selected = true  // true为选中,false为不选中

// 多选下拉框
const city = document.querySelector("#tag")
city[1].selected = true
city[2].selected = true

2.4 自定义属性

设置自定义属性

<!-- 以data-属性名定义的属性,都是自定义属性 -->
<div class="demo" data-x="1" data-y="2">1</div>

获取自定义属性的值

const demo = document.querySelector(".demo")
demo.dataset.x
demo.dataset.y

3. 定时器

3.1 间歇函数

到达一定时间,执行一次,持续执行

1. 声明

1. 匿名回调函数

setInterval(function () {
    console.log(1)
},1000)  // 时间间隔,以毫秒为单位

2. 具名回调函数

function printer() {
    console.log(1)
}
setInterval(printer,1000)  // 以毫秒为单位

2. 清除

// 具名回调函数
function printer() {
    console.log(1)
}

// 开启定时器
let timerID = setInterval(printer,1000)  // 以毫秒为单位

// 根据开启定时器的返回值,关闭定时器
clearInterval(timerID)

3. 案例

1. 用户协议倒计时

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<button class="btn" disabled>我已同意用户协议(60)</button>
<script>
    let count = 5

    function printer() {
        count--
        const btn = document.querySelector(".btn")
        btn.innerHTML = `我已同意用户协议(${count})`
        if (count <= 0) {
            btn.disabled = false
            btn.innerHTML = `同意`
            clearInterval(timerID)
        }
    }

    let timerID = setInterval(printer, 1000)  // 以毫秒为单位
</script>
</body>
</html>

3.2 延时函数

一定时间后执行一次,只执行一次

1. 声明

1. 匿名回调函数

setTimeout(function () {
    console.log(1)
},1000)  // 时间间隔,以毫秒为单位

2. 具名回调函数

function printer() {
    console.log(1)
}
setTimeout(printer,1000)  // 以毫秒为单位

2. 清除

// 具名回调函数
function printer() {
    console.log(1)
}

// 开启定时器
let timerID = setTimeout(printer,1000)  // 以毫秒为单位

// 根据开启定时器的返回值,关闭定时器
clearTimeout(timerID)

3. 案例

1. 5 秒后自动关闭的广告

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        .dady{
            position: relative;
            width: 1000px;
            height: 200px;
            background-color: pink;
            margin: 100px auto;
            text-align: center;
            font-size: 50px;
            line-height: 200px;
            font-weight: 700;
        }
        .baby{
            position: absolute;
            right: 20px;
            top: 10px;
            width: 20px;
            height: 20px;
            text-align: center;
            line-height: 20px;
            font-size: 16px;
            cursor: pointer;
        }
    </style>
</head>
<body>
<div class="dady">
    我是广告1
    <div class="baby">x</div>
</div>

<script>
    function clearGuanggao() {
        const dady = document.querySelector(".dady")
        dady.style.display = "none"
    }
    setTimeout(clearGuanggao,5000)
</script>
</body>
</html>

3.3 对比

  1. 延时函数: 只执行一次
  2. 间歇函数: 每隔一段时间就执行一次,除非手动清除

4. 事件监听

4.1 事件绑定

1. 事件监听添加事件

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

btn.addEventListener("click",function (event) {
})

2. on添加事件

<button class="btn" onclick="printer()">同意</button>
<button class="btn" ononmouseenter="printer()">同意</button>

<script>
    function printer() {
        console.log(1)
    }
</script>

3. 区别

1. 传统 on 绑定事件

  1. 同一个对象,后面注册的事件会覆盖前面注册的事件(同一个事件)
  2. 直接使用null覆盖就可以实现事件的解绑
  3. 都是冒泡阶段执行

2. 事件监听注册

  1. 后面注册的事件不会覆盖前面注册的事件(同一个事件)
  2. 可以通过第三个参数确定是在冒泡或者捕获阶段执行
  3. 必须使用removeEventListener(事件类型,事件处理函数,是否使用事件捕获)
  4. 匿名函数无法被解绑

4.2 鼠标事件

1. 点击事件

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

btn.addEventListener("click",function (event) {
})

2. 鼠标经过

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

// mouseover,有事件冒泡效果,不推荐
btn.addEventListener("mouseenter",function (event) {
})

3. 鼠标离开

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

// mouseout,有事件冒泡效果,不推荐
btn.addEventListener("mouseleave",function (event) {
})

4.3 焦点事件

1. 获得焦点

const userName = document.querySelector(".userName")

userName.addEventListener("focus",function (event) {
})

2. 失去焦点

const userName = document.querySelector(".userName")

userName.addEventListener("blur",function (event) {
})

4.4 键盘事件

1. 键盘按下

const userName = document.querySelector(".userName")

userName.addEventListener("keydown",function (event) {
})

2. 键盘抬起

const userName = document.querySelector(".userName")

userName.addEventListener("keyup",function (event) {
})

4.5 文本输入事件

const userName = document.querySelector(".userName")
userName.addEventListener("input",function (event) {
    console.log(userName.value)
})

4.6 音视频事件

1. 播放位置发生改变

const video = document.querySelector("video")

video.ontimeupdate = function (e) {
    console.log(e.timeStamp)  // 获取当前播放的时间
}

2. 加载完毕后,未开始播放前只触发一次

音视频框加载完成后,并未开始播放时只触发一次

const video = document.querySelector("video")

video.onloadeddata = function (e) {
    console.log(e.timeStamp)  // 获取当前播放的时间
}

4.7 事件对象 --- event

1. 使用场景

  1. event中有事件触发时的相关信息
  2. 鼠标点击事件中,事件对象中保存了鼠标点在哪个位置等信息
  3. 可以使用事件对象来判断用户按下了什么按键,来执行什么操作

2.常见属性

1. type

获取当前的事件类型

2. clientX / clientY

获取光标相对于浏览器窗口左上角的位置

**3. offsetX / offsetY **

获取光标相对于当前DOM元素左上角的位置

**4. key **

获取用户按下的键盘的值

5. target

当前点击的DOM对象

target.classList   // 类名列表
target.classList.contains("del")   // 类名列表中是否包含del的类名

4.8 事件流

事件流指的是事件完整执行过程中的流动路径

4.9 事件捕获

简单来说,捕获是父到子

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        .father{
            width: 400px;
            height: 400px;
            background-color: pink;
        }
        .son{
            width: 200px;
            height: 200px;
            background-color: orange;
        }
    </style>
</head>
<body>
<div class="father">
    <div class="son"></div>
</div>
<script>
    document.addEventListener("click",function () {
        alert("我是爷爷元素")
    },true)  // 第三个参数传入true,用于开启事件捕获

    const father = document.querySelector(".father")
    father.addEventListener("click",function () {
        alert("我是父亲元素")
    },true)   // 第三个参数传入true,用于开启事件捕获

    const son = document.querySelector(".son")
    son.addEventListener("click",function () {
        alert("我是儿子元素")
    },true)  // 第三个参数传入true,用于开启事件捕获
</script>
</body>
</html>

4.10 事件冒泡

1. 冒泡现象

当一个元素的事件被触发时,同样的事件将会在该元素的所有祖先元素中依次被触发,这一过程被称为事件冒泡

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        .father{
            width: 400px;
            height: 400px;
            background-color: pink;
        }
        .son{
            width: 200px;
            height: 200px;
            background-color: orange;
        }
    </style>
</head>
<body>
<div class="father">
    <div class="son"></div>
</div>
<script>
    document.addEventListener("click",function () {
        alert("我是爷爷元素")
    })   // 第三个参数插入false或者不传,就是事件冒泡,默认为事件冒泡机制

    const father = document.querySelector(".father")
    father.addEventListener("click",function () {
        alert("我是父亲元素")
    })   // 第三个参数插入false或者不传,就是事件冒泡,默认为事件冒泡机制

    const son = document.querySelector(".son")
    son.addEventListener("click",function () {
        alert("我是儿子元素")
    })  // 第三个参数插入false或者不传,就是事件冒泡,默认为事件冒泡机制
</script>
</body>
</html>

2. 阻止事件流

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        .father{
            width: 400px;
            height: 400px;
            background-color: pink;
        }
        .son{
            width: 200px;
            height: 200px;
            background-color: orange;
        }
    </style>
</head>
<body>
<div class="father">
    <div class="son"></div>
</div>
<script>
    document.addEventListener("click",function () {
        alert("我是爷爷元素")
    })

    const father = document.querySelector(".father")
    father.addEventListener("click",function () {
        alert("我是父亲元素")
    })

    const son = document.querySelector(".son")
    son.addEventListener("click",function (e) {
        alert("我是儿子元素")
        e.stopPropagation()   // 阻止事件流动,包括捕获和流动
    })
</script>
</body>
</html>

4.11 事件解绑

1. onclick 解绑

// 绑定事件
btn.onclick = function () {
    alert("点击了")
}

// 解绑事件
btn.onclick = null


// 事件只触发一次
btn.onclick = function () {
    alert("点击了")
    btn.onclick = null
}

2. addEventListener 解绑

// 必须是具名函数
function fn() {
    alert("我是儿子元素")
}

// 绑定事件
btn.addEventListener("click",fn)

// 解绑事件
btn.removeEventListener("click",fn)

4.12 事件委托

1. 原理

利用事件冒泡的特点完成事件委托, 原理就是,只给父元素注册事件,当触发子元素的时候,会冒泡到父元素身上,从而触发父元素的事件

2. 示例

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        .changeColor {
            color: red;
        }
    </style>
</head>
<body>
<ul>
    <li>我是第一个li</li>
    <li>我是第二个li</li>
    <li>我是第三个li</li>
    <li>我是第四个li</li>
    <li>我是第五个li</li>
    <li>我是第六个li</li>
    <p>我是p标签</p>
</ul>
<script>
    const ul = document.querySelector("ul")
    ul.addEventListener("click",function (e) {
        // e.target 就是当前点击的那个对象
        // 只点击li标签才有变色效果
        if (e.target.tagName === "LI"){
            e.target.classList.add("changeColor")
        }
        
        // 查看target对象上的属性和方法
        console.dir(e.target)  

    })

</script>
</body>
</html>

3. 优点 / 好处

  1. 减少注册次数,提高程序性能

4.13 阻止元素默认行为

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        .changeColor {
            color: red;
        }
    </style>
</head>
<body>
<form action="#">
    姓名: <input type="text" name="username">
    <br>
    <input type="submit"></input>
</form>
<script>
    const form = document.querySelector("form")
    form.addEventListener("submit",function (e) {
        e.preventDefault()   // 阻止form表单的默认行为
    })

</script>
</body>
</html>

4.14 页面加载事件

1. 等待页面元素完全加载完毕

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        .changeColor {
            color: red;
        }
    </style>
</head>
<body>
<script>
    // 等待页面所有资源完全加载完毕,立刻执行回调函数
    window.addEventListener("load",function () {
        const btn = document.querySelector("button")
        btn,addEventListener("click",function () {
            alert(1)
        })
    })
</script>

<button>点击</button>
</body>
</html>

2. 不等待样式表、图像等完全加载

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        .changeColor {
            color: red;
        }
    </style>
</head>
<body>
<script>
    // 等待初始的HTML文旦完全加载和解析完成后,触发 DOMContentLoaded 事件,无需等待样式表、图像等完全加载,立刻执行回调函数
    domcument.addEventListener("DOMContentLoaded",function () {
        const btn = document.querySelector("button")
        btn,addEventListener("click",function () {
            alert(1)
        })
    })
</script>

<button>点击</button>
</body>
</html>

4.15 页面滚动事件

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        .changeColor {
            color: red;
        }
    </style>
</head>
<body>
<script>
    window.addEventListener("scroll",function (e) {
        document.documentElement.scrollLeft   // 左侧被拉过的像素值
        document.documentElement.scrollTop    // 顶部被拉过的像素值
    })
    
    document.documentElement.scrollTop = 500    // 打开页面滚动条就滑动了500px的距离
    window.scrollTo(0,0)  // 滚动条到顶部
</script>

<button>点击</button>
</body>
</html>

4.16 页面尺寸事件

// 检测窗口尺寸
document.documentElement.clientWidth   // 获取元素的宽度,不包含border,包含padding,document.documentElement为html元素
document.documentElement.clientHeight  // 获取元素的高度,不包含border,包含padding,document.documentElement为html元素
document.documentElement.offsetWidth   // 获取元素的宽度,包含border,padding,content,document.documentElement为html元素
document.documentElement.offsetHeight  // 获取元素的高度,包含border,padding,content,document.documentElement为html元素
document.documentElement.offsetLeft    // 获取元素距离自己带有定位属性的父级元素的左边距离
document.documentElement.offsetTop     // 获取元素距离自己带有定位属性的父级元素的上边距离

document.documentElement.getBoundingClientRect()     // 获取元素的大小及其相对于视口的位置

// 窗口尺寸改变时触发事件
window.addEventListener("resize",function () {
})

4.16 移动端事件

1. 触屏事件

1. 手指触摸到一个 DOM 元素时触发的事件

const dady = document.querySelector(".dady")
dady.addEventListener("touchstart",function () {
    console.log(1)
})

2. 手指在一个 DOM 元素上滑动时触发

const dady = document.querySelector(".dady")
dady.addEventListener("touchmove",function () {
    console.log(1)
})

3. 手指在一个 DOM 元素上移开时触发

const dady = document.querySelector(".dady")
dady.addEventListener("touchchend",function () {
    console.log(1)
})

5. 环境对象 this

是指函数内部特殊的变量 this , 它代表着当前函数运行时所处的环境

函数的调用方式不同,this 指向的对象也不同,原则是,谁调用的这个函数,这个函数中的 this 就是谁

6. 日期对象

6.1 实例化

1. 获取当前时间

const date = new Date()

2. 获取指定时间

const date = new Date("2022-5-1 08:30:00")

6.2 常用方法

1. 获取年份

const date = new Date()
date.getFullYear()

2. 获取月份

const date = new Date()
date.getMonth() + 1  // 取到的月份是0-11,需要手动+1

3. 获取天

不同月份,取值也不相同

const date = new Date()
date.getDate()

4. 获取星期几

星期天是0,范围是 0 - 6

const date = new Date()
date.getDay()

5. 获取小时

const date = new Date()
date.getHours()

6. 获取分钟

const date = new Date()
date.getMinutes()

7. 获取秒

const date = new Date()
date.getSeconds()

8. 获取格式化后的日期

const date = new Date()
return date.toLocaleString()      // 2024/5/8 16:24:56

9. 获取年月日

const date = new Date()
return date.toLocaleDateString()  // 2024/5/8

10. 获取时分秒

const date = new Date()
return date.toLocaleTimeString()  // 16:24:56

6.3 时间戳

从1970年01月01日00时00分00秒起至现在的毫秒数

将来的时间戳 - 当前时间戳 = 剩余的毫秒数 / 1000 = 秒数

方法一:

// 获取当前时间戳
const date = new Date()   
date.getTime()

// 获取指定时间戳
const date = new Date("2024-5-8 16:24:56")
date.getTime()     

方法二:

// 获取当前时间戳
const time = +new Date()   

// 获取指定时间戳
const time = +new Date("2024-5-8 16:24:56")  

**方法三: **

// 只能获取当前时间戳
const time = Date.now()

6.4 案例

1. 同步显示时间在页面中

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div class="dateContent"></div>
<script>
    const dateContent = document.querySelector(".dateContent")
    function getDate() {
        const date = new Date()
        let y = date.getFullYear()
        let m = date.getMonth() + 1
        let d = date.getDate()
        let H = date.getHours()
        let M = date.getMinutes()
        let S = date.getSeconds()
        return `${y}-${m}-${d} ${H < 10 ? "0" + H : H}:${M < 10 ? "0" + M : M}:${S < 10 ? "0" + S : S}`
    }
    dateContent.innerHTML = getDate()
    setInterval(function () {
        dateContent.innerHTML = getDate()
    },1000)
</script>
</body>
</html>

2. 显示星期几

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div class="dateContent"></div>
<script>
    const dateContent = document.querySelector(".dateContent")

    function getDate() {
        const date = new Date()
        const arr = ["星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"]
        let D = date.getDay()
        return `${arr[D]}`
    }
    dateContent.innerHTML = getDate()
    setInterval(function () {
        dateContent.innerHTML = getDate()
    }, 1000)
</script>
</body>
</html>

3. 倒计时

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div class="today"></div>
<br>
<div class="leave">
    <div>下班倒计时</div>
    <div class="leaveTime"></div>
</div>
<br>
<div class="leaveTime"> 17:30:00 下班</div>
<script>
    const today = document.querySelector(".today")
    const dateContent = document.querySelector(".dateContent")
    const leaveTime = document.querySelector(".leave .leaveTime")

    function getDateString() {
        const date = new Date()
        let y = date.getFullYear()
        let m = date.getMonth() + 1   // 月份记得 + 1
        let d = date.getDate()
        let H = date.getHours()
        let M = date.getMinutes()
        let S = date.getSeconds()
        return `${y}-${m}-${d} ${H < 10 ? "0" + H : H}:${M < 10 ? "0" + M : M}:${S < 10 ? "0" + S : S}`
    }

    function leaveCountTime() {
        const nowdate = +new Date()    // 当前时间戳
        const localDate = new Date()
        const leaveDate = +new Date(localDate.toLocaleDateString() + " 17:30:00")  // 将来时间戳
        let allTime = (leaveDate - nowdate) / 1000  // 得到的是毫米,记得除以1000
        let h = parseInt(allTime / 60 / 60 % 24)   // 计算出小时
        let m = parseInt(allTime / 60 % 60)        // 计算出分钟
        let s = parseInt(allTime % 60)             // 计算出秒
        return `${h < 10 ? "0" + h : h}:${m < 10 ? "0" + m : m}:${s < 10 ? "0" + s : s}` // 补零操作
    }

    today.innerHTML = "今天是 " + getDateString()
    setInterval(function () {
        today.innerHTML = "今天是 " + getDateString()
    }, 1000)

    leaveTime.innerHTML = leaveCountTime()
    setInterval(function () {
        leaveTime.innerHTML = leaveCountTime()
    }, 1000)
</script>
</body>
</html>

7. 节点操作

7.1 获取父节点

获取最近一级的父节点

1. 语法

const baby = document.querySelector(".baby")
baby.parentNode

2. 示例

需求: 点击右上角的 x,隐藏整个盒子

效果图

代码实现

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        .dady{
            position: relative;
            width: 1000px;
            height: 200px;
            background-color: pink;
            margin: 100px auto;
            text-align: center;
            font-size: 50px;
            line-height: 200px;
            font-weight: 700;
        }
        .baby{
            position: absolute;
            right: 20px;
            top: 10px;
            width: 20px;
            height: 20px;
            text-align: center;
            line-height: 20px;
            font-size: 16px;
            cursor: pointer;
        }
    </style>
</head>
<body>
<div class="dady">
    我是广告
    <div class="baby">x</div>
</div>

<script>
    // 绑定在子元素,查找自己的父节点,隐藏父元素节点
    const baby = document.querySelector(".baby")
    baby.addEventListener("click",function () {
        this.parentNode.style.display = "none"
    })
    
    // 使用事件委托,事件绑定在父元素,当点击子元素时,事件冒泡到父元素,触发自己所绑定的点击事件
    const dady = document.querySelector(".dady")
    dady.addEventListener("click",function () {
        this.style.display = "none"
    })
</script>
</body>
</html>

需求: 多个盒子,点击右上角的 x,隐藏整个盒子

效果图

代码实现

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        .dady{
            position: relative;
            width: 1000px;
            height: 200px;
            background-color: pink;
            margin: 100px auto;
            text-align: center;
            font-size: 50px;
            line-height: 200px;
            font-weight: 700;
        }
        .baby{
            position: absolute;
            right: 20px;
            top: 10px;
            width: 20px;
            height: 20px;
            text-align: center;
            line-height: 20px;
            font-size: 16px;
            cursor: pointer;
        }
    </style>
</head>
<body>
<div class="dady">
    我是广告1
    <div class="baby">x</div>
</div>

<div class="dady">
    我是广告2
    <div class="baby">x</div>
</div>
<script>
    // 找到多个元素,循环为每个元素为其绑定点击事件,关闭其父元素节点
    const baby = document.querySelectorAll(".baby")
    for (let i = 0;i<baby.length;i++){
        baby[i].addEventListener("click",function () {
            this.parentNode.style.display = "none"
        })
    }

</script>
</body>
</html>

7.2 获取子节点

1. 获取所有子节点

包括元素节点、文本节点(空格、换行)、注释节点等

1. 语法

const dady = document.querySelector(".dady")
dady.childNodes

2. 获取所有元素子节点

仅获取所有元素节点,返回的是一个伪数组

1. 语法

const ul = document.querySelector("ul")
ul.children

7.3 获取兄弟节点

1. 下一个兄弟

const baby1 = document.querySelector(".baby1")
baby1.nextElementSibling

2. 上一个兄弟

const baby1 = document.querySelector(".baby1")
baby1.previousElementSibling

7.4 创建节点

document.createElement("li")

7.5 新增节点

1. 插入节点

const ul = document.querySelector("ul")
const li = document.createElement("li")
ul.insertBefore(li,ul.children[0])   // 参数1为需要插入节点对象,参数2为插入到哪个元素对象前面

2. 追加节点

const ul = document.querySelector("ul")
const li = document.createElement("li")
ul.appendChild(li)

7.6 克隆节点

const li1 = document.querySelector("ul li:first-child")
li1.cloneNode(true)  // 参数为true,则代表克隆时会包含后代节点一起克隆,参数为false,则代表克隆时不包含后代节点,默认为false

7.7 删除节点

const ul = document.querySelector("ul")
ul.removeChild(ul.children[0])

8. BOM对象

8.1 概述

1. 介绍

  1. window对象是一个全局对象,也可以说是JavaScript中的顶级对象
  2. 像 document、alert()、console.log()这些都是window对象的属性和方法,基本BOM的属性和方法都是window的
  3. 所有通过 var 定义在全局作用域中的变量、函数都会变成window对象的属性和方法
  4. window对象下的属性和方法调用的时候可以省略window

2. 组成部分

8.2 JS 执行机制(事件循环机制)

1. 面试题

下面代码的执行顺序是什么

// 面试题一
console.log(1)
setTimeout(function () {
    console.log(2)
},1000)
console.log(3)

// 面试题二
console.log(1)
setTimeout(function () {
    console.log(2)
},0)
console.log(3)

2. 执行机制

JavaScript语言的一大特点就是单线程,也就是说: 同一时间只能做一件事

这是因为 JavaScript 这门脚本语言诞生的使命所致 --- 为了处理页面中用户的交互以及操作 DOM 而诞生的.比如我们对某个 DOM 元素进行添加和删除操作,不能同时进行.应该先进行添加,之后再删除

单线程就意味着,所有任务都需要排队,前一个任务结束,才会执行后一个任务. 这样所导致的问题是: 如果JS执行时间过长,就会造成页面的渲染不连贯,导致页面渲染加载阻塞的视觉感受

为了解决这个问题,利用多核CPU 的计算能力,H5提出 Web Worker 标准,允许 JavaScript 脚本创建多个线程,于是,JS中出现了同步异步

**同步: **

前一个任务结束后再执行后一个任务,程序的执行顺序与任务的排列书序是一致、同步的

**异步: **

在执行一个任务时,由于该任务比较耗时,可以在做这个任务的同时,处理其他任务,等这个任务可以继续做了再继续做这个任务,JS的异步是通过回调函数实现的,异步任务相关添加到任务队列(消息队列)中

JS执行机制

  1. 先将所有的任务加载到内存中,将所有的同步任务放入执行栈中
  2. js借助浏览器的多线程,执行网络请求、DOM事件、定时器等异步任务,当异步任务执行结束后,将异步任务推入任务队列中
  3. 先依次执行执行栈中的同步任务
  4. 一旦执行栈中所有的同步任务执行完毕,系统会按次序读取任务队列中的异步任务,于是被读取的异步任务结束等待状态,进入执行栈开始执行,执行完毕后,再次读取任务队列中的异步任务,此过程称为事件循环

8.3 location对象

拆分并保存了URL地址的各个组成部分

1. 常用属性和方法

1. href

location.href    // 获取当前的访问地址
location.href = "http://www.baidu.com"  // 跳转到指定地址

2. search

location.search     // 获取地址中携带的请求参数,?号及后面的所有字符串

3. hash

location.hash     // 获取地址中的哈希值, #号及后面的所有字符串

4. reload()

location.reload(true)   // 刷新当前页面,参数为true表示强制刷新,不从本地后去数据,强制发送网络请求获取数据

2. 使用场景

用户点击可以跳转,如果不点击,则5秒后自动跳转,要求有秒数倒计时

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        span{
            color: red;
        }
    </style>
</head>
<body>
<a href="http://www.baidu.com">支付成功! <span>5</span> 秒后跳转到首页</a>

<script>
    const a = document.querySelector("a")
    let num = 5
    let timerID = setInterval(function () {
        num--
        a.innerHTML = `支付成功! <span>${num}</span> 秒后跳转到首页`
        if (num <= 0){
            clearInterval(timerID)
            location.href = "http://www.baidu.com"
        }
    },1000)
</script>
</body>
</html>

8.4 navigator对象

获取浏览器自身的相关信息

1. 常用属性和方法

1. userAgent

获取浏览器的版本及平台

navigator.userAgent

2. 使用场景

根据浏览器的版本及平台跳转不同的页面

// 检测userAgent的版本,不同的设备跳转不同的页面
!(function () {
    const userAgent = navigator.userAgent
    const android = userAgent.match(/(Android);?[\s\/]+([\d.]+)?/)
    const iphone = userAgent.match(/(iPhone\sOS)\s([\d_]+)/)

    if (android || iphone){
        location.href = "http://www.baidu.com"
    }
})()

8.5 history对象

主要用于管理历史记录,该对象与浏览器地址栏的操作相对应,如前进、后退、历史记录等

1. 常用属性和方法

1. back()

history.back()   // 回退到上个页面

2. forward()

history.forward()  // 前进到下个页面

3. go()

history.go()   	// 前进或后退,参数如果是正数,就是前进,是负数就是后退

8.6 本地存储

1. 概述

用于存储数据

  1. 数据存储在浏览器中
  2. 设置、读取方便,页面刷新不丢失数据
  3. 容量较大,sessionStorage和localStorage约 5M 左右

2. localStorage

可以将数据永久存储在本地(用户的电脑),除非手动删除,否则关闭页面也会存在

特性

  1. 可以多窗口(页面)共享(同一浏览器可以共享)
  2. 以键值对的形式存储使用

1. 存储

localStorage.setItem("userName","小明")

2. 读取

localStorage.getItem("userName")

3. 删除

localStorage.removeItem("userName")  // 删除指定的键值对
localStorage.clear()    // 删除所有

4. 修改

localStorage.setItem("userName","小明2")  // 如果没有 userName 就是新增,如果有就是覆盖修改

3. sessionStorage

可以用来存储数据,但是当关闭浏览器窗口的时候,sessionStroage就会被清除

1. 存储

sessionStorage.setItem("userName","小明")

2. 读取

sessionStorage.getItem("userName")

3. 删除

sessionStorage.removeItem("userName")  // 删除指定的键值对
sessionStorage.clear()    // 删除所有

4. 修改

sessionStorage.setItem("userName","小明2")  // 如果没有 userName 就是新增,如果有就是覆盖修改

4. 存储复杂数据

1. 存储

先转成 JSON 串后,再存储

const userInfo = {
    name:"小明",
    age:18,
    gender:"男"
}
localStorage.setItem("userInfo",JSON.stringify(userInfo))

2. 读取

先将读取的 JSON 串转成 Object 对象,再读取其中的内容

JSON.parse(localStorage.getItem("userInfo"))
posted @ 2024-04-25 17:13  河图s  阅读(52)  评论(0)    收藏  举报