一.window对象
浏览器对象模型;BOM包含DOM,大多数window省略
1.1.定时器-延时函数
用来让代码延迟执行,setTimeout(回调函数,等待的秒数)
注意:延时器需要等待,所以后面代码先执行
每次调用延时器,会产生一个新延时器
只执行一次,平时省略window,返回数字型id
// 只执行一次
setTimeout(function () {
console.log('时间到了');
}, 2000)
清除延时函数:clearTimeout(定时器名字)
let timer = setTimeout(function () {
console.log('时间到了');
}, 2000)
clearTimeout(timer)
延时函数只执行一次,间歇函数每隔一段时间执行一次,除非手动清除
5秒关闭广告:
<style>
img {
position: fixed;
right: 0;
bottom: 0;
}
</style>
<body>
<img src="./images/ad.png" alt="">
<script>
const img = document.querySelector('img')
setTimeout(function () {
img.style.display = 'none'
}, 5000)
</script>
</body>
1.2.js执行机制
1.2.1同步异步
js单线程,同一时间只能做一件事
同步:前一个任务结束后在执行后一个任务
异步:做一件事同时可以做另一件事
同步任务都在主线上执行,形成一个执行线
耗时的异步任务有:普通事件如click,resize(窗口大小发生改变)等;资源加载如load,error等;定时器setInterval,setTimeout等;异步任务添加到任务队列
1.2.2执行机制:
1.先执行执行栈中的同步任务
2.浏览器将异步任务放入任务队列中
3.执行栈中的同步任务执行完毕,系统按次序读取任务队列中的异步任务,异步任务结束等待,进入执行栈开始执行
事件循环就是说同步任务执行完之后,系统还会回到任务队列里去看,如果还有异步任务,就扔到主执行栈执行,执行完再回去看,如果还有就再执行
<script>
console.log(1);
console.log(2);
setTimeout(function () {
console.log(3);
}, 0)//异步任务,最后执行
console.log(4);
</script
1.3.location对象
location数据类型是对象,拆分并保存了url地址的各个组成部分
常用属性和方法:
// window可以省略不写
console.log(window.location);
console.log(location.href);
// 利用href 利用js方法自动跳转页面
location.href = 'http://www.baidu.com'
5秒钟后自动跳转页面:
<body>
<a href="http://www.baidu.com">支付成功<span>5</span>秒后跳转首页</a>
<script>
const a = document.querySelector('a')
let num = 5
let timeId = setInterval(function () {
num--
a.innerHTML = ` 支付成功<span>${num}</span>秒后跳转首页`
if (num === 0) {
// 防止num--变成负数。结束定时器
clearInterval(timeId)
// 如果不点击 倒计时变为0后自动跳转、
location.href = 'http://www.baidu.com'
}
}, 1000)
</script>
</body>
location.search:获取用户输入信息
<body>
<form action="">
<input type="text" name="username" id="">
<input type="password" name="pwd" id="">
<button>点击</button>
</form>
<script>
console.log(location.search)
</script>
location.hash:
后期vue路由的铺垫,用于不刷新页面显示不同页面
获取地址中的哈希值 #后面的
<a href="#/my">我的</a>
<a href="#/download">下载</a>
<a href="#/friend">关注</a>
方法:location.reload()
用于刷新当前页面,传入参数true时表示强制刷新
<button class="reload">刷新</button>
const reload = document.querySelector('.reload')
reload.addEventListener('click', function () {
location.reload(true)
})
1.4.navigator对象
记录了浏览器自身相关信息,通过userAgent检测浏览器版本及平台
<script>
// 检测userAgent( 浏览器信息)
!(function () {
const userAgent = navigator.userAgent
//验证是否为 Android或iPhone
const 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>
1.5.history对象
主要管历史记录,该对象与浏览器地址栏的操作相对应,如前进,后退,历史记录等
<body>
<button>前进</button>
<button>后退</button>
<script>
const back = document.querySelector('button:first-child')
const forward = back.nextElementSibling
back.addEventListener('click', function () {
// 后退一步
// history.back()
history.go(-1)
})
forward.addEventListener('click', function () {
//前进一步
// history.forward()
history.go(1)
})
</script>
</body>
二.本地存储(重要)
小型仓库,数据存储在用户浏览器中;设置,读取方便,甚至页面刷新不丢失数据,容量大
2.1 locationStorage
可以将数据永久存储在用户电脑,除非手动删除,否则关闭页面也会存在
特性:可以多页面共享,同一浏览器可以共享
以键值对的形式存储使用:
存储数据,修改数据:localStorage.setItem(’键‘,’值‘)
如果原来存在该方法,再写则为修改
localStorage.setItem('uname', 'ww')
获取数据:localStorage.getItem('key')
console.log(localStorage.getItem('uname'));
删除本地存储:localStorage.removeItem('key')
localStorage.removeItem('uname')
本地存储只能存储字符串数据类型
2.2 sessionStorage
特性:
- 生命周期为关闭浏览器窗口
- 在同一个页面下数据可以共享
- 以键值对的形式存储使用
- 用法跟localStorage基本相同
2.3存储复杂数据类型
需要将复杂数据类型转换为JSON字符串,再存储到本地:JSON.stringify(复杂数据类型)
JSON.parse()将取出的字符串转换为对象
// 1.复杂数据类型存储必须转换为JSON字符串存储
localStorage.setItem('obj', JSON.stringify(obj))
// 获取 也是字符串类型
// console.log(localStorage.getItem('obj'));
// 2.将JSON字符串转换为对象
console.log(JSON.parse(localStorage.getItem('obj')));
2.4map和join方法
map也称映射,指两个元素集之间元素相互对应的关系,有返回值;遍历数组处理数据可以生成tr,并且返回新的数组;foreach无返回值
<script>
const arr = ['red', 'blue', 'pink']
const newArr = arr.map(function (ele, index) {
console.log(ele);//ele为数组元素
console.log(index);//数组索引号
// map不仅可以遍历数组,还可以拼接字符串
return ele + '颜色'
})
console.log(newArr);
</script>
join()用于将数组中所有元素转换为一个字符串
// join方法将数组转换为一个字符串
// 小括号内为空时自动用逗号分隔
console.log(newArr.join())//red颜色, blue颜色, pink颜色
// 小括号内为空字符串时元素间无分隔符
console.log(newArr.join(''));// red颜色blue颜色pink颜色
console.log(newArr.join('|'));//red颜色|blue颜色|pink颜色
三.综合案例-学生就业统计
1.渲染模块
首先读取本地存储数据,判断本地是否存在数据,若存在则通过JSON.parse()将数组字符串转换为对象添加到新数组,若不存在则返回空数组
const arr = JSON.parse(localStorage.getItem('data')) || []
其次通过map和join渲染数组arr内数据 ;先写渲染方法render(),利用map遍历数组arr,返回数据数组。通过join将返回的数据数组转换为一个字符串添加到tbody内,同时显示添加了几条数据根据arr数组内信息长度,有几条数据则共有几条;渲染方法写完后调用方法render()
// 1.渲染模块
/* 1.1先读取本地存储数据
本地有存储数据则通过json转换为对象,存储到变量里,后期用于渲染页面
本地若没有数据,则用空数组代替 */
// 本地存储一次即可,不需每次打开重新储存
// localStorage.setItem('data', JSON.stringify(initData))
const arr = JSON.parse(localStorage.getItem('data')) || []
// console.log(arr);
// 1.2利用map和join渲染页面
function render() {
const tbody = document.querySelector('tbody')
// 1.2.1.利用map遍历数组,返回tr数组
const trArr = arr.map(function (ele, index) {//ele为数组元素,index为索引号
return `
<tr>
<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:" date-id="${index}">删除</a>
</td>
</tr>
`
})
console.log(trArr);
// 1.2.2.利用join将数组转换为字符串
// 1.2.3.利用innerHTML和join将生成数组转化为字符串添加到tbody内
tbody.innerHTML = trArr.join('')
// 显示共有几条数据
document.querySelector('.title span').innerHTML = arr.length
}
render()
2.新增数据模块
首先为form表单添加提交事件,并通过 e.preventDefault()阻止默认跳转;然后进行非空判断,若名字,年龄和薪资的值为空,则提示输入不能为空;然后点击添加则获取数据对象通过push()添加到arr数组内;然后通过render()方法渲染到页面,并通过reset()重置输入表格;最后将添加的数据信息通过localStorage.setItem进行本地存储,防止刷新后消失,但要通过JSON.stringify()转换为字符串
当向arr数组添加数据时,为了防止删除第一条数据后再添加数据时后面序号不加,需要用最后一个数据的序号id加上1,即以下现象:
// 2.新增模块
// 2.1form表单注册提交事件 阻止默认跳转行为
const info = document.querySelector('.info')
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 time = document.querySelector('.time')
const tbody = document.querySelector('tbody')
info.addEventListener('submit', function (e) {
e.preventDefault()
// 2.2非空判断 先获取不能为空的各元素
if (!uname.value || !age.value || !salary.value) {
return alert('输入不能为空')
}
// 也可以这样写
/* const items = document.querySelectorAll('[name]')
for (let i = 0; i < items.length; i++) {
if (items[i].value === '') {
return alert('输入内容不能为空')
}
} */
// 2.3给arr数组追加对象,对象里存储 表单内用户输入的数据
arr.push({
// 处理id,防止删除第一条数据后后面数据id不加,需要用最后一个数据的id加1
// arr[arr.length - 1].stuId为数组最后一条数据的id,加1则为最新一条数据的id
// 若一开始有数据存在即arr.length存在,则再添加数据为 arr[arr.length - 1].stuId + 1
// 若一开始没有数据即arr.length=0,则直接使stuId=1
stuId: arr.length ? arr[arr.length - 1].stuId + 1 : 1,
uname: uname.value,
age: age.value,
gender: gender.value,
salary: salary.value,
city: city.value,
time: new Date().toLocaleString()//得到当前时间
})
// 2.4渲染页面和重置表单
// 表单内重置为默认状态空 this为info
this.reset()
render()
// 2.5将数组信息转换为json字符串存储到本地存储,防止刷新后消失
localStorage.setItem('data', JSON.stringify(arr))
})
3.删除模块
首先为tbody添加点击事件,若点击的标签名为A,则为删除标签设置自定义id,date-id="${index},index为arr数组索引号,然后通过splice删除数组内点击的a标签对应的id号,删除后arr数组内容更新需要用render()方法重新渲染数据,然后重新将arr数组存入本地存储
// 3.删除模块
// 3.1采取事件委托给tbody注册点击事件
tbody.addEventListener('click', function (e) {
if (e.target.tagName === 'A') {
if (confirm('你确定要删除这条数据吗?')) {
// 为删除标签添加自定义属性date-id=索引号index 根据id删除
arr.splice(e.target.dataset.id, 1)
// 删除后重新渲染页面
render()
// 将最新的arr数组存入本地存储
localStorage.setItem('data', JSON.stringify(arr))
}
}