一、变量声明
变量声明有三个:var、let、const
。var
是旧写法,问题多,被淘汰,现在不常用。
在let
和const
中,const
优先。
const
的语义化更好;- 很多变量在声明之后不会被更改;
- 许多框架中使用
const
居多。
在使用const
声明数组和对象时,在地址没有发生改变的情况下可以修改里面的属性,若修改了地址则会报错,在需要修改地址的情况,需使用let
声明。
const arrA = [1, 2, 3];
arrA.push(4); // 地址不变,值变为[1, 2, 3, 4]
console.log(arrA) // 输出:[1, 2, 3, 4]
const arrB = [1, 2, 3];
arrB = [1, 2, 3, 4]; // 报错,常量不能被重新赋值(重新赋值会导致地址改变)
二、Web API —— DOM 对象
Web API的作用:使用JS去操作HTML和浏览器
分类:DOM(文档对象类型)、BOM(浏览器对象类型)
- 什么是 DOM 和 DOM 数
DOM(Document Object Model —— 文档对象模型)是用来呈现以及与任意HTML或XML文档交互的API。也就是说是浏览器提供的一套专门用来操作网页内容的功能,开发网页内容特效和实现用户交互。
DOM 树:将HTML文档以树状结构直观地表现出来,我们称之为文档树或 DOM 树。是描述网页关系内容的名词。DOM 树直观地体现了标签与标签之间的关系。 - DOM 对象
DOM 对象:浏览器根据HTML标签生成的js对象。- 所有的标签属性都可以在这个对象上面找到;
- 修改这个对象的属性会自动映射到标签上
DOM 的核心思想:把网页当作对象来处理。
document对象:
- 是DOM里提供的一个对象(最大的一个对象);
- 它提供的属性和方法都是用来访问和操作网页内容的,如:
document.write()
; - 网页所有的内容都在document里。
- 获取 DOM 对象
1)根据CSS选择器来获取DOM元素(常用)- 选择一个
- 语法:
document.querySelector('css选择器')
。 - 参数:包含一个或多个有效的css选择器字符串。
- 返回值:css选择器匹配的第一个元素,一个HTMLElement对象,如果没有匹配到,则返回null,可以使用修改对象属性的方式修改获取到的HTMLElement对象。
- 语法:
- 选择多个
- 语法:
document.querySelectorAll('css选择器')
- 返回值:css选择器匹配的NodeList对象集合,是一个伪数组(有长度有索引号,但是没有pop()、push()等数组方法),操作时需要遍历或使用索引。
2)其他获取DOM元素方式(了解)
- 语法:
document.getElementById('id名')
:根据id获取一个元素document.getElementByTagName('标签名')
:根据标签获取一类元素document.getElementByClassName('类名')
:根据标签类名获取元素
- 选择一个
- 操作元素内容
DOM 对象都是根据标签生成的,所以操作标签本质就是操作 DOM 对象。console.dir(元素对象)
可以打印对象,包括所有属性和方法。对象.innerText
属性:对象.innerText = '新内容'
,将文本内容添加/更新到标签位置,显示纯文本,不解析标签。对象.innerHTML
属性
const box1 = document.querySelector('.box1'); console.log(box1.innerText); // 输出:文字内容, box1.innerText = '新文字内容'; // 页面显示文字:新文字内容 box1.innerText = '<strong>新文字内容</strong>'; // 无法解析标签,页面显示文字: <strong>新文字内容</strong> console.log(box1.innerText); // 输出:<strong>新文字内容</strong> const box2 = document.querySelector('.box2'); console.log(box2.innerHTML); // 输出:文字内容 box2.innerHTML = '<strong>新文字内容</strong>'; // 解析标签,页面显示加粗的文字:新 文字内容 console.log(box2.innerHTML); // 输出:<strong>新文字内容</strong>
- 操作元素属性
1)常用属性
对象.属性 = 值
,最常见的属性有:href、title、src
等
2)样式属性- 通过
style
属性:对象.style.属性 = 值
。// 通过style const box = document.querySelector('.box'); box.style.width = '300px'; box.style.border = '1px solid pink'; // 属性中使用了短横线'-'时,需使用小驼峰命名法 box.style.backgroundColor = 'lightblue'; // 修改的是css中的background-color
- 通过类名(
className
):元素.className = '类名'
,在<style></style>
标签中对类名写一个样式,然后给需要修改样式的元素添加这个类名。如果修改的样式多,可使用这种方式。<!-- 通过类名 className --> <style> .box { width: 300px; background-color: grey; } </style> <script> const div = document.querySelector('div'); // 给元素添加类名,这个值会直接替换掉元素原有的class值 div.className = 'box'; // 若希望保留原有类名或添加多个类名,要将所有值都写上,以空格隔开 div.className = 'oldClassName box other' </script>
- 通过
classList
:使用className
是覆盖原有的class值,而classList
可以对class的值进行追加和删除,对于需要使用多个类名的元素更加适用。- 添加:
元素.classList.add('类名')
,多个类名之间用逗号隔开; - 删除:
元素.classList.remove('类名')
,多个类名之间用逗号隔开; - 切换:
元素.classList.toggle('类名')
; - 检查:
元素.classList.contains('类名')
; - 替换:
元素.classList.replace('旧类名', '新类名')
。
<!-- 通过类名 classList --> <style> .box { width: 300px; background-color: grey; } </style> <script> const div = document.querySelector('div'); // 给元素添加类名:如果已存在就不添加,添加多个类名用逗号隔开 div.classList.add('box'); // 给元素删除类名:如果不存在也不会报错,删除多个类名用逗号隔开 div.classList.remove('other'); // 切换类名:有就删除,没有就添加 div.classList.toggle('other'); // 检查元素是否包含某个类名, 返回 true 或 false div.classList.contains("box"); // 替换类名, 如果存在就替换, 不存在就添加 div.classList.replace("oldClass", "newClass"); </script>
- 添加:
表单很多情况也需要修改属性,比如密码框的查看密码,本质是点击眼睛时,输入框类型(type)从密码(password)转为了文本框(text)。
表单属性中添加就有效果,移除就没有效果,一律使用布尔值表示,为true
代表添加该属性,为false
代表移除该属性。比如:disabled、checked、selected
。
获取:DOM对象.属性名
。
设置:DOM对象.属性名 = 新值
。
4)自定义属性<input type="text" value="姓名"> <button>点击按钮</button> <script> const uname = document.querySelector('input'); console.log(uname.value) // 输出:姓名 console.log(uname.innerHTML) // innerHTML无法取到表单元素的值,输出为空 // 修改输入框的值 uname.value = '张三'; console.log(uname.value); // // 修改输入框类型 uname.type = 'password'; // 输入框中的内容变成密码样式的小圆点 // 获取按钮 const btn = document.querySelector('button'); btn.disabled = true; // 禁用按钮 </script>
是html5中推出的,格式为data-自定义属性名
,在DOM对象上以dataset
方式获取,对象.dataset.自定义属性名
。使用对象.dataset
可获取到该对象上所有的自定义属性。const box = document.querySelector('.box'); console.log(box.dataset.id)
- 通过
- 定时器函数
定时器函数可以重复执行某段代码。
语法:setInterval(函数, 间隔时间)
,间隔时间是数字,单位是毫秒.
关闭定时器:定时器返回值是一个id数字,可以使用变量存放该值,然后使用// 每隔一秒执行一次 setInterval(function () { console.log('一秒执行一次'); }, 1000) // 具名函数在setInterval中不需要加小括号 function fn() { console.log('三秒执行一次'); } setInterval(fn, 3000);
clearInterval()
关闭定时器。
制作倒计时效果let 变量名 = setInterval(函数, 间隔时间); clearInterval(变量名)
<button class="btn" disabled>请先阅读协议(60)</button> <script> let i = 60; // 设置倒计时起始时间 const btn = document.querySelector('.btn'); // 获取按钮对象 let m = setInterval(function() { i--; btn.innerText = `请先阅读协议(${i})`; // 倒计时:一次减一秒 if (i === 0) { // 等于0时倒计时结束 clearInterval(m); // 关闭倒计时 btn.disabled = false; // 关闭按钮禁用 btn.innerText = '同意'; // 修改按钮文字 } }, 1000); </script>
三、Web API —— 事件监听
addEventListener()
语法:元素对象.addEventListener('事件类型', 要执行的函数)
。
事件监听三要素:- 事件源:被事件触发的 DOM 元素。
- 事件类型:什么方式触发的,如:鼠标单击
click
、鼠标经过mouseover
等。 - 事件调用的函数:要做什么事。
<button>点击弹出对话框</button> <script> const btn = document.querySelector('button'); // 获取事件源 btn.addEventListener('click', function() { // 事件类型:点击'click' alert('hello world'); // 弹出对话框 }) </script>
- 事件监听版本
- L0 —— 传统注册事件,在早期的事件监听中使用
on事件
的方式来实现:元素对象.on事件 = function() {}
。如:btn.onclick = function() {console.log(11)}
。这种方式会被覆盖,同一个对象,后面注册事件会覆盖前面注册的 (同一事件)。 - L2 —— 事件监听注册,使用
addEventListener
。同一个对象,后面注册事件不会覆盖前面注册的 (同一事件)
- L0 —— 传统注册事件,在早期的事件监听中使用
- 事件类型
- 鼠标事件:
click
(鼠标点击)、mouseover
(鼠标经过)、mouseleave
(鼠标离开)。 - 焦点事件(光标):
focus
(获得焦点)、blur
(失去焦点)。 - 键盘事件:
keydown
(键盘按下触发)、keyup
(键盘抬起触发)。 - 文本事件:
input
(用户输入事件)。
<div style="width: 100px; height: 100px; background-color: pink;"></div> <input type="text"> <script> const box = document.querySelector('div'); const input = document.querySelector('input'); // 鼠标事件,点击 box.addEventListener('click', function() { alert('hello world') }) // 鼠标事件,鼠标经过 box.addEventListener('mouseover', function() { box.style.backgroundColor = 'blue'; }) // 鼠标事件,鼠标离开 box.addEventListener('mouseleave', function() { box.style.backgroundColor = 'pink'; }) // 焦点事件,获得焦点 input.addEventListener('focus', function() { console.log('获得焦点'); }) // 焦点事件,失去焦点 input.addEventListener('blur', function() { console.log('失去焦点'); }) // 键盘事件,按下键盘 input.addEventListener('keydown', function() { console.log('按下键盘'); }) // 键盘事件,松开键盘 input.addEventListener('keyup', function() { console.log('松开键盘'); }) // 输入事件,输入内容 input.addEventListener('input', function() { console.log('输入内容'); }) </script>
- 鼠标事件:
- 事件对象
事件对象也是一个对象,里面存放了事件触发的相关信息。例如:鼠标点击事件中,事件对象存放了鼠标点的位置信息,键盘按下时可以知道按下的是哪一个键。
获取事件对象:在事件绑定的回调函数中的第一个参数就是事件对象,一般命名为event、ev、e
。
元素.addEventListener('事件名', function(事件对象) {})
。const input = document.querySelector('input'); input.addEventListener('keydown', function(e) { console.log(e); // 输出:KeyboardEvent对象,包含键盘事件的信息,如按下的键值,按下的键的位置等 // 若按下的是回车键 // 输出的内容是KeyboardEvent {isTrusted: true, key: 'Enter', code: 'Enter', location: 0, ctrlKey: false, …} })
常用属性 描述 type
当前事件类型,如 click
、keydown
clientX/clientY
光标相对于浏览器可见窗口左上角的位置 offsetX/offsetY
光标相对于当前DOM元素左上角的位置 key
用户按下的键盘的值 - 环境对象
环境对象指的是函数内部特殊的变量this
,它代表着当前函数运行时所处的环境。每个函数里都有this
。- 函数的调用方式不同,this指代的对象也不同。
- 在一般情况下,谁调用,this就指向谁。(判断this指向的粗略规则)
- 直接调用函数,就相当于
window.函数
,所以此时this指向window。
- 回调函数
当一个函数被当作参数传递给另一个函数时,这个作为参数的函数就是回调函数。
四、Web API —— 事件流
事件流指的是事件完整执行过程中的流动路径。会经历捕获和冒泡两个阶段。捕获是从父到子,冒泡是从子到父。
- 事件捕获
从DOM的根元素开始去执行对应的事件(从外到里)。
事件捕获需要写对应代码才能看到效果。
DOM.addEventListener(事件类型, 事件处理函数, 是否使用事件捕获机制)
addEventListener
的三个参数传入true
代表是捕获阶段触发(很少使用);- 若传入的是
false
,则代表冒泡阶段触发(默认值); - 若是用L0事件(传统注册事件)监听,则只要冒泡阶段,没有捕获。
- 事件冒泡
当一个元素的事件被触发时,同样的事件将会在该元素的所有祖先元素中依次被触发,这一过程被称为事件冒泡。
简单理解:当一个元素触发事件后,会依次向上调用所有父级元素的同名事件。
事件冒泡是默认存在的。 - 阻止冒泡
事件对象.stopPropagation()
可阻断事件传播,对冒泡和捕获都有效果。input.addEventListener('click', function(e) { alert('1111'); e.stopPropagation(); // 阻止冒泡 })
- 解绑事件
- 传统注册事件(
on事件
):同名事件会被覆盖,所以使用null
就可以解绑事件,如btn.onclick = null
。 addEventListener
方式必须使用removeEventListener(事件类型, 事件处理函数, 获取捕获或冒泡阶段)
。- 匿名函数无法解绑
- 传统注册事件(
- 阻止默认行为
有些元素有默认的行为,但在某些情况下需要阻止默认行为,比如链接的跳转、表单提交等。
使用e.preventDefault()
阻止默认行为。 - 两种鼠标事件
鼠标经过和鼠标离开事件都有两种,他们之间的区别是:mouseover
和mouseout
会有冒泡效果,mouseenter
和mouseleave
没有冒泡效果(推荐使用)。 - 事件委托
事件委托是利用事件流的特征解决一些开发需求的知识技巧。在需要给多个元素注册同一个事件时,可以使用事件委托,减少注册次数,提高程序性能。
原理:利用事件冒泡。给父元素注册事件,当触发子元素时,会冒泡到父元素上,从而触发父元素事件。
实现:利用事件对象,使用事件对象.target.tagName
可以获得真正触发事件的元素。<ul> <p>段落</p> <li>一</li> <li>二</li> <li>三</li> <li>四</li> <li>五</li> </ul> <script> // 点击当前 li 文字变红色 // 若给每个 li 都添加事件,会造成内存浪费 // 使用事件委托,只给 ul 添加事件,点击 li 时,事件冒泡到 ul 上,触发事件 // 通过事件对象的 target 属性,获取当前点击的元素,e.target.tagName 获取当前点击元素的标签名 const ul = document.querySelector('ul'); ul.addEventListener('click', function(e){ console.log(e); if(e.target.tagName === 'LI'){ e.target.style.color = 'red'; } }) </script>
五、Web API —— 页面加载和滚动事件
- 页面加载事件
load
:当外部资源(如图片、外联CSS和JS等)加载完毕时触发的事件。多用于监听页面所有资源加载完毕。DOMContentLoaded
:当初始的HTML文档被完全加载和解析完成之后,DOMContentLoaded
事件被触发,无需等待样式表、图像等完全加载。
// 等待页面所有资源加载完成:给 window 添加 load 事件 window.addEventListener('load', function(){ alert('加载完成') }) // 监听页面 DOM 加载完毕:给 document 添加 DOMContentLoaded 事件 document.addEventListener('DOMContentLoaded', function(){ alert('11') })
- 页面滚动事件
滚动条在滚动的时候持续触发的事件scroll
。
获取滚动的位置:scrollTop
:滚动后上方被卷去的长度(即元素向下滚动的长度);scrollLeft
:滚动后左边被卷去的长度(即元素向右滚动的长度);- 上面两个值都是可读写的。
// 设置一开始整个页面的滚动距离为 100px document.documentElement.scrollTop = 100; // 监听整个页面的滚动:给 window / document 添加 scroll 事件 window.addEventListener('scroll', function(){ // 获取整个页面的滚动距离 const n = document.documentElement.scrollTop; console.log(n); // 得到的值是一个数字,不带单位,表示滚动距离是多少px })
- 页面尺寸事件
浏览器窗口大小发生变化的时候触发的事件resize
。- 获取元素的可见部分宽高(不包含边框,margin,滚动条等):
clientWidth
和clientHeight
。 - 获取可见元素的自身宽高,包含元素自身设置的宽高、padding、border:
offsetWidth
和offsetHeight
。 - 获取元素距离自己定位父级元素的左、上距离:
offsetLeft
和offsetTop
(只读属性)。
const div = document.querySelector('.div'); console.log(div.clientWidth); // 打印元素的宽度 window.addEventListener('resize', () => { console.log('页面变化了'); console.log(div.clientWidth); // 打印元素的宽度 });
- 获取元素的可见部分宽高(不包含边框,margin,滚动条等):
六、Web API —— 日期对象
-
日期对象
Date()
- 用
new
关键字可以实例化一个时间对象。 - 日期对象返回的数据不能直接使用,需要转换为实际开发中常用的格式。对实例化后的日期对象使用以下方法可从中得到对应的值。
方法 作用 说明 getFullYear()
获得年份 获取年份的四位数 getMonth()
获得月份 取值范围:0 ~ 11,0 表示 1 月 getDate()
获得月份中的某一天(年月日中的日) 不同月份取值不相同 getHours()
获得小数 取值范围:0 ~ 23 getMinutes()
获得分钟 取值范围:0 ~ 59 getSeconds()
获得秒 取值范围:0 ~ 59 getDay()
获得星期 取值范围:0 ~ 6,0 表示星期天 还可以使用
toLocaleString()、toLocaleDateString()、toLocaleTimeString()
对日期进行格式化。// 得到当前时间 const date = new Date(); // 得到时间格式为:Wed Jan 01 2024 08:00:00 GMT+0800 (中国标准时间) // 得到指定时间,有几种参数形式 // 得到指定时间,参数为字符串 // 字符串格式可以是标准时间格式,也可以是其他格式,但是要保证能被Date.parse解析,否则会返回Invalid Date // 例如:'2024-01-01'、'2024/01/01'、'2024-01-01 01:01:01'、'2024/01/01 01:01:01'、'2024-01-01T01:01:01'、'2024/01/01T01:01:01' const date1 = new Date('2024-01-01 01:01:01'); // 得到指定时间,参数为年月日时分秒,月份从0开始计算 const date2 = new Date(2024, 1, 1, 1, 1, 1); // 得到指定时间,参数为时间戳,单位为毫秒,从1970年1月1日开始计算 const date3 = new Date(1000); year = date.getFullYear(); month = date.getMonth() + 1; // 0-11,0代表1月 day = date.getDate(); hour = date.getHours(); minute = date.getMinutes(); second = date.getSeconds(); week = date.getDay(); // 0-6,0代表星期天 console.log(date); // Wed Apr 10 2024 15:27:58 GMT+0800 (中国标准时间) console.log(year, month, day, hour, minute, second, week); // 2024 4 10 15 27 58 3 // 格式化时间 // 使用toLocaleString方法 console.log(date.toLocaleString()); // 2024/4/10 15:27:58 // 使用toLocaleDateString方法 console.log(date.toLocaleDateString()); // 2024/4/10 // 使用toLocaleTimeString方法 console.log(date.toLocaleTimeString()); // 15:27:58
- 用
-
时间戳
时间戳是指1970年01月01日00时00分00秒至现在的毫秒数,是一种特殊的计量时间的方式。- 将来的时间戳 - 现在的时间戳 = 剩余时间毫秒数;
- 剩余时间毫秒数转换为剩余时间的年月日时分秒就是倒计时时间。
获取时间戳三种方法: getTime()
:需要先实例化,const date = new Date(); console.log(date.getTime())
;- 使用
+
运算符:可直接使用+new Date()
,括号中写参数可得到指定时间戳,不写参数是当前时间戳;也可实例化之后再使用+
,如const date = new Date(); console.log(+date)
Date.now()
:只能得到当前时间戳。
七、Web API —— DOM 节点
- DOM 节点
DOM 树中每一个内容都称之为节点
节点类型:- 元素节点:所有标签,如
body、div
,其中html
是根节点; - 属性节点:比如
href
; - 文本节点:所有的文本;
- 其他
- 元素节点:所有标签,如
- 查找节点
- 父节点:
元素.parentNode
,返回最近一级的父节点,找不到返回null
。 - 子节点:
元素.children
,获得元素所有的子节点中的元素节点(伪数组)。 - 兄弟节点:
元素.nextElementSibling
(下一个兄弟元素)、元素.previousElementSibling
(上一个兄弟元素)。
- 父节点:
- 新增节点
- 创建一个节点:
document.createElement('标签名')
- 追加节点(将节点放入某个元素中):
父元素.appendChild(子元素)
或父元素.insertBefore(要插入的元素, 在哪个元素前插入)
// 创建新节点 const li = document.createElement('li'); // 追加节点 const ul = document.querySelector('ul'); ul.appendChild(li); // 在ul中子元素的最后追加了一个li ul.insertBefore(li, ul.children[0]) // 在ul的第一个子元素前插入li
- 创建一个节点:
- 克隆节点
语法:被克隆元素.cloneNode(是否克隆标签里的内容)
:如:li.cloneNode(true)
,true
表示将li里面的内容一起克隆,如果是false
则表示只克隆一个标签。 - 删除节点
在JavaScript中,删除元素必须通过父元素删除。
语法:父元素.removeChild(要删除的元素)
。若不存在父子关系则删除不成功。
八、移动端事件
移动端有一些常用事件,如触屏事件touch
(触摸事件)。
touchstart
:手指触摸到一个 DOM 元素时触发;touchmove
:手指在一个 DOM 元素上滑动时触发;touchend
:手指从一个 DOM 元素上移开时触发。
九、swiper 插件
Swiper 是一款免费以及轻量级的移动设备触控滑块的js框架。
官网链接:https://www.swiper.com.cn/