路由原理
1、概念:
通过改变 URL,在不重新请求页面的情况下,更新页面视图。
2、实现方式:
更新视图但不重新请求页面,是前端路由原理的核心之一,目前在浏览器环境中这一功能的实现主要有2种方式:
- Hash — 利用 URL 中的hash("#");监听 url 中 hash 的变化,然后渲染不同的内容,这种路由不向服务器发送请求,不需要服务端的支持;
- 利用 History interface 在HTML5中新增的方法,监听 url 中的路径变化,需要客户端和服务端共同的支持;
Vue 中,它是通过 mode 这一参数控制路由的实现模式:
const router=new VueRouter({
mode:'history',
routes:[...]
})
mode 参数:
1.默认 hash
2. history。如果浏览器不支持 history 新特性,则采用 hash
3. 如果不在浏览器环境下,就采用 abstract(Node环境下)
2.1 hash模式
路由的hash模式其实是利用了window可以监听onhashchange事件,也就是说你的url中的值(#后面的值)如果有变化,前端是可以做到监听并做一些响应,这么一来,即使前端并没有发起http请求他也能够找到对应页面的代码块进行按需加载,window.location.hash获取hash值
2.2 history模式
监听url变化的事件popstate,从 HTML5开始,History interface 提供了2个新的方法:pushState()、replaceState() 使得我们可以对浏览器历史记录栈进行修改 但是不会触发popstate事件,可以用window.dispatchEvent添加事件
history.pushState()将新路由添加到浏览器访问历史的栈顶
history.replaceState()替换掉当前的路由
2.3 hash与history的区别
| hash | history | |
|---|---|---|
| url显示 | url带#号 | 无# |
| 回车刷新 | 可以加载到hash值对应页面 | 一般就是404掉了 |
| 支持版本 | 支持低版本浏览器和IE浏览器 | HTML5新推出的API(部分版本不支持) |
2.4 话术总结及使用场景
hash模式url里面永远带着#号,我们在开发当中默认使用这个模式。那么什么时候要用history模式呢?如果用户考虑url的规范那么就需要使用history模式,因为history模式没有#号,是个正常的url适合推广宣传。当然其功能也有区别,比如我们在开发app的时候有分享页面,那么这个分享出去的页面就是用vue或是react做的,咱们把这个页面分享到第三方的app里,有的app里面url是不允许带有#号的,所以要将#号去除那么就要使用history模式,但是使用history模式还有一个问题就是,在访问二级页面的时候,做刷新操作,会出现404错误,那么就需要和后端人配合让他配置一下apache或是nginx的url重定向,重定向到你的首页路由上就ok啦。
路由守卫
1、全局守卫
无论访问哪一个路径,都会触发全局的钩子函数,位置是调用router的方法 router/index.js
router.beforeEach((to,from,next)=>{}) 进入之前触发
router.afterEach((to,from)=>{}) 进入之后触发(后置钩子函数,不需要next)
回调函数中的参数:
to:即将要进入的目标 路由对象from:当前导航正要离开的路由next:表示下一步要干啥,next(’/addGoods’)就表示下一步,调到路由 /addGoods
//路由配置
{
path: '/about',
name: "about",
meta: {auth: true}, //需要认证
component: ()=>import(/*webpackChunkName: "about"*/ "./views/About.vue")
}
//全局守卫
router.beforeEach((to,from,next)=>{
//要访问/about 且未登录需要去登录
if(to.meta.auth && !window.isLogin){
if(window.confirm('请登录')){ //用户操作了登录
window.isLogin = true;
next(); //登录成功,继续
}else{
next('/'); //放弃登录,回首页
}
}else{
next(); //不需登录,继续
}
})
2、组件内守卫
放在需要守卫的组件里,跟data和methods同级
beforeRouteEnter((to,from,next)=>{}) 进入路由前调用
beforeRouteEnter(to,from,next){
alert(this.data); //此时组件还未实例化 弹出为 unedfind
next(vm =>{
alert(vm); //vm相当于this
})
}
beforeRouteUpdate((to,from,next)=>{}) 该组件被复用时调用
beforeRouteUpdate (to, from, next) {
// 当前路由改变,但是该组件被复用时调用
// 举例来说,对于一个带有动态参数的路径 /a/:id,在 /a/1 和 /a/2 之间跳转的时候
// 由于会渲染同样的 a组件,因此组件实例会被复用。而这个钩子就会在这个情况下被调用。
}
beforeRouteLeave((to,from,next)=>{})导航离开该组件的对应路由时调用
beforeRouteLeave(to,from,next){
if(confirm("确定离开吗?") == true){
next()
}else{
next(false);
}
}
3、路由独享守卫
用法与全局守卫一致。只是,将其写进其中一个路由对象中,只在这个路由下起作用。
beforeEnter((to,from,next)=>{})

路由传参
1、页面刷新数据不会丢失
<div class="examine" @click="insurance(id)">查看详情</div>
//事件
methods:{
insurance(id) {
//直接调用$router.push 实现携带参数的跳转
this.$router.push({
path: `/particulars/${id}`,
})
}
需要对应路由配置如下:
{
path: '/particulars/:id',
name: 'particulars',
component: particulars
}
另外页面获取参数如下:
this.$route.params.id
2、页面刷新数据会丢失
通过路由属性中的name来确定匹配的路由,通过params来传递参数。
methods:{
insurance(id) {
this.$router.push({
name: 'particulars',
params: {
id: id
}
})
}
对应路由配置: 注意这里不能使用:/id来传递参数了,因为组件中,已经使用params来携带参数了。
{
path: '/particulars',
name: 'particulars',
component: particulars
}
子组件中:获取参数
this.$route.params.id
3、使用path来匹配路由,通过query来传递参数
methods:{
insurance(id) {
this.$router.push({
path: '/particulars',
query: {
id: id
}
})
}
对应路由配置:
{
path: '/particulars',
name: 'particulars',
component: particulars
}
对应子组件: 获取参数
this.$route.query.id
总结:params传参和query传参的区别
(1) query可以使用name和path,而params只能使用name
(2) 使用params传参刷新后不会保存,而query传参刷新后可以保存
(3) params在地址栏中不会显示,query会显示
(4) params可以和动态路由一起使用,query不可以
3785




被折叠的 条评论
为什么被折叠?



