# 属性
# length
- 值:当前session的history个数,新开的页面值是1
<body>
<div>
我是页面
</div>
<script>
console.log(history.length); // 1
</script>
</body>
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
# state
- history栈顶的值
入栈
- 只有【history.pushState】和 【history.replaceState】才能推入栈
<body>
<div>
<span class='jump'>
1
</span>
<span class='jump'>
2
</span>
</div>
<div id='1'>我是锚1</div>
<div id='2'>我是锚2</div>
<script>
const jumps = document.querySelectorAll('.jump');
Array.prototype.forEach.call(jumps, item => item.addEventListener('click', () => {
// 点击推入历史
history.pushState({id: item.innerText}, null)
// 输出历史对象
setTimeout(() => console.log(history.state), 1000)
}))
</script>
</body>
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
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
# scrollRestoration
- 作用:回退页面时是否回到上次离开的滚动位置
值 | 意思 |
---|---|
auto | 回到滚动位置 |
manual | 回退到顶部 |
<body>
<div>
<span class='jump'>
顶部
</span>
</div>
<div>我很长</div>
<div>我很长</div>
<div>我很长</div>
<div>我很长</div>
<div>我很长</div>
<div>我很长</div>
<div>我很长</div>
<div>我很长</div>
<div>我很长</div>
<div>我很长</div>
<div>我很长</div>
<div>我很长</div>
<div>我很长</div>
<div>我很长</div>
<div>我很长</div>
<div>我很长</div>
<div>我很长</div>
<div>我很长</div>
<div>我很长</div>
<div id='my1'>我是ID1111</div>
<div>我很长</div>
<div>我很长</div>
<div>我很长</div>
<div>我很长</div>
<div>我很长</div>
<div>我很长</div>
<div>我很长</div>
<div>我很长</div>
<div>我很长</div>
<div>我很长</div>
<div>我很长</div>
<div>我很长</div>
<div>我很长</div>
<div>我很长</div>
<div>我很长</div>
<div>我很长</div>
<div>我很长</div>
<div>我很长</div>
<div>我很长</div>
<div>我很长</div>
<div>我很长</div>
<hr>
<div id='my1'>我是底部</div>
<script>
const id1 = document.querySelector('#my1');
// 回退时【不会】回到离开时的滚动位置
// history.scrollRestoration = 'manual';
// 回退时会回到离开时的滚动位置
history.scrollRestoration = 'auto';
// 滚动 -> 推入历史栈 -> 滚动 -> 回退历史记录
new Promise(resolve => {
setTimeout(() => resolve())
})
.then(_ => {
setTimeout(() => {
console.log('滚动页面');
id1.scrollIntoView();
}, 1000);
})
.then(_ => {
setTimeout(() => {
console.log('入栈');
history.pushState({}, null);
}, 2000);
})
.then(_ => {
setTimeout(() => {
console.log('滚到顶');
const jump = document.querySelector('.jump');
jump.scrollIntoView();
}, 3000);
})
.then(_ => {
setTimeout(() => {
console.log('出栈')
history.back();
}, 4000);
})
</script>
</body>
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
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
# 方法
# pushState
- 作用:向浏览器记录添加一个状态
- 调用:history.pushState(property, title[, url])
错误避免
- 浏览器跳转操作都需要时间,所以用setTimeout间隔开取值
- 热更新多次刷新同一个带跳转的页面会堆积history栈,需要重新打开才能测试正确
<body>
<script>
console.log(history.length); // 1
console.log(history.state); // null
setTimeout(() => {
console.log('推入记录,跳转');
history.pushState({id: 0}, null, '#333');
console.log(history.length); // 2
}, 1000)
setTimeout(() => {
console.log(history.state); // {id: 0}
console.log('回退');
history.back();
}, 2000)
setTimeout(() => {
console.log(history.state); // null
}, 3000)
</script>
</body>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# replaceState
- 更新当前的history栈
<body>
<script>
console.log(history.length); // 1
console.log(history.state); // null
history.replaceState({id: 0}, null);
setTimeout(() => {
// 说明是同一个历史记录,但是存的值变了
console.log(history.length); // 1
console.log(history.state); // {id: 0}
}, 1000)
</script>
</body>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
2
3
4
5
6
7
8
9
10
11
12
13
14
# back
- 作用:回到history栈的上一个位置
- 调用:history.back()
- 在百度页面多搜索几个关键词,然后的控制台中执行:
history.back()
1
# forward
- 向前移动一页
- 在百度页面多搜索几个关键词,然后回退,然后的控制台中执行:
history.forward()
1
# go
- 向移动指定页数,-X 代表后退 X页
- 在百度页面多搜索几个关键词,然后的控制台中执行:
history.go(-2)
1
# 事件
# onpopstate
- 位置:window.onpopstate
- 触发条件:
- 浏览器按前进后退
- history.back()
- history.go()
- history.forward()
- a标签的锚点
注意
- 这个事件不遵守驼峰写法
- 【history.pushState】和【history.replaceState】不会触发这个事件
- 过一秒调用回退输出id:【1】,点锚点输出事件
<body>
<div>
<span class='top'>
顶部
</span>
</div>
<div><a href="#link1">锚点1</a></div>
<div><a href="#link2">锚点2</a></div>
<div><a href="#link3">锚点3</a></div>
<div><a href="#link4">锚点4</a></div>
<script>
window.onpopstate = function(e) {
console.log(e.state?.id || e);
}
history.pushState({id: 0}, null);
history.pushState({id: 1}, null);
history.pushState({id: 2}, null);
setTimeout(() => {
history.back();
}, 1000)
</script>
</body>
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
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
# 手写history路由
history路
- 用到知识点:
- pushState和replaceState本身不会发送网络请求,只会更改url并且推入历史记录
- 更改url后window.onpopstate事件会被触发,可以做前端路由
- 浏览器本身可以前进后退,也可以调用history.back/forward/go等控制前进后退
- 注意:
- pushState和replaceState本身不会触发onpopstate事件,go/back/forward会调用