Web APIs
1. Window对象
1.1 BOM
BOM(Browser Object Model ) 是浏览器对象模型
window 是浏览器内置中的全局对象,我们所学习的所有 Web APIs 的知识内容都是基于 window 对象实现的
- window 对象下包含了 navigator、location、document、history、screen 5个属性,即所谓的 BOM (浏览器对象模型)
- document 是实现 DOM 的基础,它其实是依附于 window 的属性。 注:依附于 window 对象的所有属性和方法,使用时可以省略 window
1.2 定时器-延时函数
JavaScript 内置的一个用来让代码延迟执行的函数,叫 setTimeout
语法:setTimeout('回调函数',等待的毫秒数);
// setTimeout(function(){console.log('回调函数');},1000);
function fn(){
console.log('回调函数');
}
setTimeout(fn,1000);
setTimeout 仅仅只执行一次,所以可以理解为就是把一段代码延迟执行, 平时省略window
清除延时函数
语法:
let timer = setTimeout('回调函数',等待的毫秒数);
//清除延时函数:
clearTimeout(timer)
案例 5秒钟之后消失的广告
需求:5秒钟之后,广告自动消失
分析:
①:设置延时函数
②:隐藏元素
// setTimeout(()=>{
// document.querySelector('img').style.display = 'none';
// },5000)
setTimeout(function(){
document.querySelector('img').style.display = 'none';
},5000)
递归函数:函数内部调用其自身
function fn(n){
if(n ===0){
return;
}
fn(n-1)
console.log(n);
}
fn(5)
结合递归函数可以使用 setTimeout 实现 setInterval 一样的功能
<body>
<div class="clock"></div>
<script>
let clock = document.querySelector('.clock');
function timer() {
let date = new Date();
clock.innerHTML = date.toLocaleString();
setTimeout(timer,1000)
}
timer();
</script>
两种定时器对比:
- setInterval 的特征是重复执行,首次执行会延时
- setTimeout 的特征是延时执行,只执行 1 次
- setTimeout 结合递归函数,能模拟 setInterval 重复执行
- clearTimeout 清除由 setTimeout 创建的定时任务
经典面试题
<script>
console.log(111);
setTimeout(function(){
console.log(222);
},1000)
console.log(333);
//111
//333
//222
console.log(111);
setTimeout(function(){
console.log(222);
},1000)
console.log(333);
//111
//333
//222
</script>
1.3 JS 执行机制
以下代码执行的结果是什么?
console.log(1);
setTimeout(function () {
console.log(3);
}, 1000);
console.log(2);//1,3,2
console.log(1);
setTimeout(function () {
console.log(3);
}, 0);
console.log(2);//1,3,2
JS 是单线程
- JavaScript 语言的一大特点就是单线程,也就是说,同一个时间只能做一件事。
- 这是因为 Javascript 这门脚本语言诞生的使命所致——JavaScript 是为处理页面中用户的交互,以及操作 DOM 而诞生的。
- 比如我们对某个 DOM 元素进行添加和删除操作,不能同时进行。 应该先进行添加,之后再删除。
单线程就意味着,所有任务需要排队,前一个任务结束,才会执行后一个任务。这样所导致的问题是: 如果 JS 执行的时间过长,这样就会造成页面的渲染不连贯,导致页面渲染加载阻塞的感觉。
同步任务和异步任务
单线程导致的问题就是后面的任务等待前面任务完成,如果前面任务很耗时(比如读取网络数据),后面任务不得不一直等待!!
为了解决这个问题,利用多核 CPU 的计算能力,HTML5 提出 Web Worker 标准,允许 JavaScript 脚本创建多个线程,但是子线程完全受主线程控制。于是,JS 中出现了同步任务和异步任务。
同步
前一个任务结束后再执行后一个任务,程序的执行顺序与任务的排列顺序是一致的、同步的。比如做饭的同步做法:我们要烧水煮饭,等水开了(10分钟之后),再去切菜,炒菜。
异步
你在做一件事情时,因为这件事情会花费很长时间,在做这件事的同时,你还可以去处理其他事情。比如做饭的异步做法,我们在烧水的同时,利用这10分钟,去切菜,炒菜。
他们的本质区别: 这条流水线上各个流程的执行顺序不同。
JS中所有任务可以分成两种
- 同步任务(synchronous) 在主线程上排队执行的任务,只有前一个任务执行完毕,才能执行后一个任务;
- 异步任务(asynchronous) 不进入主线程、而进入”任务队列”的任务,当主线程中的任务运行完了,才会从”任务队列”取出异步任务放入主线程执行。
JS执行机制(事件循环)
- 先执行执行栈中的同步任务。
- 异步任务放入任务队列中。
- 一旦执行栈中的所有同步任务执行完毕,系统就会按次序读取任务队列中的异步任务,于是被读取的异步任务结束等待状态,进入执行栈,开始执行。
思考:
console.log(1)
document.addEventListener('click', function () {
console.log(4)
})
console.log(2)
setTimeout(function () {
console.log(3)
}, 3000)
图例小结
1.4 location对象
location 的数据类型是对象,它拆分并保存了 URL 地址的各个组成部分
常用属性和方法:
- reload 方法用来刷新当前页面,传入参数 true 时表示强制刷新
<button>点击</button>
<script>
var btn = document.querySelector('button');
btn.addEventListener('click', function () {
// location.reload(true);
console.log(location.hash);
console.log(location.search);
// console.log(location.href = 'http://www.itcast.cn');
console.log(location);
// 记录浏览历史,所以可以实现后退功能
// console.log(location.assign('http://www.itcast.cn'));
// 不记录浏览历史,所以不可以实现后退功能
// location.replace('http://www.itcast.cn');
});
案例 自动跳转页面
<body>
<span>注册成功 5秒后跳转主页</span>
<a href="www.baidu.com">点击跳转</a>
<script>
let c = document.querySelector('span');
let a = document.querySelector('a');
function fnn() {
let b = setInterval(fn, 1000);
let i = 5;
function fn() {
c.innerHTML = `注册成功 ${i}秒后跳转主页 `;
i--;
if (i <= 0) {
clearInterval(b);
location.href =
'http://www.itcast.cn';
//location.assign('http://www.itcast.cn');
}
}
}
fnn();
</script>
</body>
1.5 navigator对象
navigator 对象包含有关浏览器的信息,它有很多属性,我们最常用的是 userAgent,该属性可以返回由客户机发送服务器的 user-agent 头部的值。
下面前端代码可以判断用户那个终端打开页面,实现跳转
if((navigator.userAgent.match(/(phone|pad|pod|iPhone|iPod|ios|iPad|Android|Mobile|BlackBerry|IEMobile|MQQBrowser|JUC|Fennec|wOSBrowser|BrowserNG|WebOS|Symbian|Windows Phone)/i))) {
window.location.href = ""; //手机
} else {
window.location.href = ""; //电脑
}
// 检测 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'
}
})()
1.6 histroy对象
history 的数据类型是对象,该对象与浏览器地址栏的操作相对应,如前进、后退、历史记录等
常用属性和方法:
history 对象一般在实际开发中比较少用,但是会在一些 OA 办公系统中见到。
2. swiper
2.1 插件
插件: 就是别人写好的一些代码,我们只需要复制对应的代码,就可以直接实现对应的效果
学习插件的基本过程
- 熟悉官网,了解这个插件可以完成什么需求 www.swiper.com.cn/
- 看在线演示,找到符合自己需求的demo www.swiper.com.cn/demo/index.…
- 查看基本使用流程 www.swiper.com.cn/usage/index…
- 查看APi文档,去配置自己的插件 www.swiper.com.cn/api/index.h… 注意: 多个swiper同时使用的时候, 类名需要注意区分
3. 本地存储
3.1 本地存储特性
随着互联网的快速发展,基于网页的应用越来越普遍,同时也变的越来越复杂,为了满足各种各样的需求,会经常性在本地存储大量的数据,HTML5规范提出了相关解决方案。
- 数据存储在用户浏览器中
- 设置、读取方便、甚至页面刷新不丢失数据
- 容量较大,sessionStorage和localStorage约 5M 左右
3.2 localStorage
- 生命周期永久生效,除非手动删除 否则关闭页面也会存在
- 可以多窗口(页面)共享(同一浏览器可以共享)
- 以键值对的形式存储使用
存储数据:
//localStorage.setItem('键','值');
localStorage.setItem('姓名',uname);
localStorage.setItem(('age'),22);
localStorage.setItem(('sex'),1);
获取数据:
localStorage.getItem('键')
//let a = localStorage.getItem('姓名');
// console.log(a);
删除数据:
localStorage.removeItem('键');
存储复杂数据类型存储
本地只能存储字符串,无法存储复杂数据类型.需要将复杂数据类型转换成JSON字符串,在存储到本地
JSON.stringify(复杂数据类型)
将复杂数据转换成JSON字符串 存储 本地存储中
let a = JSON.stringify(obj);
console.log(a);
localStorage.setItem('student', a);
let b = localStorage.getItem('student');
console.log(b);
JSON.parse(JSON字符串)
将JSON字符串转换成对象 取出 时候使用
let c = JSON.parse(b);
console.log(c);
练习
<script>
//变量
// let uname = '张鹏';
//本地贮存
// localStorage.setItem('键','值');
// localStorage.setItem('姓名',uname);
// localStorage.setItem(('age'),22);
// localStorage.setItem(('sex'),1);
// 获取数据
// localStorage.getItem('键')
// let a = localStorage.getItem('姓名');
// console.log(a);
// 删除数据
// localStorage.removeItem('键');
//引用数据类型
let obj = {
uname: 'zp',
age: 22,
sex: '男',
};
// 将复杂数据转换成JSON字符串 存储 本地存储中
let a = JSON.stringify(obj);
console.log(a);
localStorage.setItem('student', a);
let b = localStorage.getItem('student');
console.log(b);
// 将JSON字符串转换成对象 取出 时候使用
let c = JSON.parse(b);
console.log(c);
</script>
3.3 sessionStorage(了解)
- 生命周期为关闭浏览器窗口
- 在同一个窗口(页面)下数据可以共享
- 以键值对的形式存储使用
- 用法跟localStorage 基本相同
拓展: 自定义属性
固有属性:
标签天生自带的属性 比如class id title等, 可以直接使用点语法操作
自定义属性:
由程序员自己添加的属性,在DOM对象中找不到, 无法使用点语法操作,必须使用专门的API
- getAttribute('属性名') // 获取自定义属性
- setAttribute('属性名', '属性值') // 设置自定义属性
- removeAttribute('属性名') // 删除自定义属性
data-自定义属性:
- 传统的自定义属性没有专门的定义规则,开发者随意定值,不够规范,所以在html5中推出来了专门的data-自定义属性 在
- 标签上一律以data-开头
- 在DOM对象上一律以dataset对象方式获取
综合案例 本地存储学习信息案例
需求:改为本次存储版本的学习信息表
分析:
需求①:读取本地存储数据(封装函数)
如果本地存储有数据,则返回 JSON.parse() 之后的对象
如果本地存储没有数据,则默认写入三条数据,注意存储的利用JSON.stringify() 存 储JSON 格式的数据
需求②:渲染模块
先读取本地存储数据,然后渲染
需求③:添加模块
注意,先取的最新的本地存储数据,然后追加
新增了数据,要把新数据存储到本地存储别,忘记转换
<!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>Document</title>
<link rel="stylesheet" href="css/user.css" />
</head>
<body>
<h1>新增学员</h1>
<div class="info">
姓名:
<input type="text" class="uname" />
年龄:
<input type="text" class="age" />
性别:
<select name="gender" id="" class="gender">
<option value="男">男</option>
<option value="女">女</option>
</select>
薪资:
<input type="text" class="salary" />
就业城市:
<select name="city" id="" class="city">
<option value="北京">北京</option>
<option value="上海">上海</option>
<option value="广州">广州</option>
<option value="深圳">深圳</option>
<option value="曹县">曹县</option>
</select>
<button class="add">录入</button>
</div>
<h1>就业榜</h1>
<table>
<thead>
<tr>
<th>学号</th>
<th>姓名</th>
<th>年龄</th>
<th>性别</th>
<th>薪资</th>
<th>就业城市</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<!-- <tr>
<td>1001</td>
<td>欧阳霸天</td>
<td>19</td>
<td>男</td>
<td>15000</td>
<td>上海</td>
<td>
<a href="javascript:">删除</a>
</td>
</tr> -->
</tbody>
</table>
<script>
// 1. 准备好数据后端的数据
let arr = [
{
stuId: 1001,
uname: '欧阳霸天',
age: 19,
gender: '男',
salary: '20000',
city: '上海',
},
{
stuId: 1002,
uname: '令狐霸天',
age: 29,
gender: '男',
salary: '30000',
city: '北京',
},
{
stuId: 1003,
uname: '诸葛霸天',
age: 39,
gender: '男',
salary: '2000',
city: '北京',
},
];
function getLocalData() {
let date = localStorage.getItem('date');
if (date) {
return JSON.parse(date);
} else {
let arr = [
{
stuId: 1001,
uname: '欧阳霸天',
age: 19,
gender: '男',
salary: '20000',
city: '上海',
},
{
stuId: 1002,
uname: '令狐霸天',
age: 29,
gender: '男',
salary: '30000',
city: '北京',
},
{
stuId: 1003,
uname: '诸葛霸天',
age: 39,
gender: '男',
salary: '2000',
city: '北京',
},
];
}
localStorage.setItem('date',JSON.stringify(arr))
// let a = JSON.stringify(arr);
// console.log(a);
// let b = localStorage.setItem('list',a);
// console.log(b);
}
// 获取父元素 tbody
let tbody = document.querySelector('tbody');
// 添加数据按钮
// 获取录入按钮
let add = document.querySelector('.add');
// 获取各个表单的元素
let uname = document.querySelector('.uname');
let age = document.querySelector('.age');
let gender = document.querySelector('.gender');
let salary = document.querySelector('.salary');
let city = document.querySelector('.city');
// 渲染函数 把数组里面的数据渲染到页面中
function render() {
let arr = getLocalData();
// 先干掉以前的数据 让tbody 里面原来的tr 都没有
tbody.innerHTML = '';
// 在渲染新的数据
// 根据数据的条数来渲染增加 tr
for (let i = 0; i < arr.length; i++) {
// 1.创建tr
let tr = document.createElement('tr');
// 2.tr 里面放内容
tr.innerHTML = `
<td>${arr[i].stuId}</td>
<td>${arr[i].uname}</td>
<td>${arr[i].age}</td>
<td>${arr[i].gender}</td>
<td>${arr[i].salary}</td>
<td>${arr[i].city}</td>
<td>
<a href="javascript:" id="${i}">删除</a>
</td>
`;
// 3.把tr追加给 tobdy 父元素.appendChild(子元素)
tbody.appendChild(tr);
}
}
// 页面加载就调用函数
render();
add.addEventListener('click', function () {
let arr = getLocalData();
if(arr.length === 0){
stuId = '1001';
}else{
stuId: arr[arr.length - 1].stuId + 1;
}
// alert(11)
// 获得表单里面的值 之后追加给 数组 arr 用 push方法
arr.push({
// 得到数组最后一条数据的学号 1003 + 1
stuId: arr[arr.length - 1].stuId + 1,
uname: uname.value,
age: age.value,
gender: gender.value,
salary: salary.value,
city: city.value,
});
localStorage.setItem('date',JSON.stringify(arr));
// console.log(arr)
// 重新渲染我们的函数
render();
// 复原所有的表单数据
uname.value = age.value = salary.value = '';
gender.value = '男';
city.value = '北京';
});
// 删除操作, 删除的也是数组里面的数据 , 但是我们用事件委托
tbody.addEventListener('click', function (e) {
// alert(11)
// 我们只能点击了链接 a ,才会执行删除操作
// 那我们怎么知道你点击了a呢?
// 俺们只能点击了链接才能做删除操作
// console.dir(e.target.tagName)
if (e.target.tagName === 'A') {
// alert('你点击了链接')
// 删除操作 删除 数组里面的数据 arr.splice(从哪里开始删,1)
// 我要得到a的id 需要
// console.log(e.target.id)
arr.splice(e.target.id, 1);
// 重新渲染我们的函数
localStorage.setItem('date',JSON.stringify(arr));
localStorage.removeItem('date',JSON.stringify(arr))
render();
}
});
</script>
</body>
</html>