BOM
window对象 ==>包含docment
Browser Object Model
定时器–延时函数
之前学的是间歇函数
让代码延迟执行 仅执行一次
setTimeout(回调函数,等待毫秒数)
消除 clearTimeout(timer)
==> 用于递归时需要进行去除
JS执行机制
单线程 ==> 一个任务结束,才会执行下一个任务
导致渲染慢
如何解决?
Web Worker标准 == 允许JavaScript脚本创建多个线程
因此分出了同步和异步
同步 | 程序的执行顺序和任务的排列顺序一样 |
---|---|
异步 | 当一件事花费很长时间,同时还可以处理其他事情 |
同步任务 | 立马就能执行,都在主线程上执行,形成一个执行栈 |
---|---|
异步任务 | 普通事件,资源加载,定时器等等,添加到任务队列中 |
[!IMPORTANT]
- 先执行执行栈【相当于主车道】中的同步任务
- 异步任务放入任务队列中【应急车道】
- 一旦执行栈中的所有同步任务执行完毕,系统会按次序读取任务队列中的异步任务==> 结束等待状态,进入执行栈,执行
事件循环
进行多线程处理的是,浏览器[宿主环境]而不是JavaScript,
location 对象
拆分并保存了URL的各个部分
常用属性
href | 赋值则会跳转到网址,可配合定时器 |
---|---|
search | 拿地址中’?'后面的信息(表单提交的数据等) |
hash | '#'后面的值 |
补充方法:
reload(布尔值) 若为true,则可以强制刷新
navigator 对象
判断用户使用设备 ==> 跳转到适配页面
history 对象
管理历史记录,前进后退历史页面
相当于浏览器中的前进后退的按钮
back() | 后踢一个页面 |
---|---|
forward() | 前进一个页面 |
go(参数) | 通过参数判断前进后退到哪里 |
本地存储
本地存储数据,读取方便,刷新页面不会丢失
localStorage
永久存储在本地
- 增
setItem(key,value)
- 删
removeItem(key)
- 改
setItem(key,value)
- 获取
getItem(key)
路径:
检查 ==> Application ==> Storage ==> local …
sessionStorage
不同:生命周期为关闭浏览器窗口
若需要存储复杂数据
转换为JSON字符串存储,转换会复杂数据类型获取
JSON.stringify(复杂数据类型) | JSON.parse(key) |
---|
综合案例
学生统计表
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta http-equiv="X-UA-Compatible" content="ie=edge" /><title>学生就业统计表</title><link rel="stylesheet" href="./iconfont/iconfont.css"><link rel="stylesheet" href="css/index.css" />
</head><body><h1>学生就业统计表</h1><form class="info" autocomplete="off"><input type="text" class="uname" name="uname" placeholder="姓名" /><input type="text" class="age" name="age" placeholder="年龄" /><input type="text" class="salary" name="salary" placeholder="薪资" /><select name="gender" class="gender"><option value="男">男</option><option value="女">女</option></select><select name="city" class="city"><option value="北京">北京</option><option value="上海">上海</option><option value="广州">广州</option><option value="深圳">深圳</option><option value="曹县">曹县</option></select><button class="add"><i class="iconfont icon-tianjia"></i>添加</button></form><div class="title">共有数据<span>0</span>条</div><table><thead><tr><th>ID</th><th>姓名</th><th>年龄</th><th>性别</th><th>薪资</th><th>就业城市</th><th>录入时间</th><th>操作</th></tr></thead><tbody><!-- <tr><td>1</td><td>迪丽热巴</td><td>23</td><td>女</td><td>12000</td><td>北京</td><td>2099/9/9 08:08:08</td><td><a href="javascript:"><i class="iconfont icon-shanchu"></i>删除</a></td></tr> --></tbody></table><script>// const obj = {// stuId: arr.length + 1,// uname: uname.value,// age: 22,// salary: salary.value,// gender: gender.value,// city: city.value,// time: new Date().toLocaleString(),// }//获取对象const tbody = document.querySelector('tbody')const info = document.querySelector('.info')const add = document.querySelector('.add')const uname = document.querySelector('.uname')const age = document.querySelector('.age')const salary = document.querySelector('.salary')const gender = document.querySelector('.gender')const city = document.querySelector('.city')const howmany = document.querySelector('.title span')const initData = []// localStorage.setItem('data', JSON.stringify(initData))const arr = JSON.parse(localStorage.getItem('data'))render()//渲染业务function render() {//从本地数据中读取数组//更改为tr的格式const newArr = arr.map(function (ele, index) {return `<td>${ele.stuId}</td><td>${ele.uname}</td><td>${ele.age}</td><td>${ele.gender}</td><td>${ele.salary}</td><td>${ele.city}</td><td>${ele.time}</td><td><a href="javascript:" data-id="${index}"><i class="iconfont icon-shanchu"></i>删除</a></td></tr>`})console.log(newArr);//转化为字符串形式并存储到tbody的innerHTMl中tbody.innerHTML = newArr.join('')//渲染一共有几条数据howmany.innerHTML = arr.length}//新增业务function addMan() {//点击添加按钮//1.阻止表单默认提交行为info.addEventListener('submit', function (e) {e.preventDefault()})//2.判断表单中是否有内容空了,空了则返回提示信息if (!uname.value || !age.value || !salary.value) {return alert('输入内容不能为空')}//3.将表单的数据写道对象中//4.将对象追加到arr数组中去arr.push({stuId: arr.length + 1,uname: uname.value,age: 22,salary: salary.value,gender: gender.value,city: city.value,time: new Date().toLocaleString()})//4.1将arr存储到本地中localStorage.setItem('data', JSON.stringify(arr))//5.重新渲染页面render()//6.重置表单info.reset()}add.addEventListener('click', function () {addMan()})//删除业务//1.点击删除按钮 tbody 利用事件委托tbody.addEventListener('click', function (e) {//2.判断是否为aif (e.target.tagName === 'A') {//3.弹窗,询问是否删除// let input = +(prompt('是否删除,删除选1,不删除选0'))if (confirm('您是否要删除这条学生数据')) {//4.若删除,获取对应对象的dataset值//5.通过对应的id值来索引下标,删除arr中的对应元素arr.splice(+(e.target.dataset.id), 1)//5.1将本地存储数据更新localStorage.setItem('data', JSON.stringify(arr))//6.重新渲染页面render()}}})</script>
</body></html>
可实现
- 渲染页面
- 新增数据
- 删除数据
- 刷新页面不会消失数据,依旧有以前的数据
正则表达式(对象)
用于匹配字符串中字符组合的模式
use:用来查找,替换那些符合正则表达式的文本 ==> 匹配,替换,提取
语法
- 定义规则
/....../
==> 字面量 - 查找
方法
test(字符串) | 返回布尔值 |
---|---|
exec(字符串) | 返回数组或null |
exec()返回的数组中包含的是匹配正则表达式的字符串的相关信息
元字符
具有特殊含义的字符
- 边界符
^---开头 $---结尾 两个一起使用则为精准匹配
- 量词
- 字符类
修饰符
语法位置
/...../修饰符
i | 忽略字母大小写 |
---|---|
g | 匹配所有结果 |
案例
用户验证案例
<!DOCTYPE html>
<html lang="en"><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>span {display: inline-block;width: 250px;height: 30px;vertical-align: middle;line-height: 30px;padding-left: 15px;}.error {color: red;background: url(./images/error1.png) no-repeat left center;}.right {color: green;background: url(./images/right.png) no-repeat left center;}</style>
</head><body><input type="text"><span></span><script>//获取对象const input = document.querySelector('input')const span = document.querySelector('span')//书写正则表达式的规则const rule = /^[a-zA-Z0-9-_]{6,16}$///绑定事件input.addEventListener('blur', function () {//判断是否符合正则表达式规则if (rule.test(this.value)) {span.className = 'right'// console.log('right');span.innerHTML = '输入正确'} else {span.className = 'error'// console.log('wrong');span.innerHTML = '请输入6-16位由英文字母,数字,下划线的字符串'}})</script>
</body></html>
综合案例:
页面注册
//获取所有对象const code = document.querySelector('.code')//发送验证码模块//获取对象//绑定点击事件let flag = true //控制在倒计时内无法再次点击发送验证码 节流阀code.addEventListener('click', function () {if (flag) {flag = falselet num = 5code.innerHTML = '5秒后重新获取'let stop = setInterval(function () {num--code.innerHTML = `${num}秒后重新获取`if (num === 0) {code.innerHTML = `重新获取`clearInterval(stop)//到时间了,可以使节流阀flag打开了flag = true}}, 1000)}})//验证输入内容是否符合模块//1.用户名模块const name = document.querySelector('[name=username]')//1.1绑定事件name.addEventListener('change', verifyName)//1.2封装函数function verifyName() {// console.log(11);const tip = name.nextElementSibling//设定正则表达式const ruleName = /^[a-zA-Z0-9-_]{6,10}$/if (!ruleName.test(name.value)) {tip.innerHTML = '输入有误,请输入6-10位'return false}tip.innerHTML = ''return true}//2.手机号模块const phone = document.querySelector('[name=phone]')//1.1绑定事件phone.addEventListener('change', verifyPhone)//1.2封装函数function verifyPhone() {// console.log(11);const tip = phone.nextElementSibling//设定正则表达式const rulePhone = /^1(3\d|4[5-9]|5[0-35-9]|6[567]|7[0-8]|8\d|9[0-35-9])\d{8}$/if (!rulePhone.test(phone.value)) {tip.innerHTML = '输入有误,请输入11位手机号码'return false}tip.innerHTML = ''return true}//3.密码模块const password = document.querySelector('[name=password]')//1.1绑定事件password.addEventListener('change', verifypassword)//1.2封装函数function verifypassword() {// console.log(11);const tip = password.nextElementSibling//设定正则表达式const rulepassword = /^[a-zA-Z0-9-_]{6,20}$/if (!rulepassword.test(password.value)) {tip.innerHTML = '输入有误,请输入6-20位字母数字下划线密码'return false}tip.innerHTML = ''return true}//4.验证码模块const Code = document.querySelector('[name=code]')//1.1绑定事件Code.addEventListener('change', verifyCode)//1.2封装函数function verifyCode() {// console.log(11);const tip = Code.nextElementSibling//设定正则表达式const ruleCode = /^\d{6}$/if (!ruleCode.test(Code.value)) {tip.innerHTML = '输入有误,请输入6位数字'return false}tip.innerHTML = ''return true}//5.再次密码验证模块const confirm = document.querySelector('[name=confirm]')//1.1绑定事件confirm.addEventListener('change', verifyconfirm)//1.2封装函数function verifyconfirm() {// console.log(11);const tip = confirm.nextElementSibling//设定正则表达式const ruleconfirm = /^\d{6}$/if (!(confirm.value === password.value)) {tip.innerHTML = '与上述密码不一致'return false}tip.innerHTML = ''return true}//6.协议模块//获取对象const agree = document.querySelector('.icon-queren')//绑定点击事件agree.addEventListener('click', function () {agree.classList.toggle('icon-queren2')})//7.全部提交//获取表单对象const form = document.querySelector('form')//添加提交事件监听器form.addEventListener('submit', function (e) {//判断是否同意协议if (!agree.classList.contains('icon-queren2')) {alert('请勾选同意协议')//阻止表单默认行为e.preventDefault()}//依次判断其他模块是否输入正确内容if (!verifyName()) e.preventDefault()if (!verifyconfirm()) e.preventDefault()if (!verifyCode()) e.preventDefault()if (!verifypassword()) e.preventDefault()if (!verifyPhone()) e.preventDefault()})
补充知识点:
- input的change事件 ==> 当内容发生变化,且失去焦点,事件触发
- classList有新方法contains(‘类名’) 返回布尔值
登录页面
//1.tab栏切换//获取对象 -- 事件委托const tab_nav = document.querySelector('.tab-nav')const panel = document.querySelectorAll('.tab-pane')//绑定事件tab_nav.addEventListener('click', function (e) {if (e.target.tagName === 'A') {//取消之前的activetab_nav.querySelector('.active').classList.remove('active')//增加后来的activee.target.classList.add('active')}//更换对应盒子//先全部去除for (let i = 0; i < panel.length; i++) {panel[i].style.display = 'none'}//显示对应需要的盒子panel[e.target.dataset.id].style.display = 'block'})//点击提交事件const agree = document.querySelector('[name=agree]')const form = document.querySelector('form')const username = document.querySelector('[name=username]')const password = document.querySelector('[name=password]')//绑定提交事件form.addEventListener('submit', function (e) {//阻止提交e.preventDefault()//判断是否有同意协议if (!agree.checked) {alert('请勾选协议')}//将数据存储到本地存储中去localStorage.setItem('xtx_name', username.value)localStorage.setItem('xtx_pwd', password.value)//跳转页面location.href = 'http://127.0.0.1:5500/webAPI/%E5%85%83%E5%AD%97%E7%AC%A6%E6%A1%88%E4%BE%8B/%E7%BB%BC%E5%90%88%E6%A1%88%E4%BE%8B%E7%B4%A0%E6%9D%90/index.html'})
首页页面
//获取对象const li1 = document.querySelector('.xtx_navs li:first-child')const li2 = li1.nextElementSibling//封装render函数function render() {//获取本地数据const uname = localStorage.getItem('xtx_name')//判断是否有用户名数据if (uname) {li1.innerHTML = ` <a href="javascript:;">${uname}</a>`li2.innerHTML = ` <a href="javascript:;">退出登录</a>`} else {li1.innerHTML = `<a href="./login.html">请先登录</a>`li2.innerHTML = ` <a href="./register.html">免费注册</a>`}}//跳转页面后先进行一次渲染render()//绑定事件li2.addEventListener('click', function () {//删除本地数据localStorage.removeItem('xtx_name')//重新渲染render()})