本文目前介绍JS中的API的知识点,操作案例后续补充。
目录
1. web API基本认知
2. API 作用和分类
2.1 DOM
2.1.1 DOM树
2.1.2 DOM对象
2.1.2.1 操作DOM对象
① 选中这个标签后才能操作
1. 选择匹配的第一个元素
2. 选择多个元素
3. 获取1个可直接修改
4. 遍历获取
② 操作元素内容
1. 对象.innerText
2. 对象.innerHTML
3. 练习-随机抽奖
③ 操作元素属性
1. 常用属性修改
2. 样式属性修改
3. 表单属性修改
4. 自定义属性修改
2.1.2.2 计时器-间歇函数
① 开启定时器
② 关闭定时器
③ 小练习
④ 用户阅读协议倒计时
⑤ 轮播图定时(后更)
2.1.2.3 事件监听
① 事件监听介绍
② 事件监听三要素
③ 举例
④ 删除广告案例
⑤ 综合案例
⑥ const的使用
2.1.2.4 事件类型
① 鼠标事件
1. 鼠标经过与离开
2. 轮播图练习(后更)
② 焦点事件
1. 获得与失去
2. 练习
③ 键盘事件
④ 文本事件
练习
2.1.2.5 事件对象
① 获取事件对象
② 事件对象属性
③ 发布评论练习(后更)
2.1.2.6 环境对象
2.1.2.7 回调函数
2.1.2.8 Tab栏切换(后更)
2.1.2.9 全选文本框(后更)
2.1.2.10 事件流
① 捕获
② 冒泡
③ 阻止冒泡
④ 解绑事件
⑤ 补充
2.1.2.11 事件委托
① 原理
② tab切换栏改进(后更)
③ 补充-阻止默认行为
2.1.2.12 其他事件
① 页面加载事件
② 元素滚动事件
1. 获取应用
2. 页面导航案例(后更)
③ 页面尺寸事件
2.1.2.13 元素尺寸与位置
① 尺寸
1. 获取宽高
2. 获取位置
3. 仿京东滑动(后更)
4. bilibili导航滑动(后更)
2.1.2.14 电梯导航(后更)
2.1.2.15 日期对象
① 实例化
② 日期对象方法
③ 时间戳
1. 什么是时间戳
2. 使用
3. 算法
4. 获取时间戳
5. 返回指定时间戳
④ 倒计时案例(后更)
2.1.2.16 节点操作
① DOM节点
② 节点操作 - 查
父节点
前面关闭广告的示例
关闭广告升级
子节点
兄弟节点
③ 节点操作 - 增
特殊:克隆节点
④ 节点操作 - 删
2.1.2.17 M端事件
2.1.2.18 swiper插件的使用
2.1.2.19 学生信息表(后更)
2.2 BOM
2.2.1 window对象
2.2.1.1 BOM
2.2.1.2 定时器 - 延时函数
5秒后自动消失的图片
2.2.1.3 JS执行机制
2.2.1.4 location 对象
5秒后自动跳转页面
search 属性
hash 属性
reload 方法
userAgnet
2.2.1.6 history 对象
2.2.2 本地存储
2.2.2.1 分类
① localStorage
存储数据
取数据
删除数据
改 / 增 数据
② sessionStorage
2.2.2.2 处理复杂数据类型
2.2.2.3 读取本地存储管理(后更)
2.2.3 字符串拼接(新方法)
2.2.3.1 map方法
2.2.3.2 join方法
2.2.3.3 案例改进(后更)
2.2.4 正则表达式
2.2.4.1 语法
2.2.4.2 元字符
① 分类
边界符
量词
字符类
② 输入用户名案例(后更)
2.2.4.3 修饰符
过滤敏感字
1. web API基本认知
变量的声明:let var const
建议 const 常量 优先:
const 语义化更好,声明之和我们知道它不会被改了。
一般我们先给他用const 发现要修改的时候可以改为 let
但是需要注意:
基本数据类型中,被修改的量用 let 而不能用 const。
而在复杂数据类型中(数组、对象)是可以用 const 的(前提是没有开辟新的空间)
原因:
复杂数据类型用堆存储,它的地址不变,const 表示他的地址,所以无论数组和对象里的值怎么变(比如添加和删除)都不会造成地址的变化。所以在他被修改的时候(而不是开辟新的地址)可以用const。
就比如 一个人是不变的 但是他身上穿的衣服是可变的,但这个人本质仍然还是他自己没有变化。
例如:
let person = {age : 18,gender : '男',
}
person.gender : '女';
console.log(person);// 以上是可以将let修改为const的
const names = [];
names = [1,2,3]; // 不允许改const 地址被改了
// 但是可以追加const obj = {};
obj = {uname : 'zzz';
}
// 不允许,地址被修改了
建议数组和对象用const声明。
2. API 作用和分类
作用:使用JS去操作HTML和浏览器
分类:DOM 文档对象模型、BOM浏览器对象模型
前面学过的alert就属于DOM。
2.1 DOM
DOM是浏览器提供的一套专门操作网页内容的功能
作用:开发网页特效和实现用户交互。
2.1.1 DOM树
将HTML文档以树状结构直观的表示出来,称为文档树或DOM树。
直观体现标签与标签的关系。
2.1.2 DOM对象
标签是以对象形式表现出来的。
DOM对象:浏览器根据html标签生成的JS对象
— 所有的标签属性可以在这个对象上找到
— 修改对象的属性会自动映射到标签上
举例:
<script>const div = document.querySelector('div');// 打印对象console.dir(div); // 获取到div后成为dom对象</script>
核心思想:
把网页内容当成对象来处理。
最大的对象是document对象,其次是html对象
document对象:
它提供的属性和方法都是用来访问和操作页面的。
如:document.write()
2.1.2.1 操作DOM对象
通过CSS选择器获取DOM元素
① 选中这个标签后才能操作
1. 选择匹配的第一个元素
语法:
document.querySelector('CSS选择器');
<script>// 1. 获取匹配的第一个元素const box = document.querySelector('.box'); // 可以用标签div或者类名.box或者id名#XXXconsole.dir(box); // dir可以显示具体信息// 选择的是第一个 123const nav = document.querySelector('#nav');console.dir(nav);// 想要获取ul里的第一个liconst li = document.querySelector('ul li:first-child');console.dir(li);</script>
如图只获取到了第一个元素测试1
2. 选择多个元素
语法:
document.querySelectorAll('CSS选择器');
如获取ul里的所有li
const lis = document.querySelectorAll('ul li');console.dir(lis);
获取到一个数组的形式
得到的是一个伪数组:
有长度有索引号但没有数组的方法
想要得到里面的每一个对象需要for遍历来得到
3. 获取1个可直接修改
但是获取多个时不能直接修改,需要遍历数组进行修改。
4. 遍历获取
<body><ul class="nav"><li>11</li><li>22</li><li>33</li></ul><script>// 1.获取元素const lis = document.querySelectorAll('.nav li');// console.dir(lis);// 2.遍历修改for(let i=0; i<lis.length; i++){console.log(lis[i]); // 打印出每一个li对象}</script>
</body>
② 操作元素内容
修改元素的文本并且更换内容,本质上是操作DOM对象
比如倒计时修改秒数
操作对象使用的点语法
1. 对象.innerText
<body><div class="box">我是文字内容</div><script>// 1.先获取对象const box = document.querySelector('.box');// 2.修改文字内容// 对象.innerTextconsole.log(box.innerText); // 获取文字内容box.innerText = '<strong>我是盒子</strong>'; // inerText只显示纯文本,不显示标签</script>
</body>
2. 对象.innerHTML
对应的这个就可以识别标签
<body><div class="box1">我是文字内容1</div><div class="box2">我是文字内容2</div><script>// 1.先获取对象const box1 = document.querySelector('.box1');const box2 = document.querySelector('.box2');// 2.修改文字内容// 对象.innerTextconsole.log(box1.innerText); // 获取文字内容box1.innerText = '<strong>我是盒子</strong>'; // inerText只显示纯文本,不显示标签// 对象.innerHTMLbox2.innerHTML = '<strong>我是盒子</strong>';</script>
</body>
我们一般用HTML的
3. 练习-随机抽奖
从数组随机抽奖一等奖二等奖和三等奖
分析:
① 声明数组,抽奖的范围
② 一等奖:随机生成某范围内的整数,并找到对应数组的名字
③ 二等奖:将一等奖的名字删去继续抽
④ 三等奖:继续删名字然后抽
⑤ 将对应的名字显示在对应的位置
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head>
<body><div class="wrapper"><strong>抽奖名单</strong><h2>一等奖:<span id="one">???</span></h2><h2>二等奖:<span id="two">???</span></h2><h2>三等奖:<span id="three">???</span></h2></div><script>// 1.声明数组const personArr = ['A','B','C','D','E','F','G'];// 2.先做一等奖const random1 = Math.floor(Math.random()*personArr.length);console.log(personArr[random1]);// 2.1 获取one元素并将其显示上去const one = document.querySelector('#one');one.innerHTML = personArr[random1];// 2.2 删除一等奖的名字personArr.splice(random1,1);console.log(personArr); // 目前的数组内没有一等奖的人// 变化后的数组继续操作// 3.做二等奖const random2 = Math.floor(Math.random()*personArr.length);console.log(personArr[random1]);// 2.1 获取two元素并将其显示上去const two = document.querySelector('#two');two.innerHTML = personArr[random2];// 2.2 删除一等奖的名字personArr.splice(random2,1);console.log(personArr); // 目前的数组内没有一等奖二等奖的人// 4.最后做三等奖const random3 = Math.floor(Math.random()*personArr.length);console.log(personArr[random3]);// 2.1 获取one元素并将其显示上去const three = document.querySelector('#three');three.innerHTML = personArr[random3];// 2.2 删除一等奖的名字personArr.splice(random3,1);console.log(personArr); // 目前的数组内没有一等奖的人</script>
</body>
</html>
③ 操作元素属性
比如大小,颜色,位置还有一些自定义的属性。
1. 常用属性修改
比如 href title src等等
语法:
对象.属性 = 值
举例:
首先建立一个文件夹并放一些图片
<body><!-- 默认为第一张图片 --><img src="./images/1.webp" alt=""><script>// 1.想要修改先要获取元素对象const img = document.querySelector('img');// 2.修改为2.jpgimg.src = './images/9.webp';img.title = '纯色图';</script>
</body>
练习:
页面刷新时随机显示不同的图片
分析:
① 随机显示 则要random
② 更换图片需要用到的src属性并修改
<body><img src="./images/1.webp" alt=""><script>// 取到 1-10的随机整数function getRandom(N,M){return Math.floor(Math.random()*(M-N+1))+N;}// 1.获取图片对象const img = document.querySelector('img');// 2.得到随机数const random = getRandom(1,10);// 3.更换路径img.src = `./images/${random}.webp`;</script>
</body>
每次刷新都能更新图片
2. 样式属性修改
比如通过轮播图小圆点自动更换颜色样式
点击按钮可以滚动图片
① style操作CSS
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><style>.box{width: 200px;height: 200px;background-color: pink;}</style>
</head>
<body><div class="box"></div><script>// 1.先获取元素const box = document.querySelector('.box');// 2.修改样式 对象.style.样式属性 = '值'box.style.width = '300px'; // 是字符串且必须写单位box.style.backgroundColor = 'red'; // 出现短横线用小驼峰命名法// 边框改为蓝色实线box.style.border = '2px solid blue';// 上边框改为绿色box.style.borderTop = '2px solid green';</script>
</body>
</html>
练习:
随机更新背景图片
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><style>body{background: url(./images/1.webp) no-repeat top center/cover; }</style>
</head>
<body><script>// console.log(document.body) 可以直接用// 获取随机数function getRandom(N,M){return Math.floor(Math.random()*(M-N+1))+N;}const random = getRandom(1,10);// 只需要更换背景图片Image即可document.body.style.backgroundImage = `url(./images/${random}.webp)`</script>
</body>
</html>
③ className修改
需要修改的属性过多,需要多行代码过于冗杂,可以使用CSS类名修改
元素.className = 'active';
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><style>div{width: 200px;height: 200px;background-color: skyblue;}/* 给div添加类名后可以直接用 */.box{/* 各种CSS属性 */}</style>
</head>
<body><div></div><!-- 或者这里可以写<div class="nav"></div> 后面就相当于赋新值 box--><script>// 获取div元素const div = document.querySelector('div');// 给div添加类名box,style可以直接用div.className = 'box';</script>
</body>
</html>
③ classList修改(重要)
通过此方式追加和删除类名
// 追加一个类
元素.classList.add('类名')// 删除一个类
元素.classList.remove('类名')// 切换一个类
元素.classList.toggle('类名')
举例:
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><style>.box{width: 200px;height: 200px;color: #333;}.active{color: red;background-color: pink;}</style>
</head>
<body><div class="box">文字</div><script>// 1.获取元素const box = document.querySelector('.box');// 给box添加类(属性)不用加点// box.classList.add('active');// 给box删除类// box.classList.remove('box');// 给box切换类 div里有就删掉 没有就加上box.classList.toggle('active'); </script>
</body>
</html>
④ 轮播图案例
(CSS更新后会编辑此案例)
3. 表单属性修改
表单中的很多内容也需要修改:
比如点击输入密码旁边的眼睛可以看到密码,其本质是将表单类型转换为文本框。
正常有属性有取值和其他标签属性没有区别
获取:DOM对象.属性名
设置:DOM对象.属性名 = 新值
表单.value = '用户名'
表单.type = 'password'
举例:
<body><input type="text" value="电脑"><script>// 获取表单元素const uname = document.querySelector('input');// 获取表单里的属性值console.log(uname.value); // innerHTML得不到表单内容// 设置表单的值uname.type = 'password'; // 将文本框设置为密码框</script>
</body>
操作表单元素属性
表单属性中添加就有效果,移除就没有效果,一律使用布尔值。
true代表添加了该属性,false代表移除了该属性
主要:disabled checked selected
<body><!-- <input type="text" value="电脑"> --><input type="checkbox" name="" id=""> <!-- 里面如果有checked默认true --><button disabled>点击</button><!-- disabled = 'disabled可以省略后面,disabled是指不能点击--><script>// // 获取表单元素// const uname = document.querySelector('input');// // 获取表单里的属性值// console.log(uname.value); // innerHTML得不到表单内容// // 设置表单的值// uname.type = 'password'; // 将文本框设置为密码框// JS形式复选框勾选全选const ipt = document.querySelector('input');// console.log(ipt.checked) // input里有checked会默认true// checked只接受布尔值ipt.checked = true;// ipt.checked = 'true'; // 虽然可以但是不提倡// 1.获取按钮const button = document.querySelector('button');console.log(button.disabled) // 默认false 不禁用// disabled在这里是禁用吗?的意思且默认false不禁用button.disabled = true; // 改为true要禁用</script>
</body>
4. 自定义属性修改
标准属性:
标签自带的属性 比如class id等,可以直接使用点语法操作比如 disabled checked selected。
自定义属性:
H5中推出的专门的 data-自定义属性
标签上以 data- 开头
DOM对象上一律以dataset对象方式获取
举例:
<body><div data-id="hh" data-mm="ppp">1</div><div>2</div><div>3</div><div>4</div><div>5</div><script>const one = document.querySelector('div'); // 获取的第一个console.log(one.dataset); // 获取到了所有自定义的属性console.log(one.dataset.id); // 获取自定义的idconsole.log(one.dataset.mm); </script>
</body>
2.1.2.2 计时器-间歇函数
每隔一段时间需要自动执行一段代码,不需要我们手动取触发
例如:阅读用户协议中的倒计时
有两种我们现在先介绍间歇函数
可以开启和关闭定时器
① 开启定时器
setInterval(函数,间隔时间)
作用:
每隔一段时间就调用这个函数,时间单位是毫秒ms
举例:
<body><script>// 匿名函数setInerval(函数,间隔时间)// 匿名函数时setInterval(function(){console.log('一秒执行一次');}, 1000)function fn(){console.log('两秒执行一次');}// 具名函数setInerval(函数名,间隔时间)// 此处不能是fn(),这相当于调用fn函数,需要返回值,无法继续2000ms下一轮// 但 'fn()' 是可以的setInterval(fn,2000);</script>
</body>
② 关闭定时器
如轮播图中我们将鼠标放在相应图片上时就不会继续换图了。
而且需要注意的是:一个页面上可能存在多个定时器,时间间隔不同,所以我们每一个定时器都是独一无二的,我们将每一个计时器最后返回给一个变量。
let n = setInterval(fn,1000)
关闭的方法
let 变量 = setInterval(函数,间隔时间)
clearInterval(变量名);
③ 小练习
200ms间隔生成数字
<script>let i = 1;setInterval(function(){document.write(i);i++;},200)</script>
④ 用户阅读协议倒计时
需求:按钮5秒后才可以使用
分析:
① 开始先将按钮禁止 disabled
② 获取元素
③ 函数内处理逻辑
— 秒数开始减减
— 按钮里的文字也要变化
— 秒数为0停止计时器
— 同时文字变为同意 最后点击
<body><textarea name="" id="" cols="30" rows="10">用户注册协议:欢迎注册,协议内容:XXXXXXXXXX.</textarea><br><button class="btn" disabled>我已阅读用户协议(5)</button><script>// 1.获取元素const btn = document.querySelector('.btn');// console.log(btn.innerHTML); // button显示的内容是中间的文字,innerHTML获取的是这个,而非类似input的value// 2.倒计时let i = 6;// 2.1开启计时器let n = setInterval(function(){i--; // i--必须在前面btn.innerHTML = `我已阅读用户协议(${i})`;if(i === 0){clearInterval(n); // 关闭btn.disabled = false; // 要禁用吗?不禁用btn.innerHTML = '同意';}},1000) </script>
</body>
⑤ 轮播图定时(后更)
(同上方轮播图同时更新)
2.1.2.3 事件监听
主要给DOM元素添加事件监听。
事件:在编程时系统内发生的动作或者发生的事情。
例如:用户在网页上单击一个按钮
① 事件监听介绍
让程序检测是否有事件发生。一旦有事件发生,就立即调用一个函数做出响应,也称为绑定事件或者注册事件,例如检测到鼠标经过就要显示下拉菜单。
语法
元素对象.addEventListener('事件类型', 要执行的函数);
② 事件监听三要素
1. 事件源:哪个dom元素被触发了,需要获取这个dom元素
2. 事件类型:用何种方式触发的,如鼠标单击click、鼠标经过mouseover
3. 事件调用的函数:触发后要做什么事情
③ 举例
<body><button>点击</button><script>// 需求:点击按钮后弹出对话框// 1.事件源:button按钮// 获取按钮const btn = document.querySelector('button');// 2.事件类型:点击按钮// 给事件添加监听器btn.addEventListener('click',function(){alert('hi');})// 3.事件处理:弹出对话框</script>
</body>
④ 删除广告案例
页面上有一个广告,右上角有个❌,点击后消失,再次刷新后广告重新出现。
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><style>.box{position: relative;width: 1000px;height: 200px;background-color: pink;margin: 100px;text-align: center;font-size: 50px;line-height: 200px;font-weight: 700;}.box1{position: absolute;right: 20px;top: 10px;width: 20px;height: 20px;background-color: #fff;text-align: center;line-height: 20px;font-size: 16px;}</style>
</head>
<body><div class="box">我是广告<div class="box1">X</div></div><script>// 1.获取事件源const box1 = document.querySelector('.box1');const box = document.querySelector('.box');// 2.添加事件监听box1.addEventListener('click',function(){// 关闭广告其实就是隐藏display 刷新后还能出现// 利用style修改属性值box.style.display = 'none';})</script>
</body>
</html>
⑤ 综合案例
现在要实现一个随机点名的页面
主要业务:
1. 点击开始按钮
随机抽取数组的一个数据放到页面中
2. 点击结束按钮
删除数组当前抽取的一个数据
3. 抽取到最后一个数据
两个按钮同时禁用
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head>
<body><h2>随机点名</h2><div class="box"><span>名字:</span><div class="ming">此处显示名字</div></div><br><div class="btns"><button class="start">开始</button><button class="end">结束</button></div><script>// 初始名字数组const arr = ['A','B','C','D','E','F','G','H','I'];// 定时器的全局变量let i1 = 0;// 随机号也是全局变量let random = 0;// 获取两个按钮元素const start = document.querySelector('.start');const end = document.querySelector('.end');const ming = document.querySelector('.ming');// 给这两个元素添加事件监听器start.addEventListener('click',function(){// 设置定时器自动刷新// 去掉定时器号的let 成为全局变量i1 = setInterval(function(){// 页面开始随机出现名字// 先获取名字数组的下标号 随机randomrandom = Math.floor(Math.random()*arr.length);ming.innerHTML = arr[random];},100);// 如果数组里只剩下一个值就不需要抽了,将两个按钮禁用if(arr.length === 1){start.disabled = true;end.disabled = true;}})end.addEventListener('click', function () {clearInterval(i1);// 将抽到的名字从数组中删除arr.splice(random, 1);console.log(arr);})</script>
</body>
</html>
⑥ const的使用
如下代码中用到了垃圾回收机制
<body><button>点击</button><script>// 获取按钮元素const btn = document.querySelector('button');btn.addEventListener('click',function(){const num = Math.random(); // [0,1)随机一个数给num常量console.log(num);// 这里可以运行是因为垃圾回收机制,这次点击事件结束后会自动清理})</script>
</body>
而下面的代码则不可
const num = Math.random(); // [0,1)随机一个数给num常量
num = 10; // 这里报错是因为对其进行了修改
console.log(num);
2.1.2.4 事件类型
① 鼠标事件
1. 鼠标经过与离开
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><style>div{width: 200px;height: 200px;background-color: pink;}</style>
</head>
<body><div></div><script>const div = document.querySelector('div');// 鼠标经过事件div.addEventListener('mouseenter',function(){console.log('111');})// 鼠标离开事件div.addEventListener('mouseleave',function(){console.log('222');})</script>
</body>
</html>
2. 轮播图练习(后更)
② 焦点事件
1. 获得与失去
<body><input type="text"><script>// 获得文本输入框const input = document.querySelector('input');// 得到焦点事件input.addEventListener('focus',function(){console.log('焦点触发');})// 失去焦点事件input.addEventListener('blur',function(){console.log('失去焦点触发');})</script>
</body>
2. 练习
小米下拉框,点击时显示,点击其他地方则消失
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><style>* {margin: 0;padding: 0;box-sizing: border-box;}ul {list-style: none;}.mi {position: relative;width: 223px;margin: 100px auto;}.mi input {width: 223px;height: 48px;padding: 0 10px;font-size: 14px;line-height: 48px;border: 1px solid #e0e0e0;outline: none;}.mi .search {border: 1px solid #ff6700;}.result-list {display: none;position: absolute;left: 0;top: 48px;width: 223px;border: 1px solid #ff6700;border-top: 0;background: #fff;}.result-list a {display: block;padding: 6px 15px;font-size: 12px;color: #424242;text-decoration: none;}.result-list a:hover {background-color: #eee;}</style>
</head>
<body><div class="mi"><input type="search" placeholder="小米笔记本"><ul class="result-list"><li><a href="#">全部商品</a></li><li><a href="#">小米11</a></li><li><a href="#">小米105</a></li><li><a href="#">小米笔记本</a></li><li><a href="#">空调</a></li><li><a href="#">黑鲨4</a></li><li><a href="#">小米手机</a></li></ul></div><script>// 获取inputconst input = document.querySelector('[type=search]');// 属性选择器// 获取ulconst ul = document.querySelector('.result-list');// console.log(input);// 焦点监听input.addEventListener('focus',function(){ul.style.display = 'block';// 点击时添加边框颜色的类input.classList.add('search');})// 失去焦点input.addEventListener('blur',function(){ul.style.display = 'none';// 失去时释放属性input.classList.remove('search');})</script>
</body>
</html>
③ 键盘事件
<body><input type="text"><script>// 获取输入框const input = document.querySelector('input');// 键盘监听input.addEventListener('keydown',function(){console.log('键盘按下');})input.addEventListener('keyup',function(){console.log('键盘弹起');})// 同时出现</script>
</body>
④ 文本事件
<body><input type="text"><script>const input = document.querySelector('input');// 用户输入文本事件input.addEventListener('input',function(){console.log(input.value);// 无论什么内容输入都有控制台输出111})</script>
</body>
练习
评论字数统计
用户输入文字,可以计算用户输入的字数
分析:
1. 判断用输入事件input
2. 不断取得文本框里的字符长度 利用:文本域.value.length
3. 把获得的数字给下面的文本框
本练习涉及H5和CSS内容后续补充
2.1.2.5 事件对象
① 获取事件对象
也是object,所以一定有属性和方法
它存储的是事件触发时的相关信息
比如:
鼠标点击事件中,事件对象就存了鼠标点击在哪个位置等信息。
键盘事件中,判断用户按下了哪个键。
获取语法:
在事件中绑定的回调函数的第一个参数就是事件对象,一般命名为event、ev、e
举例:
元素.addEventListener('click',function(e) {})
② 事件对象属性
能够使用常见事件对象属性
一些常用属性:
1. type
获取当前的事件类型
2. clientX / clientY
获取光标相对于浏览器可见窗口左上角的位置
3. offsetX / offsetY
获取光标相对于当前DOM元素左上角的位置
4. key
用户按下的键盘键的值
如图:
③ 发布评论练习(后更)
后续更
2.1.2.6 环境对象
指的是函数内部特殊的变量 this,代表当前函数运行时所处的环境
弄清除this的指向可以让代码更简洁
函数的调用方式不同,this 指代的对象也不同
一般:谁调用,this 就是谁
举例:
<body><button>点击</button><script>// 每个函数里都有this 环境对象function fn(){console.log(this); // 输出当前函数所处的环境// 普通函数中 直接调用的话,this指向的是window}fn();const btn = document.querySelector('button');btn.addEventListener('click',function(){// function是一个函数console.log(this); // btn对象// 这里指向的是本函数的调用者,谁调用了就指向谁// 还可以用this修改属性,因为它指向了调用者this.style.color = 'red' // 等效 btn.style.color})</script>
</body>
2.1.2.7 回调函数
将函数A作为参数传递给函数B时,称A为回调函数
比如:
<script>function fn(){console.log('我是回调函数');}// 将fn传递给了定时器,fn是回调函数setInterval(fn,1000); // 每过一秒回去调用一次函数</script>
还有一个:
<body><div class="box"></div><script>// 另一种回调函数const box = document.querySelector('.box');box.addEventListener('click',function(){// 每当点击一次box就回去调用一次函数console.log('我也是回调函数');})</script>
</body>
2.1.2.8 Tab栏切换(后更)
后更
2.1.2.9 全选文本框(后更)
后更
2.1.2.10 事件流
事件流指的是事件完整执行过程中的流动路径
分为两个阶段
① 捕获
从大到小 父到子
比如要去南京的红山动物园,那我们的路线是 江苏省 — 南京市 —— 红山动物园
又比如:Document - html - body - div
从大到小的范围取捕获
应用:
DOM.addEventListener(事件类型,事件处理函数,是否使用捕获机制)第三个参数一般传入 true
默认是false 即为冒泡阶段
举例:
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><style>.father{width: 200px;height: 200px;background-color: pink;}.son{width: 100px;height: 100px;background-color: green;}</style>
</head>
<body><div class="father"><div class="son"></div></div><script>const fa = document.querySelector('.father');const son = document.querySelector('.son');// 捕获document.addEventListener('click',function(){alert('我是爷爷');},true)fa.addEventListener('click',function(){alert('我是爸爸');},true)son.addEventListener('click',function(){alert('我是儿子');},true)</script>
</body>
</html>
点击绿块 会依次从document - father - son 显示处理
② 冒泡
从小到大 子到父
要求能够说出事件冒泡的执行流程
注意:
1. 冒泡是一定会发生的
2. 调用的父级元素的同名事件 比如都是 click 事件
就是上面的反例
DOM.addEventListener(事件类型,事件处理函数,是否使用捕获机制)第三个参数默认是false 即为冒泡阶段
将上述的例子中的true全部删掉
然后刷新页面再次点击绿色块
则依次显示 son - father - document 的信息
是从小到大的查
③ 阻止冒泡
因为默认是有冒泡的存在,所以容易导致事件影响到父级元素
所以我们要把事件限制在本元素内,阻止事件冒泡
要想阻止冒泡,首先需要拿到事件对象。
阻止语法:
事件对象.stopPropagation()
注意:
此方法可以阻断事件流动传播,不光在冒泡阶段有效,捕获阶段也有效(即阻止捕获)
举例:
son.addEventListener('click',function(e){alert('我是儿子');// 阻止流动传播e.stopPropagation(); // 只能显示儿子的信息})
④ 解绑事件
<body><button>点击</button><script>const btn = document.querySelector('button');// // 传统的事件绑定// btn.onclick = function(){// alert('点击了');// }// // 传统事件解绑// btn.onclick = null;// L2的方式// 注意 匿名函数无法被解绑,所以:// 需要将监听事件中的原来的匿名函数独立处理成为具名函数function fn(){alert('点击');}// 注意只写函数名即可,回调函数只写函数名btn.addEventListener('click',fn);btn.removeEventListener('click',fn);</script>
</body>
⑤ 补充
mouseover 和 mouseout
与
mouseenter 和 mouseleave
的区别在于前者有冒泡影响效果,后者没有
我们推荐使用后者
2.1.2.11 事件委托
比如送快递,原先是需要快递小哥亲自送到手里,但是很耽误事件效率也很低,所以快递小哥将所有快递送到驿站(将快递委托给驿站)所有人直接取驿站取即可,这就是事件委托。
开发应用中,如果我们需要给多个元素注册同一个事件,一般我们是利用for循环挨个执行,需要注册多个事件,现在我们利用事件委托,指需注册一次事件就达到效果。
① 原理
事件委托其实利用的是事件冒泡的特点
给父级元素注册事件,触发子级元素时,会冒泡到父级元素上,从而触发父级元素的事件
举例:
<body><ul><li>第1个孩子</li><li>第2个孩子</li><li>第3个孩子</li><li>第4个孩子</li><li>第5个孩子</li><p>我不要变色</p></ul><script>// 点击每个li 当前li变为红色// 按照事件委托的方式// 1.获得父元素const ul = document.querySelector('ul');ul.addEventListener('click',function(e){// alert('111');// 点击li 但li没有点击事件,会冒泡到ul上// 2.现在让字的颜色变红// this.style.color = 'red'; // 所有li都变红了,因为this指向的环境时ul// 所以我们需要用到事件对象e// e.target 代表点击的对象,在这个点击事件中 点到谁 谁就是targetconsole.log(e.target);// e.target.style.color = 'red';// 但是现在又有p标签 不能变色,只能li变色// 所以对标签 tagName 有要求// 注意是大写LIif(e.target.tagName === 'LI'){e.target.style.color = 'red';}})</script>
</body>
② tab切换栏改进(后更)
后更
③ 补充-阻止默认行为
比如阻止链接的跳转,表单的跳转等等
e.preventDefault();
举例:
<body><form action="http://baidu.com"><input type="submit" value="注册"></form><a href="http://baidu.com"></a><script>// 先获取表单const form = document.querySelector('form');form.addEventListener('submit',function(e){// 事件对象e.preventDefault();})// 获取链接const a = document.querySelector('a');a.addEventListener('click',function(e){// 阻止e.preventDefault();})</script>
</body>
2.1.2.12 其他事件
① 页面加载事件
加载外部资源(如图片、外联CSS和JS等)加载完毕时触发的事件
为什么有这个?
— 有时候我们需要等页面资源全部处理完了做一些事情
— 老代码喜欢把script写在head里,这时候直接找dom元素找不到
事件名:load
监听页面所有资源加载完毕:
给 window 添加 load 事件
// 页面加载事件
window.addEventListener('load',function(){// 执行的操作
})
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><script>// 等待页面所有资源加载完毕就回去执行回调函数window.addEventListener('load',function(){// 执行的操作const btn = document.querySelector('button');btn.addEventListener('click',function(){alert(111);})})</script>
</head>
<body><button>点击</button>
</body>
</html>
还有一种是DOMContentLoaded事件被触发,无需等待样式表图像等完全加载
事件名:DOMContentLoaded
监听页面DOM加载完毕:
给 document 添加 DOMContentLoaded 事件
document.addEventListener('DOMContentLoaded',function(){})
document.addEventListener('DOMContentLoaded',function(){const btn = document.querySelector('button'); btn.addEventListener('click',function(){alert(111);}) })
② 元素滚动事件
滚动条滚动时持续触发的事件
比如很多页面需要检测用户把页面滚动到某区域做一些处理,比如固定导航栏 返回顶部等等。
事件名:scroll
监听整个页面window滚动:
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><style>body{height: 3000px;}</style>
</head>
<body><script>window.addEventListener('scroll',function(){console.log('页面滚动中'); // 只要页面滚动1像素就触发})</script>
</body>
</html>
给window / document / 某个元素 / 某个标签 添加 scroll
页面滚动的应用:
1. 获取应用
先认识两个新的属性
scrollLeft 和 scrollTop
— 获取被卷去的大小
— 获取元素内容往左、往上滚出去看不到的距离
— 这两个值是可读写的
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><style>body{padding-top: 100px;height: 3000px;}div{margin: 100px;overflow: scroll;width: 200px;height: 200px;border: 1px solid black;}</style>
</head>
<body><div>我这里面有很多很多文字我这里面有很多很多文字我这里面有很多很多文字我这里面有很多很多文字我这里面有很多很多文字我这里面有很多很多文字我这里面有很多很多文字我这里面有很多很多文字我这里面有很多很多文字我这里面有很多很多文字我这里面有很多很多文字我这里面有很多很多文字我这里面有很多很多文字我这里面有很多很多文字</div><script>// window.addEventListener('scroll',function(){// console.log('页面滚动中'); // 只要页面滚动1像素就触发// })// 给div监听滚动事件const div = document.querySelector('div');div.addEventListener('scroll',function(){// console.log(111);console.log(div.scrollTop);})</script>
</body>
</html>
代表页面上面溢出(被卷去)部分的长度是多少
在开发中我们用的更多的是页面的滚动
现在先隐藏div元素,要求整个页面滚动超过100像素时div显示出来,小于100像素时消失
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><style>body{padding-top: 100px;height: 3000px;}div{display: none;margin: 100px;overflow: scroll;width: 200px;height: 200px;border: 1px solid black;}</style>
</head>
<body><div>我这里面有很多很多文字我这里面有很多很多文字我这里面有很多很多文字我这里面有很多很多文字我这里面有很多很多文字我这里面有很多很多文字我这里面有很多很多文字我这里面有很多很多文字我这里面有很多很多文字我这里面有很多很多文字我这里面有很多很多文字我这里面有很多很多文字我这里面有很多很多文字我这里面有很多很多文字</div><script>// 先要获取到div元素const div = document.querySelector('div');window.addEventListener('scroll',function(){// console.log('页面滚动中'); // 只要页面滚动1像素就触发// 想知道页面滚动了多少像素 被卷去了多少// 获取html元素: document.documentElement// 这句话必须写在监听里 因为它是一直取到的新值const n = document.documentElement.scrollTop;if(n >= 100){div.style.display = 'block';}else{div.style.display = 'none';}})</script>
</body>
</html>
同时他们是可读写的,就是可以给它赋值的
比如一打开页面就是固定在某个位置
// 可读写document.documentElement.scrollTop = 300; // 页面一打开就停留在300像素位置// 同时也可以用它来设置“返回顶部” 即在点击按钮时设置top等于0即可window.addEventListener('scroll',function(){// console.log('页面滚动中'); // 只要页面滚动1像素就触发// 想知道页面滚动了多少像素 被卷去了多少// 获取html元素: document.documentElement // 这句话必须写在监听里 因为它是一直取到的新值const n = document.documentElement.scrollTop;if(n >= 500){div.style.display = 'block';}else{div.style.display = 'none';}})
2. 页面导航案例(后更)
后更
③ 页面尺寸事件
在窗口尺寸改变的时候触发事件
window.addEventListener('resize',function(){// 执行的代码
})
举例:
<script>// resize 是浏览器窗口大小发生变化的时候触发的事件window.addEventListener('resize',function(){console.log(1);})</script>
检测屏幕宽度:
window.addEventListener('resize',function(){let w = document.documentElement.clientWidth;console.log(w);
})
获取元素宽高
— 获取元素的可见部分宽高(不包含边框、margin、滚动条等)
— clientWidth 和 clientHeight
— 下图中黑色部分不可获取
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><style>div{display: inline-block;/* width: 200px; */height: 200px;background-color: pink;padding: 10px; /* 包含padding 不包含border */border: 20px solid red;}</style>
</head>
<body><div>11111111111111111111111111111111</div><script>// 获取divconst div = document.querySelector('div');console.log(div.clientWidth); // 320console.log(div.clientHeight); // 220// resize 是浏览器窗口大小发生变化的时候触发的事件window.addEventListener('resize',function(){console.log(1);})</script>
</body>
</html>
2.1.2.13 元素尺寸与位置
① 尺寸
1. 获取宽高
— 获取元素的自身宽高、包含元素自身设置的宽高、padding、border
— offsetWidth 和 offsetHeight
— 获取出来的是数值方便计算
— 获取的是可视宽高、若盒子是隐藏的则获取的结果是0
2. 获取位置
— 获取元素距离自己定位父级元素的左、上距离
方法1:
— offsetLeft 和 offsetTop 是只读属性
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><style>div{width: 200px;height: 200px;background-color: pink;margin: 100px;}p{width: 100px;height: 100px;background-color: purple;margin: 50px;}</style>
</head>
<body><div><p></p></div><script>const div = document.querySelector('div');const p = document.querySelector('p');// console.log(div.offsetLeft);// 检测盒子位置 最近一级带有定位的祖先元素console.log(p.offsetLeft); // 到父亲margin50px + 父亲到外面margin100px + bodymargin 8px// 如果div 加上相对定位就是50px</script>
</body>
</html>
方法2:
返回元素的大小及其相对于视口(会变化)的位置
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><style>body{height: 2000px;}div{width: 200px;height: 200px;background-color: pink;margin: 100px;}</style>
</head>
<body><div></div><script>const div =document.querySelector('div');console.log(div.getBoundingClientRect());</script>
</body>
</html>
视口变化前:
视口变化后(下滑):
3. 仿京东滑动(后更)
4. bilibili导航滑动(后更)
2.1.2.14 电梯导航(后更)
后更
2.1.2.15 日期对象
能够在网页上显示日期,得到当前系统时间
① 实例化
在代码中发现了new关键字一般将此操作称为实例化
创建一个时间对象并获取时间
获得当前时间:
const date = new Date();
<script>// 实例化 newconst date = new Date();console.log(date);</script>
获得指定时间:
一般用于倒计时
// 2.获得指定时间const date1 = new Date('2020-5-1 08:30:11');console.log(date1);
② 日期对象方法
日期对象返回的数据我们不能直接使用,需要转换为实际开发中常用的格式
<script>// 1.获得日期对象 实例化newconst date = new Date();console.log(date.getFullYear()); // 四位年份 2025console.log(date.getMonth() + 1); // 获得月份 月份是0-11 所以需要+1console.log(date.getDay()); // 获得星期console.log(date.getHours() + 1); // </script>
注意月份+1 才能得到真正的月份
显示星期:
// 根据日期Day() 0-6 返回星期几const arr = ['星期天','星期一','星期二','星期三','星期四','星期五','星期六'];console.log(arr[new Date().getDay()]); // arr[5] 星期五
现在要求页面自动显示时间
格式:YYYY-MM-DD HH:mm
例如 2008-08-08 08:08
一位数字时需要补0
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><style>div{width: 500px;height: 40px;border: 1px solid pink;text-align: center;line-height: 40px;}</style>
</head>
<body><div></div><script>const div = document.querySelector('div');function getMyDate(){const date = new Date();let h = date.getHours();let m = date.getMinutes();let s = date.getSeconds();h = h < 10 ? '0'+h : h;m = m < 10 ? '0'+m : m;s = s < 10 ? '0'+s : s;return `今天是:${date.getFullYear()}年${date.getMonth()+1}月${date.getDate()}日 ${h}:${m}:${s}`}// 刚打开页面就能看到而不是空的div.innerHTML = getMyDate();// 让时间在页面自己动起来// 开计时器setInterval(function(){div.innerHTML = getMyDate();},1000); // 一秒后回去执行一次函数</script>
</body>
</html>
另一种简便方法:
<body><div></div><script>const div = document.querySelector('div');const date = new Date();div.innerHTML = date.toLocaleString(); // 2025/2/28 17:30:01div.innerHTML = date.toLocaleDateString(); // 2025/2/28div.innerHTML = date.toLocaleTimeString(); // 17:30:01// 要想将其自动实现setInterval(function(){const date = new Date(); // 先要获取最新时间div.innerHTML = date.toLocaleString();},1000)</script>
</body>
③ 时间戳
我们要能够获得当前的时间戳。
1. 什么是时间戳
它是1970年1月1日00时00分00秒起始至现在的毫秒数,它是一种特殊的计量时间的方式
2. 使用
如果计算倒计时效果,前面的方法无法计算,需要借助时间戳完成
3. 算法
将来的时间戳 - 现在的时间戳 = 剩余的时间毫秒数
剩余的毫秒数 转换为剩余时间的 年月日时分秒
即为倒计时时间
4. 获取时间戳
三种方法:
<script>// 1.getTime()// 需要实例化const date = new Date();console.log(date.getTime());// 2.+newDate() 字符串转换为数字型// 无需实例化console.log(+new Date());// 3.Date.now()// 无需实例化// 但只能得到当前时间戳,前面两种可以返回指定的时间戳console.log(Date.now());</script>
5. 返回指定时间戳
// 以方法2为例返回指定时间戳 需要用单引号console.log(+new Date('2025-2-28 17:30:01'));
④ 倒计时案例(后更)
2.1.2.16 节点操作
① DOM节点
DOM树里的每一个内容都称为节点
节点类型:
元素节点:所有的标签,html是根节点 (增删改查)
属性节点:所有的属性,比如href、div里的id class等等
文本节点:所有的文本
② 节点操作 - 查
主要在于节点关系
节点关系:针对的找亲戚返回的都是对象
父节点
子元素.parentNode
前面关闭广告的示例
这里只显示改动部分
<body><div class="box">我是广告<div class="box1">X</div></div><script>// 1.获取事件源 这里我们只获取box1盒子即可,后面利用父节点操作const box1 = document.querySelector('.box1');// 2.添加事件监听box1.addEventListener('click',function(){// 关闭广告其实就是隐藏display 刷新后还能出现// 利用style修改属性值// 使用box1的父节点删去// this指的是box1的环境this.parentNode.style.display = 'none'; // 或者box1.parentNode})</script>
</body>
关闭广告升级
有多个广告需要关闭
比如有三个广告
<body><div class="box">我是广告<div class="box1">X</div></div><div class="box">我是广告<div class="box1">X</div></div><div class="box">我是广告<div class="box1">X</div></div><script>// 获取所有属性是box1的div const btns = document.querySelectorAll('.box1'); // 伪数组// 使用循环给数组的每一个按钮进行监听和操作for(let i = 0; i < btns.length; i++){// 对每一个btn进行父节点操作btns[i].addEventListener('click',function(){// this指代当前的环境this.parentNode.style.display = 'none';})}</script>
</body>
子节点
childNodes:获得所有子节点、包括文本节点(空格、换行)、注释节点等
children属性(重点):
— 仅获得所有元素节点
— 返回的是伪数组
<body><ul><li><p>第一个段落</p></li><li>1</li><li>2</li><li>3</li><li>4</li></ul><script>const ul = document.querySelector('ul'); // 获得ulconsole.log(ul.children); // 获得它的所有孩子的伪数组,且包括这些孩子的所有内容</script>
</body>
兄弟节点
<body><ul><li><p>第一个段落</p></li><li>1</li><li>2</li><li>3</li><li>4</li></ul><script>// 先获得第二个子节点const li2 = document.querySelector('ul li:nth-child(2)'); // 上一个兄弟节点console.log(li2.previousElementSibling);// 下一个兄弟节点console.log(li2.nextElementSibling);</script>
</body>
③ 节点操作 - 增
在页面中新增元素
比如点击发布按钮,可以新增一条信息
流程:
1、创建一个新节点
2、把创建的新的节点放入到指定的元素内部
但是可能会出现:
<script>// 1.创建节点const div = document.createElement('div');console.log(div);// 2.追加节点// 放到父元素的最后一个子元素// 父元素是bodydocument.body.appendChild(div); // 打开页面发现它是插入到了script里</script>
要把它放在页面上
<body><ul><li></li></ul><script>// // 1.创建节点// const div = document.createElement('div');// console.log(div);// // 2.追加节点// // 放到父元素的最后一个子元素// // 父元素是body// document.body.appendChild(div); // 打开页面发现它是插入到了script里// 1.获取ul并创建liconst ul = document.querySelector('ul');const li = document.createElement('li');li.innerHTML = '我是li';// 2.追加节点并放到 最后一个子元素ul.appendChild(li); // 打开页面发现标签</script>
</body>
默认是插入到最后一个子元素,若是插到某个子元素之前呢
<body><ul><li>我是第一个li</li></ul><script>// 1.获取ul并创建liconst ul = document.querySelector('ul');const li = document.createElement('li');li.innerHTML = '我是li';// 2.追加节点并放到 第一个子元素// ul.children[0] 第一个元素// insertBefore(插入的元素,放到哪个元素的前面);ul.insertBefore(li,ul.children[0]); </script>
</body>
特殊:克隆节点
复制一个已有的元素节点
把复制的节点放入到指定的元素内部
元素.cloneNode(布尔值)
布尔值:
true 代表克隆时会包含后代节点一起克隆
false 代表克隆时不会包含后代
默认为 false
举例:
<body><ul><li>1</li><li>2</li><li>3</li></ul><script>// 1.克隆节点// 先获取ulconst ul = document.querySelector('ul');// 开始克隆 元素.cloneNode(布尔值) 并存入li1const li1 = ul.children[0].cloneNode(true);// 2.追加到ul的最后ul.appendChild(li1);</script>
</body>
④ 节点操作 - 删
DOM操作中,删除元素必须要经过父元素删除
父元素.removeChild(要删的元素)
注:
不存在父子关系则删除不成功
删除与隐藏(display:none)有区别:隐藏还存在,删除是不存在了
<body><ul><li>没用了</li></ul><script>// 先获取父元素ulconst ul = document.querySelector('ul');// 删除节点 父元素.removeChild(子元素)ul.removeChild(ul.children[0]); // 删除第一个子元素</script>
</body>
2.1.2.17 M端事件
移动端
比如触屏事件 touch,Android和IOS都有
touch 对象代表一个触摸点。触摸点可能是一根手指也可能是一根触摸笔
常见触屏事件:
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><style>div{width: 300px;height: 300px;background-color: pink;}</style>
</head>
<body><div></div><script>// 1.触摸// 先获取const div = document.querySelector('div');// 开始监听div.addEventListener('touchstart',function(){console.log('开始摸了');})div.addEventListener('touchmove',function(){console.log('一直摸');})div.addEventListener('touchend',function(){console.log('离开');})</script>
</body>
</html>
2.1.2.18 swiper插件的使用
插件就是别人写好的一些代码,只需要复制对应的代码就可以直接使用
后续补充详细操作
2.1.2.19 学生信息表(后更)
后更
2.2 BOM
2.2.1 window对象
2.2.1.1 BOM
BOM是浏览器对象模型,它包含DOM
window对象是一个全局对象,也可以说是JS中的顶级对象,document alert() console.log() 这些都是window中的属性,基本BOM的属性和方法都是window的。
所有通过 var 定义在全局作用域中的变量和函数,都会变成window对象的属性和方法。
window对象下的属性和方法调用的时候可以省略window.
2.2.1.2 定时器 - 延时函数
和前面介绍的间歇函数不同,间歇函数是间隔X秒后再次执行,而延时函数是延迟X秒后执行,且不再执行,只执行一次。
JS中内置的:
setTimeout(回调函数, 等待的毫秒数)
<script>setTimeout(function(){console.log('时间到'); // 两秒后显示},2000);</script>
清除延时函数
某些特殊情况下需要清除,后面会说明
let timer = setTimeout(回调函数, 等待的时间毫秒数); // 返回数字型id
clearTimeout(timer);
5秒后自动消失的图片
分析:
1、设置延时函数
2、隐藏元素
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><style>img{position: fixed; left: 0;bottom: 0;}</style>
</head>
<body><img src = "./7.webp" ><script>// 先获取图片const img = document.querySelector('img');// 延时函数隐藏setTimeout(function(){img.style.display = 'none';},3000)</script>
</body>
</html>
2.2.1.3 JS执行机制
上述的结果都是
1111 3333 2222
为什么?
JS语言的最大特点是单线程,就是说一个时间只能做一件事。
如果遇到耗时的操作会造成页面阻塞,为了解决这个问题利用多核CPU的计算,H5提出web worker标准,允许JS脚本创建多个线程,于是出现了同步和异步。
同步:
前一个任务结束了才进行下一个任务。
同步任务都在主线程上执行,形成一个执行栈。
异步:
在做某件耗时操作时可以处理其他事情,通过回调函数实现
异步任务分为三种:
1、普通事件,如click resize
2、资源加载,如load error
3、定时器,setInterval setTimeout
异步任务相关添加到任务队列中。
本质区别是:执行顺序不同。
执行机制:
1、先执行执行栈中的同步任务
2、异步任务放入任务队列中
3、执行栈中执行完就按次序读取任务队列的异步任务,被读取到的异步任务结束等待并进入执行栈开始执行任务,这个异步任务结束后检查执行栈还有没有需要执行的,如果没有,回到任务队列读取下一个异步任务重复上述操作,称之为事件循环。
异步队列中的顺序:
1:onload onclick等
2:setTimeout等
3:网络请求AJAX
事件循环 event loop 是重点。
2.2.1.4 location 对象
属于window,可以省略window
它拆分并保存了URL地址的各个组成部分
常用属性和方法:
href 属性获取完整的URL地址,对其赋值时用于地址的跳转。
<script>// console.log(Location)// 1.href经常利用js的方法去自动跳转页面location.href = 'http://www.baidu.com'</script>
5秒后自动跳转页面
用户可以点击可以跳转,如果不点击,则5秒后自动跳转,要求里面有秒数倒计时
分析:
1、目标元素是网页链接
2、利用setInterval定时器(秒数改变)设置数字倒计时
3、时间到了自动跳转
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><style>span{color: red;}</style>
</head>
<body><!-- 在标签设置链接是点击时也可以跳转 --><!-- 5秒是打开页面初始的 --><a href="http://www.baidu.com">将会在<span>5</span>秒跳转页面</a><script>// 1。获取a元素const a = document.querySelector('a');// 2.设置定时器// 3.声明倒计时变量let num = 5;let timeId = setInterval(function(){num--;a.innerHTML = `将会在<span>${num}</span>秒跳转页面`;if(num === 0){// 4.停止定时器clearInterval(timeId);// 5.跳转页面location.href = 'http://www.baidu.com';}},1000)</script>
</body>
</html>
search 属性
获取地址中携带的参数 ?后面的部分
举例写一个表单
<body><form action=""><input type="text" name = "username"><input type="password" name = "pwd"><button>提交</button></form>
</body>
点击提交后:
hash 属性
获取地址中的哈希值,符号#后的部分
vue路由部分会涉及
比如点击页面的某个功能按钮,点击后只有页面一部分发生的改变,其他的不变,可以说是hash的改变导致的
<body><form action=""><input type="text" name = "username"><input type="password" name = "pwd"><button>提交</button></form><a href="#/my">我的</a><a href="#/friend">关注</a>
</body>
reload 方法
刷新当前页面,输入参数true时表示强制刷新
也可以不输入true
<body><form action=""><input type="text" name = "username"><input type="password" name = "pwd"><button>提交</button></form><a href="#/my">我的</a><a href="#/friend">关注</a><button class="reload">刷新</button><script>// 获取刷新按钮const reload = document.querySelector('.reload');// 点击事件reload.addEventListener('click',function(){location.reload(true); // 强制刷新})</script>
</body>
2.2.1.5 navigator 对象
它也是一个对象,该对象记录了浏览器自身的相关信息
常用属性和方法:
userAgnet
检测浏览器的版本和平台
以下代码可以直接复制进script中
//检测 userAgent(浏览器信息)!(function () {const userAgent = navigator.userAgent// 验证是否为Android或iPhoneconst android = userAgent.match(/(Android);?[\s\/]+([\d.]+)?/) const iphone = userAgent.match(/(iPhone\sOS)\s([\d_]+)/)// 如果是Android或iPhone,则跳转至移动站点 if (android || iphone) {location.href = 'http://m.itcast.cn'}})()
完整代码:
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><script>//检测 userAgent(浏览器信息)!(function () {const userAgent = navigator.userAgent// 验证是否为Android或iPhoneconst android = userAgent.match(/(Android);?[\s\/]+([\d.]+)?/) const iphone = userAgent.match(/(iPhone\sOS)\s([\d_]+)/)// 如果是Android或iPhone,则跳转至移动站点 if (android || iphone) {location.href = 'http://m.itcast.cn'}})()</script>
</head>
<body>这是PC端
</body>
</html>
点击Elements旁边的按钮并选择IPhone版本后,点击页面刷新按钮就会出现:
2.2.1.6 history 对象
它时对象,主要管理历史记录,该对象与浏览器地址栏的操作相对应,比如前进、后退、历史记录等等。
<body><button>后退</button><button>前进</button><script>const back = document.querySelector('button:first-child');const forward = back.nextElementSibling; // back的下一个兄弟back.addEventListener('click',function(){// 后退history.back();// 或者 go(-1)})forward.addEventListener('click',function(){// 前进history.forward();// 或者go(1)})</script>
</body>
2.2.2 本地存储
浏览器为了满足各种各样的需求,会经常在本地存储大量的数据,有些页面存入数据后一刷新就没了(因为是存在了内存里),所以我们需要能够一直保存在浏览器的功能,达到一个浏览器的仓库的作用,就出现了本地存储。
本地存储中:
1、数据存储在用户浏览器中
2、设置、读取方便、页面刷新不会丢失
3、容量较大,sessionStorage 和 localStorage 约为5M左右
2.2.2.1 分类
① localStorage
作用:可以将数据永久的存储在本地,除非手动删除,关闭页面也存在
特性:
1、大部分可以在同一个浏览器的不同的窗口使用(除非涉及到跨域)
2、以键值对的形式存储使用
语法:
存储数据
<script>// 要存储一个名字 uname zzz// localStorage.setItem('键','值')localStorage.setItem('uname','zzz');</script>
打开同域名的新页面检查也出现同样的
取数据
// 取数据// localStorage.getItem('键')console.log(localStorage.getItem('uname'));
删除数据
// 删除数据,只删除名字localStorage.removeItem('uname');
如果要都删除可以点击右上角的按钮
改 / 增 数据
有这个键的就是改数据,没有这个键的就是增加这个键的数据
// 改/增数据localStorage.setItem('uname','bbb'); // 改localStorage.setItem('age',18); // 增console.log(localStorage.getItem('age')); // 得到的是字符串// 本地存储只能存储字符串
注意:
本地存储只能存储字符串,需要转换类型的化要注意
② sessionStorage
生命周期:关闭浏览器窗口就消失
同一个窗口(页面)下可以数据共享
键值对形成存储
用法与localStorage基本相同
2.2.2.2 处理复杂数据类型
本地存储一次只能存一个信息而且还是字符串,我们现在想要存储更复杂的数据类型,比如对象。
<script>const obj = {uname : 'zzz',age : 18,gender : '男'}// 存储复杂数据类型 对象localStorage.setItem('obj',obj); // 前面是键 后面是值(内容)console.log(localStorage.getItem('obj')); // [object Object] 没有内容 不能直接使用</script>
存的还是字符串类型
解决:
① 需要将复杂数据类型转换成JSON字符串,再存储到本地
语法:
JSON.stringify(复杂数据类型)
<script>const obj = {uname : 'zzz',age : 18,gender : '男'}// 存储复杂类型要用 JSONlocalStorage.setItem('obj',JSON.stringify(obj));// 取console.log(localStorage.getItem('obj'));// {"uname":"zzz","age":18,"gender":"男"}// JSON对象的属性和值都用双引号</script>
我们最后取出来的是字符串,但是我们要的是对象
② 把JSON字符串转换为对象
完整代码,最后获取的是对象
<script>const obj = {uname : 'zzz',age : 18,gender : '男'}// 1.存储复杂类型要用 JSONlocalStorage.setItem('obj',JSON.stringify(obj));// 取console.log(localStorage.getItem('obj'));// {"uname":"zzz","age":18,"gender":"男"}// JSON对象的属性和值都用双引号 都是字符串// 2.将JSON字符串转换为 对象// JSON.parse()console.log(JSON.parse(localStorage.getItem('obj')));</script>
2.2.2.3 读取本地存储管理(后更)
学生就业统计表
2.2.3 字符串拼接(新方法)
map方法和join方法 实现字符串拼接
2.2.3.1 map方法
map可以遍历处理数据,写一个回调函数,最后返回新的数组
map也称为映射,指两个元素的集(原数组与新数组)互相对应的关系
map的重点在于有返回值,后面介绍的forEach则没有
<script>const arr = ['red','blue','green'];const newArr = arr.map(function(ele,index){// 返回给一个新的数组console.log(ele); // 数组元素console.log(index); // 数组索引号return ele + '颜色';})console.log(newArr);</script>
2.2.3.2 join方法
join() 用于将数组中的所有元素都转换为一个字符串
<script>const arr = ['red','blue','green'];console.log(arr.join('')); // redbluegreen 且是字符串// join() 的括号内是一个空字符则是代表所有元素以空字符作为分隔console.log(arr.join()); // red,blue,green// 小括号为空则元素之间用逗号分隔console.log(arr.join('|')); // red|blue|green// 用竖杠分隔</script>
2.2.3.3 案例改进(后更)
后更 学生就业信息管理
2.2.4 正则表达式
正则表达式是用于匹配字符串中字符组合的模式。
在JS中,正则表达式也是对象。
通常用来查找、替换那些符合正则表达式的文本,许多语言都支持正则表达式。
应用:验证手机号,匹配中文昵称、过滤 / 替换敏感词、从字符串中获取特定部分等等。
很多语言都有正则表达式。
2.2.4.1 语法
举例:
我们要在一群人中找到戴眼镜的人
1. 定义规则:戴眼镜的
2. 根据规则取查找:找到就返回
定义规则的语法:
const 变量名 = /表达式/// 是正则表达式的字面量
判断是否有符合规则的字符串
用test()方法来查看正则表达式与指定的字符串是否匹配
regObj.test(被检测的字符串)
举例:
<script>const str = '我们在学习前端,希望学习前端能高薪毕业';// 1.定义规则 /表达式/const reg1 = /前端/;const reg2 = /java/;// 2.是否匹配 // 规则.test(被检测的字符串)console.log(reg1.test(str)); // trueconsole.log(reg2.test(str)); // false</script>
除此之外还有一种方法也是检索符合规则的字符串
exec()
regObj.exec(被检测字符串)
如果匹配成功,将会返回一个数组,否则返回的是null
console.log(reg1.exec(str));
index 是规则出现的索引号
2.2.4.2 元字符
普通字符:
大多数字符只能够描述他们自身,这些字符称作普通字符,例如字母和数字,只能够匹配字符串中和他们相同的字符。
元字符:
是一些具有特殊含义的字符,极强的灵活性和匹配功能
比如规定用户只能输入英文26个字母,普通字符应该:abcdef...
而元字符写法:[a-z] 即可
① 分类
边界符
表示位置、开头和结尾,必须用什么开头,用什么结尾
^ 匹配行首的文本 以谁开始
$ 匹配行尾的文本 以谁结束
<script> console.log(/ha/.test('erhahahaha')); // true// 1.边界符// 定义一个以h开头的规则console.log(/^h/.test('haha')); //trueconsole.log(/^h/.test('ehaha')); // false// 定义h结尾console.log(/^h$/.test('h')); //trueconsole.log(/^h$/.test('haha')); // false// 就是精确匹配 只能有h 为true</script>
量词
设定某个模式出现的次数
// 2.量词第一部分console.log(/^h$/.test('h')); // true// * 等价于 >=0 次console.log(/^h*$/.test('hhhhhh')); // trueconsole.log(/^h*$/.test('ehh')); // 必须以h开头 falseconsole.log(/^h*$/.test('hhee')); // 必须以h结尾 false// + 等价于 >=1 次console.log(/^h+$/.test('hhhhhh')); // trueconsole.log(/^h+$/.test('')); // 至少一次 为falseconsole.log(/^h+$/.test('ehh')); // 必须以h开头 falseconsole.log(/^h+$/.test('hhee')); // 必须以h结尾 false// ? 0次或1次console.log(/^h?$/.test('h')); //trueconsole.log(/^h?$/.test('')); // trueconsole.log(/^h?$/.test('hh')); // false
// 2.量词第二部分// {n} 写几次就必须出现几次console.log(/^h{4}$/.test('hhhh')); // h必须只能是4次其他都是错的// 应用于手机号匹配 只能11位// {n,} >=n 次console.log(/^h{4,}$/.test('hhhhhh')); //trueconsole.log(/^h{4,}$/.test('hhh')); // false// {n,m} n~m次 逗号两次不能有空格console.log(/^h{4,8}$/.test('hhhhhh')); // trueconsole.log(/^h{2,4}$/.test('hhhhhh')); // false// 应用于用户名和密码的长度限制
字符类
比如 \d 表示 0-9
(1) [ ] 匹配字符集合
后面的字符串只要包含abc中的任意一个字符,都返回 true
<script>// 字符类 // [abc] 匹配成功一个就true// ^ $ 精确匹配console.log(/^[abc]$/.test('a')); // tconsole.log(/^[abc]$/.test('b')); // tconsole.log(/^[abc]$/.test('c')); // tconsole.log(/^[abc]$/.test('ab')); // f// 可以两个console.log(/^[abc]{2}$/.test('ab')); // t// [a-z] 只选一个console.log(/^[a-z]$/.test('h')); // tconsole.log(/^[A-Z]$/.test('p')); // f// 字母和数字组合console.log(/^[a-zA-Z0-9]$/.test('m')); // t// 只要是一个字母或数字就t</script>
例如QQ号的正则表达式:
// QQ号// /^[1-9][0-9]{4,}$/ 10000开始
(2) [ ] 里加上 ^ 取反符号
比如 [^a-z] 表示匹配除了小写字母以外的其他字符
注意一定要写到 [ ] 里
不要和开始符号混淆
(3) . 匹配除换行符之外的任何单个字符
(4) 预定义:常见模式的简写方式
例如日期格式:
^\d{4}-\d{1,2}-\d{1,2}
② 输入用户名案例(后更)
后更
需求:用户名要求英文字母大小写、数字、下划线或短横线组成,长度位6~16位
分析:
1. 准备正则表达式模式
/^ [a-zA-Z0-9-_]{6,16}$/
2. 表单失去焦点就开始验证
3. 符合正则规范,则让后面的span标签添加right类
4. 不符合则添加wrong类
2.2.4.3 修饰符
修饰符约束正则执行的某些细节行为,如是否区分大小写、是否支持多行匹配
/表达式/修饰符
// 修饰符为 i 正则匹配时不区分大小写
console.log(/a/i.test('a')) // true
console.log(/a/i.test('A')) // true// 修饰符为 g 全局匹配 匹配所有满足正则表达式的结果 所有满足匹配规则的都被修饰
// 替换 replace
字符串.replace(/正则表达式/,'替换的文本')
<script>console.log(/^java/.test('java')); // tconsole.log(/^java/i.test('JAVA')); // tconst str = 'java是一门编程语言,学完java很好';// java替换为前端// replaceconst str1 = str.replace(/java/ig,'前端'); // 不区分大小写 且需要全局匹配所有的java ig// 也可以 /java | JAVA/ |表示或// 且需要返回值console.log(str1); // 前端是一门编程语言,学完前端很好</script>
过滤敏感字
需求:要求用户不能输入敏感字否则被替换为 **
分析:
1. 用户输入内容
2. 内容用正则替换查找,找到敏感词,进行**
3. 全局替换使用 g
<body><textarea name="" id="" cols="30" rows="10"></textarea><button>发布</button><div>点击发布后显示处理后的内容</div><script>const tx = document.querySelector('textarea');const btn = document.querySelector('button');const div = document.querySelector('div');// 点击按钮btn.addEventListener('click',function(){// console.log(tx.value);// 开始过滤div.innerHTML = tx.value.replace(/你好|你号/g,'**');})</script>
</body>
相关综合案例后续逐一补充。