BOM- 操作浏览器

1. JS执行机制

  1. JavaScript 语言的一大特点就是单线程,也就是说,同一个时间只能做一件事。这是因为 Javascript 这 门脚本语言诞生的使命所致——JavaScript 是为处理页面中用户的交互,以及操作 DOM 而诞生的。比 如我们对某个 DOM 元素进行添加和删除操作,不能同时进行。 应该先进行添加,之后再删除
  2. 单线程就意味着,所有任务需要排队,前一个任务结束,才会执行后一个任务。这样所导致的问 题是: 如果 JS 执行的时间过长,这样就会造成页面的渲染不连贯,导致页面渲染加载阻塞的感觉
  3. 为了解决这个问题,利用多核 CPU 的计算能力,HTML5 提出 Web Worker 标准,允许 JavaScript 脚本创建多个线程。于是,JS 中出现了同步和异步

1. 同步

  1. 前一个任务结束后再执行后一个任务,程序的执行顺序与任务的排列顺序是一致的、同步的。比如做饭的同步 做法:我们要烧水煮饭,等水开了(10分钟之后),再去切菜,炒菜
  2. 同步任务都在主线程上执行,形成一个执行栈

2. 异步

  1. 你在做一件事情时,因为这件事情会花费很长时间,在做这件事的同时,你还可以去处理其他事 情。比如做饭的异步做法,我们在烧水的同时,利用这10分钟,去切菜,炒菜
  2. JS 的异步是通过回调函数实现的
一般而言,异步任务有以下三种类型:
  1. 普通事件, 如 click、resize 等
  2. 资源加载, 如 load、error 等
  3. 定时器, 包括 setInterval、setTimeout 等 异步任务相关添加到任务队列中(任务队列也称为消息队列)
  4. 他们的本质区别: 这条流水线上各个流程的执行顺序不同
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// 1. JS执行机制 同步 异步
// 同步: 执行栈 在主线程上执行
// 异步: 任务/消息队列 通过回调函数实现
// 1. 先执行栈的同步任务
// 2. 异步任务放入任务队列中
// 3. 同步任务执行完 系统按次序读取异步任务 进入执行栈执行
// 主线程重复获得任务、执行任务、再获取任务、再执行 这种机制称事件循环event loop
console.log(1)
setTimeout(function () {
console.log(2)
}, 0)
console.log(3)
console.log(11)
document.addEventListener('click', function () {
console.log(44)
})
console.log(22)
setTimeout(function () {
console.log(33)
}, 2000)

2. JS执行过程

  1. 先执行执行栈中的同步任务
  2. 异步任务放入任务队列中
  3. 一旦执行栈中的所有同步任务执行完毕, 系统就会按次序读取任务队列中的异步任务,于是被读取的异步任务 结束等待状态,进入执行栈,开始执行

由于主线程不断的重复获得任务、执行任务、再获取任务、再执行,所以这种机制被称为事件循环event loop

3. Window对象

  1. BOM(Browser Object Model ) 是浏览器对象模型
  2. window 是浏览器内置中的全局对象,我们所学习的所有 Web APIs 的知识内容都是基于 window 对象实现的window 对象下包含了 navigator、location、document、history、screen 5个属性, 即所谓的 BOM(浏览器对象模 型)
  3. document 是实现 DOM 的基础,它其实是依附于 window 的属性
  4. 注:依附于 window 对象的所有属性和方法,使用时可以省略 window
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// window是最大的对象 浏览器对象模型
// document是DOM最大对象
window.document.querySelector('.box')
window.setInterval()
function fn() {
console.log(1)
}
window.fn()
addEventListener('scroll', function () {
console.log(2)
})
window.alert()
window.prompt()
console.log(window)

1. 定时器-延时函数

  1. JavaScript 内置的一个用来让代码延迟执行的函数,叫 setTimeout
  2. setTimeout 仅仅只执行一次,所以可以理解为就是把一段代码延迟执行, 平时省略window
  3. 结合递归函数可以使用 setTimeout 实现 setInterval 一样的功能
1
2
3
4
5
6
7
8
9
// 1. 延迟对象 仅执行一次 就没了
let time = setTimeout(function () {
document.write('爆炸了')
}, 10000)
// 2. 清除延迟函数 点击按钮后清除
let num1 = document.querySelector('button')
num1.addEventListener('click', function () {
clearTimeout(time)
})
1. 两种定时器对比:
  1. setInterval 的特征是重复执行,首次执行会延时
  2. setTimeout 的特征是延时执行,只执行 1 次
  3. setTimeout 结合递归函数,能模拟 setInterval 重复执行
  4. clearTimeout 清除由 setTimeout 创建的定时任务
2. 5秒钟之后消失的广告
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
// 2秒后自动消失广告
let num2 = document.querySelector('img')
setTimeout(function () {
num2.style.display = 'none'
}, 2000)
// 4. 递归函数: 自己调用自己
// 容易死递归 要加上退出条件
let num3 = 0
function fn() {
num3++
console.log(1)
// 如果要退出 得加上判断条件
if (num3 >= 10) {
return
}
// 自己调自己
fn()
}
fn()
// 5. 利用递归实现/模拟 setInterval
let num4 = document.querySelector('div')
function fn1() {
num4.innerHTML = new Date().toLocaleString()
setTimeout(fn1)
}
fn1()
// 6. 两个定时器对比
// 间歇函数 重复执行 首次延迟执行
// 延迟函数 只执行1次

2. location对象

  1. location 的数据类型是对象,它拆分并保存了 URL 地址的各个组成部分

1. href 属性获取完整的 URL 地址,对其赋值时用于地址的跳转

  1. href 属性获取完整的 URL 地址,对其赋值时用于地址的跳转
1
2
3
// 1. location.href 得到url地址 可读写 可利用js跳转页面
console.log(location.href)
// location.href = 'http://baidu.com'
5秒钟之后跳转的页面
1
2
3
4
5
6
7
8
9
10
11
12
// 2. 3秒后跳转页面
<a href="">3秒后跳转百度页面</a>
let num1 = document.querySelector('a')
let num2 = 100
let num3 = setInterval(function () {
num2--
num1.innerHTML = `${num2}秒后跳转百度页面`
if (num2 == 1) {
clearInterval(num3)
location.href = 'http://baidu.com'
}
}, 1000)

2. search 属性获取地址中携带的参数,符号 ?后面部分

1
2
3
4
5
6
7
<!-- 3.location.search 属性 -->
<form action="4.JS执行机制.html">
<input type="text" name="username">
<button>提交</button>
</form>
// 3. location.search 属性 ?username=abd
document.write(location.search)

3. hash 属性获取地址中的啥希值,符号 # 后面部分

后期vue路由的铺垫,经常用于不刷新页面,显示不同页面,比如 网易云音乐

1
2
3
4
5
// 4. location.hash # 属性 vue路由
<a href="#one">第一个</a>
<a href="#two">第二个</a>
let num4 = document.querySelector('a')
document.write(location.hash)

4. reload 方法用来刷新当前页面,传入参数 true 时表示强制刷新

1
2
3
4
5
6
7
// 5. location.reload 属性 方法
button class="btn">强制刷新</button>
let num5 = document.querySelector('.btn')
num5.addEventListener('click', function () {
// 强制刷新 默认为 true
location.reload()
})

3. navigator对象

  1. navigator的数据类型是对象,该对象下记录了浏览器自身的相关信息
  2. 通过 userAgent 检测浏览器的版本及平台
1
2
3
4
5
6
7
8
9
10
11
12
console.log(navigator)
// 1.检测 userAgent 浏览器信息
!(function () {
const userAgent = navigator.userAgent
// 2.验证是否为Android或iPhone
const android = userAgent.match(/(Android);?[\s\/]+([\d.]+)?/)
const iphone = userAgent.match(/(iPhone\sOS)\s([\d_]+)/)
// 3.如果是Android或iPhone,则跳转至移动站点
if (android || iphone) {
location.href = 'http://baidu.com'
}
})()

4. histroy对象

  1. history 的数据类型是对象,该对象与浏览器地址栏的操作相对应,如前进、后退、历史记录等
  2. history 对象一般在实际开发中比较少用,但是会在一些 OA 办公系统中见到
使用方法作用
back()可以后退
forward()前进
go(参数)前进后退, 1是前进页面, -1是后退页面
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<button>前进</button>
<button>后退</button>
// 1. history.forward()
let btn = document.querySelector('button:first-child')
btn.addEventListener('click', function () {
// history.forward()
history.go(1)
})
// 2. history.back()
let btn1 = btn.nextElementSibling
btn1.addEventListener('click', function () {
// history.back()
history.go(-1)
})

4. 本地存储

  1. 随着互联网的快速发展,基于网页的应用越来越普遍,同时也变的越来越复杂,为了满足各种各样的需求,会经常性在 本地存储大量的数据,HTML5规范提出了相关解决方案
  2. 数据存储在用户浏览器中
  3. 设置、读取方便、甚至页面刷新不丢失数据
  4. 容量较大,sessionStorage和localStorage约 5M 左右

1. localStorage

  1. 生命周期永久生效,除非手动删除 否则关闭页面也会存在
  2. 可以多窗口 (页面) 共享 (同一浏览器可以共享)
  3. 以键值对的形式存储使用
1
2
3
4
5
6
// 1. 存储数据 localStorage.setItem('键', '值')
localStorage.setItem('name', 'csy')
// 2. 获取数据 getItem('键')
console.log(localStorage.getItem('name'))
// 3. 删除数据 removeItem('值')
localStorage.removeItem('name')

2. 存储复杂数据类型存储

本地只能存储字符串,无法存储复杂数据类型.需要将复杂数据类型转换成JSON字符串,在存储到本地

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// 存储复杂数据类型 引用数据类型
let obj = {
uanme: '小城',
age: 18,
sex: '男'
}
// JSON 格式 属性和值 双引号包含
let obj1 = {
"uanme": "小城",
"age": "18",
"sex": "男"
}
1. JSON.stringify(复杂数据类型)
2. 将复杂数据转换成JSON字符串 存储 本地存储中
3. localStorage.setItem('obj', obj) 是对象 但不知道什么名
4. 复杂数据类型转换为 json字符串 进行存储
console.log(localStorage.getItem('obj', JSON.stringify(obj)))
localStorage.setItem('obj', JSON.stringify(obj))

1. JSON.parse(JSON字符串)
2.JSON字符串转换成对象 取出 时候使用
3. 取数据 将 json字符串 转换为 对象
console.log(JSON.parse(localStorage.getItem('obj')))

3. sessionStorage(了解)

  1. 生命周期为关闭浏览器窗口
  2. 在同一个窗口(页面)下数据可以共享
  3. 以键值对的形式存储使用
  4. 用法跟localStorage 基本相同
1
2
// 生命周期为关闭浏览器窗口 (了解)
sessionStorage.setItem('uname', 'csy')

5. 自定义属性

  1. 固有属性: 标签天生自带的属性 比如class id title等, 可以直接使用点语法操作
  2. 由程序员自己添加的属性,在DOM对象中找不到, 无法使用点语法操作,必须使用专门的API
  • getAttribute(‘属性名’) // 获取自定义属性
  • setAttribute(‘属性名’, ‘属性值’) // 设置自定义属性
  • removeAttribute(‘属性名’) // 删除自定义属性
1
2
3
4
5
6
7
8
9
10
// 自带的属性id: 直接用点语法操作
// 由程序员自己添加属性 在DOM对象中找不到 无法使用点语法操作 须使用专门API
<div class="box" data-id="1" data-id1="2"></div>
let num1 = document.querySelector('.box')
// 1. 设置自定义属性
num1.setAttribute('myid', 10)
// 2. 获取自定义属性
console.log(num1.getAttribute('myid'))
// 3. 删除自定义属性
num1.removeAttribute('myid')

data-自定义属性:

  1. 传统的自定义属性没有专门的定义规则,开发者随意定值,不够规范,所以在html5中推出来了专门的data-自定义属性 在 标签上一律以data-开头
  2. 在DOM对象上一律以dataset对象方式获取
1
2
3
4
// dataset对象 不能随意定值 需data-id规范 取值是数组
<div class="box" data-id="1" data-id1="2"></div>
console.log(num1.dataset.id)
console.log(num1.dataset)

5. swiper 插件

  1. 插件: 就是别人写好的一些代码,我们只需要复制对应的代码,就可以直接实现对应的效果
  2. 熟悉官网,了解这个插件可以完成什么需求 https://www.swiper.com.cn
  3. 看在线演示,找到符合自己需求的demo https://www.swiper.com.cn/demo/index.html
  4. 查看基本使用流程 https://www.swiper.com.cn/usage/index.html
  5. 查看APi文档,去配置自己的插件 https://www.swiper.com.cn/api/index.html
  6. 注意: 多个swiper同时使用的时候, 类名需要注意区分
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
var swiper = new Swiper(".Swiper", {
slidesPerView: 1, // 等分播放
spaceBetween: 0, // 背景过渡
loop: true, // 是否循环
pagination: { // 小圆点显示/隐藏
el: ".swiper-pagination",
clickable: true, // 小圆点是否能点
},
navigation: { // 左右按钮
nextEl: ".swiper-button-next",
prevEl: ".swiper-button-prev",
},
autoplay: { // 自动切换
delay: 400, // 间隔时间
stopOnLastSlide: false, // 到最后一个停止切换 loop模式下无效
disableOnInteraction: false, // 拖动/点击后 停止自动切换
},
keyboard : true, // 键盘左右键控制
})

6. 综合案例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
需求①:读取本地存储数据(封装函数)
如果本地存储有数据,则返回 JSON.parse() 之后的对象
如果本地存储没有数据,则默认写入三条数据,注意存储的利用JSON.stringify() 存 储JSON 格式的数据
需求②:渲染模块
先读取本地存储数据,然后渲染
需求③:添加模块
注意,先取的最新的本地存储数据,然后追加
新增了数据,要把新数据存储到本地存储别,忘记转换
需求④:删除模块
注意,先取的最新的本地存储数据,然后追加
新增了数据,要把新数据存储到本地存储别忘记转换
<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>
</tbody>
</table>
<script>
// 1. 读取本地存储数据 封装函数
function fn1() {
let num1 = localStorage.getItem('data')
if (num1) {
// 如果本地存储有数据 则返回 JSON.parse 对象
return JSON.parse(num1)
} else {
// 如果没有则默认写入三条数据 利用stringify 存储
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('data', JSON.stringify(arr))
}
}
fn1()

let tbody = document.querySelector('tbody')
let btn = 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 fn() {
// 2. 先读取本地存储数据 再渲染
let arr = fn1()
tbody.innerHTML = ''
for (let num1 = 0; num1 < arr.length; num1++) {
let tr = document.createElement('tr')
tr.innerHTML = `
<tr>
<td>${arr[num1].stuid}</td>
<td>${arr[num1].uname}</td>
<td>${arr[num1].age}</td>
<td>${arr[num1].gender}</td>
<td>${arr[num1].salary}</td>
<td>${arr[num1].city}</td>
<td><a href="javascript:" id="${num1}">删除</a></td>
</tr>`
tbody.appendChild(tr)
uname.value = age.value = salary.value = ''
gender.value = '男'
city.value = '北京'
}
}
fn()

btn.addEventListener('click', function () {
// 3. 先读取本地存储数据 再渲染
let arr = fn1()
arr.push({
stuid: arr[arr.length - 1].stuid + 1,
uname: uname.value,
age: age.value,
gender: gender.value,
salary: salary.value,
city: city.value
})
// 4. 存储到本地
localStorage.setItem('data', JSON.stringify(arr))
fn()
})

tbody.addEventListener('click', function (e) {
// 5. 先读取本地数据 再渲染
let arr = fn1()
if (e.target.tagName == 'A') {
// 7. 第一条数据不能删除 添加判断
if (e.target.id == 0) {
return alert('此条数据不能被删除')
}
arr.splice(e.target.id, 1)
// 6. 存储到本地
localStorage.setItem('data', JSON.stringify(arr))
}
fn()
})
</script>
</body>

本节单词:

  1. localStorage

  2. setItem

  3. getItem

  4. stringify

  5. parse

  6. removeItem

  7. setTimeout

  8. location

  9. href

  10. search

  11. hash

  12. reload

  13. setAttribute

  14. getAttribute

  15. removeAttribute

  16. dataset

  17. histroy

  18. forward

  19. back

  20. go

  21. json

  22. window

  23. navigator

  24. sessionStorage

  25. Browser Object Model