前端路由?如何手动实现前端路由
我报名参加金石计划一期挑战——瓜分10万奖池,这是我的第三篇文章,点击查看活动详情
前端最开始是没有路由这个概念的,因为最早的时候,前端负责切图的时候,一个html文件路径对应着一个页面,是没有路由这个概念的,只有页面和路径的概念的。而随着前端的发展,前端也不再只是作为一个单单的切图仔的角色,路由这个概念也随之引入。
什么是前端路由?
说到什么是前端路由,咱们先来举个栗子吧。

然后我们点击一下沸点:
路径变为:juejin.cn/pins

这里我们可以看到的是,路径只有最后最后面一部分的路径发生了改变,前面的路径并没有发生改变。
这说明什么?这其实是个单页页面,只存在一个页面,点击进行跳转只是通过改变路径,而渲染出不同的页面效果,但是值得一提的是,页面并没有进行刷新,这里是有一个过程量的
即你在首页页面点击沸点之前和点击沸点之后,你可以看到那个页面刷新按钮是没有进行刷新的。
总结:前端路由就是描述url 和 页面ui 之间的映射关系,单向映射。
实现路由应该做到什么?
1.如何改变url却不引起页面的刷新
2.如何检测url发生了变化
实现前端路由的方式
hash
hash又被叫为哈希,须知的是改变浏览器url的hash值部分,页面是不会刷新的。
这里,我们写了两个a标签,路径分别为/home
和/about
,那么这点击这两个a标签超链接,我们的页面就会发生跳转,进入下一个页面,即多页应用。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<ul>
<li>
<a href="/home">首页</a>
</li>
<li>
<a href="/about">关于</a>
</li>
</ul>
<!-- 渲染对应的UI -->
<div id="routerView"></div>
</body>
</html>
那么,如何实现hash路由呢?
首先,我们只要把a标签的路径改为#/home
和#/about
,hash路径都要加上一个#
前缀,浏览器会自动识别这是hash路径,从而达到路径发生改变,但页面并没有进行刷新跳转,仍旧处于原本这个页面。
<body>
<ul>
<li>
<a href="#/home">首页</a>
</li>
<li>
<a href="#/about">关于</a>
</li>
</ul>
</body>
可浏览器识别了路径的hash值发生了改变,页面也并没有什么其它的东西渲染出来啊?这就是我们需要解决的第二个问题了,怎样检测监听页面url的改变,我们只需要检测到页面url的改变,且获取改变的那一段页面url,来判断那一段url应该在页面上渲染什么。
那么,怎么检测页面url发生改变呢?
window.addEventListener('hashchange',onHashChange)
JS自带一个有关于window事件的监听,第一个参数为hashchange
,即监听页面url的hash值改变,第二个参数为一个函数,这里我们为了好看一点,这里放上函数名onHashChange
。
只要页面的url里hash值部分发生改变,那么就会调用onHashChange
函数。
再通过location.hash
来获取页面改变的hash值部分在函数里面来决定应该渲染哪一部分页面。
完整代码如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<ul>
<li>
<a href="#/home">首页</a>
</li>
<li>
<a href="#/about">关于</a>
</li>
</ul>
<!-- 渲染对应的UI -->
<div id="routerView"></div>
<script>
let routerView = document.getElementById('routerView')
window.addEventListener('hashchange',onHashChange)
//控制渲染对应的ui
function onHashChange(){
switch(location.hash){
case '#/home':routerView.innerHTML='首页'
braek;
case '#/about':routerView.innerHTML='关于'
break;
default:return
}
}
</script>
</body>
</html>
效果如图:



hash实现路由非常简便,但是有一个小弊端,就是路径不美观,每一段路径都会加一个#号,而路径我们一般都是/去分割,多加一个#不太美观,所以我们通常用history方法实现路由用的更多。
history
history是HTML5提供的一个对象方法。
而我们要实现history路由之前,我们应该知道这么三种方法:
pushState
//增加url,且不会引起页面变化replaceState
//修改url 并且不会引起页面刷新的popState
//监听url变化
在用history方法之前,我们需要先监听a标签的点击事件,然后阻止a标签自带的跳转,这里我们使用preventDefault()
方法。
用a.getAttribute('href')
获取a标签里的href路径,用作于history的history.pushState(null,'',a.getAttribute('href'))
里,添加改变路径。
再调用PoPState
函数决定渲染哪一部分的函数
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<ul>
<li>
<a href="/home">首页</a>
</li>
<li>
<a href="/about">关于</a>
</li>
</ul>
<!-- 渲染对应的UI -->
<div id="routerView"></div>
<script>
let routerView = document.getElementById('routerView')
window.addEventListener('DOMContentLoaded',onLoad) //页面第一次加载就进行默认选中渲染内容
// window.addEventListener('popstate',PoPState) //浏览器的前进后退能匹配
function onLoad(){
PoPState()
let links = document.querySelectorAll('li a[href]')
links.forEach(a=>{
a.addEventListener('click',(e)=>{
e.preventDefault(); //阻止a标签的href标签
history.pushState(null,'',a.getAttribute('href'))
PoPState()
})
})
}
onLoad()
function PoPState(){
switch(location.pathname){
case '/home':
routerView.innerHTML = '<h2>home page</h2>'
return
case '/about':
routerView.innerHTML = '<h2>about page</h2>'
return
default:
return
}
}
</script>
</body>
</html>
效果如下:



总体来说,都是通过改变页面url但不刷新页面,然后判断路径来选择不同的组件来渲染页面实现路由效果。
转载自:https://juejin.cn/post/7143064688661069854