一些知识点
1、# 锚编程
在浏览器解析url的时候会忽略掉#字符后面的数据,但是仍然会将此时的url压入history的栈中。
在编写前端的时候,当一个网友的长度特别长的时候。便会在底部放置返回顶部的锚。通过锚将页面定位到相应的地方。<a>
标签通常会被用来作为一个跳转的标签。
2、history对象
官方api说明
(1) history
history对象是浏览器自带的一个全局对象。用来记录用户的浏览历史的,但是用户不能通过history获得相关的数据。
(2) history对象的属性。
- length 长度,历史记录的长度
- scrollRestoration 允许Web应用程序在历史导航上显式地设置默认滚动恢复行为。此属性可以是自动的(auto)或者手动的(manual)
- state 返回一个表示历史堆栈顶部的状态的值。这是一种可以不必等待popstate 事件而查看状态而的方
(3) history对象的方法 - back() 返回上一页 等价于go(-1)
- forward() 前往下一页 等价于go(1)
- go(n) 相对于当前页面的跳转。n为正往前,n为负往后。0 为当前。空值和非数值型和超出栈长都不会报错。也不会做任何的事件处理
- pushState() 按指定的名称和URL(如果提供该参数)将数据push进会话历史栈,数据被DOM进行不透明处理
- replaceState() 按指定的数据,名称和URL(如果提供该参数),更新历史栈上最新的入口
(3) 事件监听
window.onpopstate用来监听url改变事件的。但是对pushState并不起作用。3、自主实现一个渲染系统,并且路由可控
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
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
<html>
<head>
<meta charset="utf-8" />
<title></title>
<style>
body{
text-align: center;
}
h1 {
font-size: 50px;
}
#app {
font-size: 40px;
height: 300px;
background-color: lightgray;
}
#operation {
font-size: 36px;
}
input {
height: 36px;
font-size: 32px;
}
button {
height: 36px;
}
</style>
</head>
<body>
<h1>模拟路由</h1>
<h2 id="showParams"></h2>
<!--渲染主要区域-->
<div id="app">
</div>
<!--操作栏-->
<div id="operation">
<a href="#login">登陆</a>
<a href="#main">首页</a>
<a href="#fadfagaseawg">404</a>
<br />
路由地址: <input type="text" id="routerTarget" width="100"/>
<br />
路由参数:<input type="text" id="routerParams" width="100"/>
<button onclick="jump()">跳转</button>
</div>
<!--锚编程-->
<div style="height: 10000px;"></div>
<a href="#app">返回顶部</a>
</body>
<script>
/**
* 浏览器路由监听器
* @param {Object} event
*/
function routerChangeListener(event) {
console.log(event);
console.log(location.href);
console.log(location.hash);
if(event.state){
// 路由有参数 将路由参数显示在页面
const params = JSON.stringify(event.state.params);
console.log(`路由传参:${params}`);
document.getElementById("showParams").innerHTML = params;
}
// 获得路由
let route = location.hash.split("#")[1];
Route(route)
}
/**
* main的组件
*/
const mainComponet = `
`
/**
* 路由配置文件
*/
const router =
[
{
path: 'login',
},
{
path: 'main',
component: mainComponet
},
{
path: '404',
component: '404 NO FOUND'
}
]
/**
* 渲染的函数
* @param {Object} el 要渲染到的dom标签
* @param {Object} value 渲染的值
*/
function render(el,value){
let element = document.getElementById(el);
element.innerHTML= value;
}
/**
* 路由函数,用来寻找对应组件来渲染
* @param {Object} hash
*/
function Route(hash){
/**
* 寻找路由
*/
for(routerItem of router){
// console.log(routerItem);
if(routerItem.path === hash){
// 调用render 来渲染数据
render('app',routerItem.component);
return;
}
}
// 渲染404
let noFoundPage = router[router.length-1];
// console.log(noFoundPage);
render('app',noFoundPage.component);
}
/**
* Router对象
* 核心函数: push
* 模拟: this.$router.push()
*/
function Router() {
/**
* this.$router.push()
*/
this.push = function push(url,params) {
// console.log('push')
window.history.pushState({params:params},'push',`#${url}`);
// 填充后后退刷新
window.history.pushState({},'null','#');
history.back();
}
}
/**
* 全局路由对象
*/
var $router = new Router();
/**
* 业务逻辑
*/
/**
* 按钮单击 跳转到对应的路由
* @param {Object} event
*/
function jump(event) {
console.log('跳转')
// 获得要跳转的路径
let target = document.getElementById("routerTarget").value;
// 获得路由的传参
let params = document.getElementById("routerParams").value;
// 路由跳转类似 vue中 this.$router.push()
this.$router.push(target,params);
}
/**
* 开始运行
*/
(function(){
console.log('hello')
/**
* 给浏览器路由变化设置监听
*/
window.onpopstate = routerChangeListener;
/**
* 路由到登陆界面
*/
this.$router.push('login');
})()
</script>
</html>