在单页面应用如日中天发展的过程中,备受关注的少了前端路由。
而且还经常会被xxx面试官问到,什么是前端路由,它的原理的是什么,它是怎么实现,跳转不刷新页面的...
一大堆为什么,问你头都大
前言
今天主要讲的是:
- 原生js实现hashRouter
- 原生js实现historyRouter
- react-router-dom的BrowserRouter
- react-router-dom的HistoryRouter
四种路由的实现原理。
环境问题
因为等一下要用到h5新增的pushState() 方法,因为这玩(diao)意(mao)太矫情了,不支持在本地的file协议运行,不然就会报以下错误
只可以在http(s)协议 运行,这个坑本渣也是踩了很久,踩怀疑自己的性别。
既然用file协议 不行那就只能用webpack搭个简陋坏境了,你也可以用阿帕奇,tomcat...啊狗啊猫之类的东西代理。
本渣用的是webpack环境,也方便等下讲解react-router-dom的两个路由的原理。环境的配置,我简单的贴一下,这里不讲。
代码语言:javascript复制npm i webpack webpack-cli babel-loader @babel-core @babel/preset-env html-webpack-plugin webpack-dev-server -D
webpack.config.js
代码语言:javascript复制const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
entry:path.resolve(__dirname,'./index.js'),
output:{
filename:'[name].[hash:6].js',
path:path.resolve(__dirname,'../dist')
},
module:{
rules:[
{
test:/.js$/,
exclude:/node_module/,
use:[
{
loader:'babel-loader',
options:{
presets:['@babel/preset-env']
}
}
]
}
]
},
plugins:[
new HtmlWebpackPlugin({
template:path.resolve(__dirname,'./public/index.html'),
filename:'index.html'
})
]
}
package.json的script添加一条命令
代码语言:txt复制 "dev":"webpack-dev-server --config ./src/webpack.config.js --open"
项目目录
运行
代码语言:txt复制npm run dev
现在所有东西都准备好了,我们可以进入主题了。
原生js实现hashRouter
html
代码语言:javascript复制<ul>
<li><a href='#/home'>home</a></li>
<li><a href='#/about'>about</a></li>
<div id="routeView"></div>
</ul>
js
代码语言:javascript复制window.addEventListener('DOMContentLoaded', onLoad)
window.addEventListener('hashchange', changeView)
let routeView = ''
function onLoad() {
routeView = document.getElementById('routeView')
changeView()
}
function changeView() {
switch (location.hash) {
case '#/home':
routeView.innerHTML = 'home'
break;
case '#/about':
routeView.innerHTML = 'about'
break;
}
}
原生js实现hashRouter主要是监听它的hashchange事件的变化,然后拿到对应的location.hash更新对应的视图
原生js实现historyRouter
html
代码语言:javascript复制<ul>
<li><a href='/home'>home</a></li>
<li><a href='/about'>about</a></li>
<div id="routeView"></div>
</ul>
historyRoute
代码语言:javascript复制window.addEventListener('DOMContentLoaded', onLoad)
window.addEventListener('popstate', changeView)
let routeView = ''
function onLoad() {
routeView = document.getElementById('routeView')
changeView()
let event = document.getElementsByTagName('ul')[0]
event.addEventListener('click', (e) => {
if(e.target.nodeName === 'A'){
e.preventDefault()
history.pushState(null, "", e.target.getAttribute('href'))
changeView()
}
})
}
function changeView() {
switch (location.pathname) {
case '/home':
routeView.innerHTML = 'home'
break;
case '/about':
routeView.innerHTML = 'about'
break;
}
}
能够实现history路由跳转不刷新页面得益与H5提供的pushState(),replaceState()等方法,这些方法都是也可以改变路由状态(路径),但不作页面跳转,我们可以通过location.pathname来显示对应的视图
react-router-dom
react-router-dom是react的路由,它帮助我们在项目中实现单页面应用,它提供给我们两种路由一种基于hash段实现的HashRouter,一种基于H5Api实现的BrowserRouter。
下面我们来简单用一下。
如果你在用本渣以上提供给你的环境,还要配置一下,下面