Web前端笔记-8、JS基础-WebAPI DOM、定时器、事件、事件流、其他事件、时间对象、DOM树、JS插件
DOM
DOM(Document Object Model-文档对象模型)
作用:DOM用来 操作网页文档,开发网页特效和实现用户交互
DOM的核心思想就是把网页内容当做对象来处理,通过对象的属性和方法对网页内容操作
Document对象
document 对象
- 是DOM 里提供的一个对象,是DOM顶级对象
- 作为网页内容的入口
- 所以它提供的属性和方法都是用来访问和操作网页内容的
获取DOM元素
根据CSS选择器获取DOM元素。
document.querySelector('css选择器')
document.querySelectorAll()
const box = document.querySelector('.box')
console.dir(box) // 打印对象
const li3 = document.querySelector('li:nth-child(3)')
// 使用属性选择器获取元素对象
const uname = document.querySelector('[type="text"]')
querySelector返回CSS选择器匹配的第一个元素对象;如果没有匹配到,则返回 null
querySelector返回CSS选择器匹配的全部元素,是NodeList 伪数组。
伪数组
得到的是一个伪数组:
- 有长度有索引号的数组
- 但是没有 pop()push()等数组方法
想要得到里面的每一个对象,则需要for遍历的方式获得
操作元素内容
innerText
innerHTML
可以通过console.dir查看document元素都有哪些属性。
- "渲染"文本内容到标签里面
- Text显示、获取纯文本,不解析标签
- HTML解析、获取标签
操作元素属性
还可以通过DOM操作元素属性,比如通过src 更换 图片地址
最常见的属性比如:href、title、src 等等
img.src = ''
操作元素样式
还可以通过 DOM对象修改标签元素的样式属性
比如通过 轮播图小圆点自动更换颜色 样式
点击按钮可以滚动图片,这是移动的的位置 translatex 等等
三种方式:
- style属性操作CSS
对象.style.样式属性 = 值
JS中用style设置的样式都是行内样式,权重较高。
- 类名操作CSS(理解,基本不用)
如果修改的样式比较多,直接通过style属性修改比较繁琐,我们可以通过借助于css类名的形式
核心:把多个样式放到CSS一个类中,然后把这个类添加到这个元素身上
对象.className = 'active'
由于class是关键字,所以使用className去代替
className是使用新值换旧值,如果需要添加一个类,需要保留之前的类名
现在不用其做替换,有时候用来获取类名(也不多)
- classList操作类(推荐)
为了解决className 容易覆盖以前的类名,我们可以通过classList方式追加和删除类名
对象.classList.add('')
对象.classList.remove('')
对象.classList.toggle('') 切换类名,有则删除,没有则添加
对象.classList.contains('') 判断是否存在类名,返回值为Boolean类型
操作表单属性
表单很多情况,也需要修改属性,比如点击眼睛,可以看到密码,本质是把表单类型转换为文本框
正常的有属性有取值的 跟其他的标签属性没有任何区别
- 获取:
DOM对象.属性 - 设置:
DOM对象.属性 = 新值
表单属性中添加就有效果,移除就没有效果,用布尔值。比如实现禁用按钮,勾选按钮等。
- 如果为 true 代表添加了该属性
- 如果是false 代表移除了该属性
比如:disabled、checked、selected
操作自定义属性
标准属性:标签天生自带的属性 比如class、id、title等,可以直接使用点语法操作比如:对象.title
自定义属性:在htmI5中推出来了专门的data-自定义属性。
使用场景:通过自定义属性可以存储数据,后期可以使用这个数据。
在标签上一律以data-开头。
在DOM对象上一律以dataset对象方式获取。 box.dataset是一个对象
<div class="box" data-id="10"></div>
<script>
const box = document.querySelector('.box')
console.log(box.dataset.id)
</script>
定时器
网页中经常会需要一种功能:每隔一段时间需要自动执行一段代码,不需要我们手动去触发
例如:网页中的倒计时
要实现这种需求,需要定时器函数
定时器函数有两种:间隔函数 和 延迟函数
间隔函数
定时器函数可以开启和关闭定时器
- 开启定时器
setInterval(函数, 间隔时间)
作用:每隔一段时间调用这个函数
注意:间隔时间单位是毫秒
返回值:定时器对应的id值。
- 关闭定时器
let timerId = setInterval(函数, 间隔时间)
clearIntervaval(timeId)
一般不会刚创建就停止,而是满足一定条件再停止
例子:轮播图。轮播图通常使用 i%数组长度
事件
事件监听
以前写的代码都是自动执行的,我们希望一段代码在某个特定的时机才去执行,比如点击按钮可以弹出警示框、比如鼠标经过显示下拉菜单等等。
事件是程序在运行的时候,发生的特定动作或者特定的事情。
语法:元素对象.addEventListener('事件类型', 事件处理函数)
事件发生后,想要执行的代码写到事件处理函数里面。
当触发指定的事件时,则事件处理函数就会被执行。
事件监听是将事件处理函数注册到元素对象身上。
事件监听也称为:事件注册、事件绑定。
事件类型要加引号,小写。
函数是点击之后再去执行,每次点击都会执行一次。
回调函数
回调函数:当一个函数当做参数来传递给另外一个函数的时候,这个函数就是回调函数(回头调用的函数)
事件监听版本
事件源.on事件类型 = function(){}
元素对象.addEventListener('事件类型', 事件处理函数)
on 方式同名事件会被覆盖,addEventListener则不会,同时拥有事件更多特性,推荐使用
事件类型
鼠标事件
click 鼠标点击
mouseenter 鼠标经过
mouseleave 鼠标离开
键盘事件
keydown 键盘按下
keyup 盘抬起
焦点事件
focus 获得焦点
blur 失去焦点
文本事件
input 表单value 被修改时触发
让一个元素对象自动获取焦点:
对象.focus()
事件对象(重要)
事件对象是什么
- 就是个对象,这个对象里有事件触发时的相关信息,包含属性和方法
- 例如:鼠标点击事件中,事件对象就存了鼠标点在哪个位置等信息
使用场景
可以判断用户按下哪个键,比如按下回车键可以发布新闻
可以判断鼠标点击了哪个元素,从而做相应的操作
语法:
注册事件中,回调函数的第一个参数就是事件对象
一般命名为event、ev、e
e.target e.key
e.target得到的是触发事件的元素
环境对象 this
环境对象:指的是函数内部特殊的 this,它指向一个对象,并且受当前环境影响。作用:弄清楚this的指向,可以让我们代码更简洁
函数的调用方式不同,this 指代的对象也不同
【谁调用,this 就是谁】是判断 this 指向的粗略规则;直接调用函数,其实相当于是 window.函数,所以 this 指代 window
间歇函数 =>this指向window
事件 => this指向 事件源
排他思想
是一种思路,目的是突出显示某个元素
比如,有多个元素,当鼠标经过时,只有当前元素会添加高亮样式,其余的元素移除样式
口诀:注意顺序
- 排除其他人
- 保留我自己
事件流
事件流指的是事件完整执行过程中的流动路径
当触发事件时,会经历两个阶段,分别是捕获阶段、冒泡阶段
- 事件捕获概念:当一个元素的事件被触发时,会从DOM的根元素开始依次调用同名事件(从外到里)
元素对象.addEventListener('事件类型', 事件处理函数, 是否使用捕获机制)
- 事件冒泡概念:当一个元素的事件被触发时,同样的事件将会在该元素的所有祖先元素中依次被触发。这一过程被称为事件冒泡。即当一个元素触发事件后,会依次向上调用所有父级元素的 同名事件
- 事件冒泡是默认存在的,或者第三个参数传入false 都是冒泡。实际工作都是使用事件冒泡为主默认就是事件冒泡。
阻止冒泡
因为默认就有冒泡阶段的存在,所以容易导致事件影响到父级元素。
若想把事件就限制在当前元素内,就需要阻止事件冒泡。
阻止事件冒泡需要拿到事件对象(e)。
e.stopPropagation()
此方法可以阻断事件流动传播,不光在冒泡阶段有效,捕获阶段也有效。
鼠标经过和离开事件在冒泡的区别
mouseoyer 和 mouseout 会有冒泡
mouseenter 和 mouseleave 没有冒泡(常用)
事件委托
事件委托(Event Delegation):是Javascript中注册事件的常用技巧,也称为事件委派、事件代理
简单理解:原本需要注册在子元素的事件委托给父元素,让父元素担当事件监听的职务
为什么要用事件委托呢?
如果同时给多个元素注册事件,还需要利用循环多次注册事件
优点:减少注册次数,可以提高程序性能
原理:事件委托其实是利用事件冒泡的特点
- 给父元素注册事件,当我们触发子元素的时候,会冒泡到父元素身上,从而触发父元素的事件(事件子元素本身就是存在的)
- 给父元素注册,那利用事件委托方式如何得到当前点击的(子)元素呢:
父事件元素对象e.target.tagName可以获得真正触发事件的元素标签名。
ul.addEventListener('click', function(e){
if(e.target.tagName === 'LI') {
e.target.style.color = '#8df'
}
})
tab栏切换改造
需求:优化程序,将tab切换案例改为事件委托写法
思路:
- tab栏顶部高亮效果:
- 给a的父级注册鼠标经过事件,采取事件委托方式
- 注意mouseenter没有冒泡,所以此处使用mouseover
- 如果鼠标经过的是A,则进行排他思想,删除添加类
- 注意判断的方式 利用 e.target.tagName
- tab栏底部跟随显示效果:
- 因为没有索引号了,所以这里我们可以自定义属性data-id ,给5个链接添加序号
- 下面大盒子获取索引号的方式 e.target.dataset.id 号,然后进行排他思想
阻止默认行为
- 阻止元素发生默认的行为
- 例如:当点击提交按钮时阻止对表单的提交、阻止链接的跳转等等
事件对象e.preventDefault()
如果阻止了默认提交,我们就可以对数据进行验证了
移除事件监听
移除事件处理函数,也称为解绑事件。
L2级事件监听的解绑:
removeEventListener(事件类型, 事件处理函数,[捕获或者冒泡阶段])
注意:事件处理函数如果是匿名函数无法解绑。
L0级事件监听的解绑:
on事件方式,直接使用nul覆盖偶就可以实现事件的解绑
其他事件
页面加载事件1
加载外部资源(如图片、外联CSS和JavaScript等)加载完毕时触发的事件
为什么要学?
- 有些时候需要等页面资源全部处理完了做一些事情
- 老代码喜欢把 script 写在 head 中,这时候直接找dom 元素找不到
事件名:load
监听页面所有资源加载完毕: 给window 添加 load 事件
不光可以监听整个页面资源加载完毕,t可以针对某个资源绑定load事件
页面加载事件2
当初始的 HTML文档被完全加载和解析完成之后就触发,而无需等待样式表、图像等完全加载。
事件名:DOMContentLoaded
监听页面DOM加载完毕:给 document 添加 DOMContentLoaded 事件
只要HTML标签加载完成了,机会触发这个事件,他不会等待 Css Js 图片 视频音频等素材。
页面滚动事件
滚动条在滚动的时候持续触发的事件
为什么要学?
很多网页需要检测用户把页面滚动到某个区域后做一些处理,比如固定导航栏,比如返回顶部
事件名:scroll
监听整个页面滚动:window或者 document
案例
开发需求:
我们想要页面滚动一段距离,比如100px,就让某些元素显示隐藏,那我们怎么知道,页面滚动了100像素呢?
- 页面谁滚动?
HTML元素滚动
document.documentElement 返回HTML元素,拿到了整个HTML
- 如何知道滚动了多少距离?
scrollLeft和scrollTop(属性)
获取被卷去的左侧和头部
获取元素内容往左、往上滚出去看不到的距离
这两个值是可读写的

window.addEventListener('scroll', function(){
const n = document.documentElement.scrollTop
})
显示侧边栏案例:当页面滚动大于等于300像素的距离时候,就显示侧边栏,否则隐藏侧边栏
返回顶部案例
页面尺寸事件
会在窗口尺寸改变的时候触发事件:resize
获取元素宽高
获取宽高:
获取元素的可见部分宽高(不包含border,margin,滚动条等):clientWidth和clientHeight
元素尺寸与位置
获得元素的尺寸大小和页面中的位置
使用场景:
可以通过js的方式,得到元素在页面中的位置
可以通过js的方式,得到元素的实际大小
- 大小
offsetWidth 和 offsetHeight
获取元素的自身宽高、包含元素自身设置的宽高、padding、border
返回的是数字不带单位,并且是只读属性
- 位置
offsetLeft 和 offsetTop
获取元素距离自己定位父级元素的左、上距离,跟绝对定位类似;如果父级都没有定位则以浏览器文档为准
返回的是数字不带单位,并且是只读属性
案例:顶部吸附导航栏
时间对象
DOM树
父节点查找:parentNode
子元素节点:children(重点),获得所有子元素节点,返回的是一个伪数组
下一个兄弟:节点对象.nextElementSibling;该属性获取节点的下一个兄弟节点
上一个兄弟:节点对象.previousElementSibling;该属性获取节点的上一个兄弟节点
增加节点
很多情况下,我们需要在页面中增加元素。比如,点击发布按钮,可以新增一条信息。
一般情况下,我们新增节点,按照如下操作:
- 创建一个新的节点
- 把创建的新的节点放入到指定的元素内部
document.createElement('标签名')
父元素最后一个子节点之后,插入节点元素
elcnent.append()
父元素第一个子元素的之前,插入节点元素
element.prepend()
删除节点
element.remove()
把对象从它所属的 DOM 树中删除
JS插件
插件:就是别人写好的一些代码,我们只需要复制对应的代码,就可以直接实现对应的效果。
轮播图
了解这个插件可以完成什么需求 https://www.swiper.com.cn/
AlloyFinger
AlloyFinger 是腾讯 AlloyTeam 团队开源的超轻量级Web 手势插件,为元素注册各种手势事件
github地址:https://github.com/AlloyTeam/AlloyFinger
一些方法
数组.forEach(function(数组每一项, 数组每一项的索引){})
字符串.substring(number start, number end)左闭右开

浙公网安备 33010602011771号