一.前端路由定义
路由可以简单理解为一个url地址,这个地址映射到服务端可能是一个文件读取操作、一个数据库查询或者一次数据处理;而对应于前端就是一次dom操作,卸载或隐藏掉一些dom节点,展示另外一些。
二.前端路由的实现
前端路由分为hash路由和history路由。
早期前端路由都是基于hash路由实现的,所谓hash路由就是url中#之后的部分,如:https://www.word.com#search
location.hash有以下特点:
1. url中的hash部分是前端状态,hash值变化不会给服务端发送消息,只是前端状态变化。
2. location.hash变化会引起浏览器的浏览记录中插入一条新的记录,这样就可以使用浏览器的前进/后退按键来改变location.hash。
3. 可以通过监听hashchange事件监听到location.hash的变化,这样就可以在hash变化是做出相应操作。
以下先实现一个hash路由和history路由的基类:
class BaseRoute {
constructor(list) {
this.list = list;
}
render(state) {
let ele = this.list.find(item => item.path === state);
ele = ele ? ele ? this.list.find(item => item.path === '*');
ELEMENT.innerText = ele.component;
}
以下补充hash路由的实现:
class HashRoute extends BaseRoute {
constructor(list) {
super(list);
this.handler();
window.addEventListener('hashchange', this.handler.bind(this));
}
getState() {
let hash = location.hash;
return hash ? hash.slice(1) : '/';
}
handler() {
this.render(this.getState());
}
push(path) {
window.location.hash = path;
}
getUrl(path) {
const href = window.location.href;
const i = href.indexOf('#');
const base = i >= 0 ? href.slice(0, i) : href;
return base +'#'+ path;
}
replace(path) {
window.location.replace(this.getUrl(path));
}
go(n) {
window.history.go(n);
}
}
在html5之后,浏览器提供了新的History api来实现url的改变,pushState 和 replaceState 。
pushState 和 replaceState 可以实现不刷新页面而改变页面url, pushState实现向浏览历史中插入一条记录,replaceState实现将当前的浏览历史替换成新的。
可以通过监听popState实现监听路由变化,但pushState和replaceState不会引起popState事件触发。
故在使用pushState和replaceState时需要主动调用响应函数。
一下为history路由的实现:
class HistoryRoute extends BaseRoute {
constructor(list) {
super(list);
this.handler();
window.addEventListenter('popstate', this.handler.bind(this));
}
// 渲染页面
handler() {
this.render(this.getState());
}
// 获取 url
getState() {
const path = window.location.pathname;
return path ? path : '/';
}
// push 页面
push(path) {
history.pushState(null, null, path);
this.handler();
}
// replace 页面
replace(path) {
history.replaceState(null, null, path);
this.handler();
}
// 前进 or 后退浏览历史
go(n) {
window.history.go(n);
}
}
注意: history路由需要服务端接入层(ngix)配合修改,将发送给服务端的前端路由都代理到webapp的js文件上。
location /test/mywebapp { autoindex on; index index.html; try_files $uri /test/mywebapp/index.html; }
三.前端路由库分析
现较流行的前端路由库history对外提供三种路由模式BrowserHistory、HashHistory 和 MemoryHistory,其中BrowserHistory、HashHistory分别对应上文的history路由和hash路由,而MemoryHistory是针对react-native的内存路由。具体代码较简单,只是在上面的基本路由思想的基础上加入了block,在路由发生变化时,加入block可以阻塞路由变化,待阻塞解除后再执行路由变化,可以将一些退出挽留等业务逻辑放在此处。
react-router库是一个基于react的组件库,提供了router、routes、route三个react组件,实现的基本功能是1.基于路由实现按照路由匹配渲染功能,2.向子组件提供history、navigate等状态和方法,子组件需要使用包中提供能hooks来自行取用。
react-router-dom是基于history和react-router两个库的,为web使用的前端路由组件库,对外提供 BrowserRouter和 HashRouter两个路由组件。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。