Vue redirect | 路由懒加载 | 路由守卫

317 阅读5分钟

1.redirect

1.重定向到平级的路径上去

第一个对象里是配置路由path:’/'为项目的根目录,redirect重定向为渲染的路径redirect:'/index'(这里我是指向了第二个对象里的path),所以就要写第二个对象方便 redirect 找到它。

第二个对象里的配置path:’/index’是自定义的路径,component / Customers组件名称

2.重定向到子路由路径上面去

父路由(path:'/')重定向到相应的子路由路径上去了 redirect:'/index'

3.重定向的地址不需要接收参数

const routes = [
    { path: '/', redirect: '/index'},
    { path: '/index', component: index }
]

把"/"重定向到"/index"

4.重定向的地址需要接收参数然而没有传参

不会改变地址,页面不会报错但是也不会显示内容

5.重定向的地址需要接收参数并且传参

{
  path:'/goParams/:newsId(\d+)/:newsTitle',
  redirect:'/params/:newsId(\d+)/:newsTitle'
}

重定向改变了路径,此时路径并不是goParams/1993/yq love znf而是params/1993/yq love znf

2.路由懒加载

export const constantRouterMap = [
    {
    path: '/login',
    meta: { title: '登录', keepAlive: true },
    component: (resolve) => require(['@/views/login'], resolve), 
    hidden: true
    }
]

这是异步加载组件,当你访问 /login,才会加载 login.vue。

路由懒加载的一种写法

resolve 就是 promise 的 resolve 回调,组件加载成功后调用。

也可以用import

export const constantRouterMap = [
  {
    path: '/login',
    meta: { title: '登录', keepAlive: true },
    component: () => import(['@/views/login']),
    hidden: true
  }
]

vue-router中,require代替import解决vue项目首页加载时间过久的问题

vue的路由配置文件(routers.js),一般使用import引入的写法,当项目打包时路由里的所有component都会打包在一个js中,在项目刚进入首页的时候,就会加载所有的组件,所以导致首页加载较慢, 而用require会将component分别打包成不同的js,按需加载,访问此路由时才会加载这个js,所以就避免进入首页时加载内容过多。
require: 运行时调用,理论上可以运用在代码的任何地方
import:编译时调用,必须放在文件开头

3.路由守卫

在进行权限控制的时候,beforeEach函数将会接受三个参数(to, from, next),to的意思是所到的路由的信息,from的意思是跳转前路由的信息,在beforeEach中可以使用next()来控制路由的前进。

beforeEach((to, from, next) => {
	to // 要去的路由
	from // 当前路由
	next() // 放行的意思
}

其实在路由守卫中,只有next()是放行,其他的诸如:next('/logon')next(to) 或者 next({ ...to, replace: true })都不是放行,而是:中断当前导航,执行新的导航

可以这么理解: next() 是放行,但是如果next()里有参数的话,next()就像被重载一样,就有了不同的功能。

而对于上面说的中断当前导航,执行新的导航打个比方:

现在我有一个守卫,在守卫中我使用next('/logon'),肯定有同学认为是会直接跳转到/logon路由:

beforeEach((to, from, next) => {
  next('/logon')
}

但执行时需要这么看:

beforeEach((to, from, next) => {
  beforeEach(('/logon', from, next) => {
  	 beforeEach(('/logon', from, next) => {
  	 	 beforeEach(('/logon', from, next) => {
  	 	 	beforeEac...  // 一直循环下去...... , 因为我们没有使用 next() 放行
 		}
 	 }
  }
}

如果把这个守卫改一下,当我在地址栏输入/home时

beforeEach((to, from, next) => {
   if(to.path === '/home') {
   	next('/logon')
   } else {
    // 如果要去的地方不是 /home , 就放行
   	next()
   }
}

我本来要去/home路由,因此执行了第一次 beforeEach((to, from, next)

但是这个路由守卫中判断了如果要去的地方是'/home',就执行next('/logon')

所以想要访问/home可以这么看

beforeEach((to, from, next) => {
   beforeEach(('/logon', from, next) => {
     next()  // 现在要去的地方不是 /home , 因此放行
   }
}

注意:重点就在这,next('/logon')不是说直接去/logon路由,而是中断(不是CPU的那个中断!VUE中的中断就是此时不会执行router.afterEach(() => {})这一次路由守卫的操作,又进入一次路由守卫,就像嵌套一样,一层路由守卫,然后又是一层路由守卫,此时路由守卫进入到第二层时,to.path已经不是/home了,这个时候才执行next()放行操作。

1.next()

next():进行管道中的下一个钩子。如果全部钩子执行完了,则导航的状态就是confirmed(确认的)。

2.next(false)

next(false)中断当前的导航。如果浏览器的 URL 改变了 (可能是用户手动或者浏览器后退按钮),那么 URL 地址会重置到from路由对应的地址。

3.next(error)

next( error ):如果传入next的参数是一个Error实例,则导航会被终止且该错误会被传递给router.onError()注册过的回调。

在使用next()的时候如果在括号中配置了另外的路由地址,则表示为中断之前的beforeEach()的操作,并且再嵌套一层beforeEach(),并且将to的路由地址改为之前配置的路由地址。

beforeEach((to, from, next) => {
   if(to.path === '/home') {
    next('/logon')
   } else {
    // 如果要去的地方不是 /home , 就放行
    next()
   }
}
//等价于
beforeEach((to, from, next) => {
   beforeEach(('/logon', from, next) => {
     next()  // 现在要去的地方不是 /home , 因此放行
   }
}

在使用动态添加路由addRoutes()会遇到下面的情况:在addRoutes()之后第一次访问被添加的路由会白屏,这是因为刚刚addRoutes()就立刻访问被添加的路由,然而此时addRoutes()没有执行结束,因而找不到刚刚被添加的路由导致白屏。因此需要从新访问一次路由才行。

该如何解决这个问题 ?

此时就要使用next({ ...to, replace: true })来确保addRoutes()时动态添加的路由已经被完全加载上去。next({ ...to, replace: true })中的replace: true只是一个设置信息,告诉VUE本次操作后,不能通过浏览器后退按钮,返回前一个路由。

next({ ...to })的执行的时候,它会判断:如果参数to不能找到对应的路由的话,就再执行一次beforeEach((to, from, next)直到其中的next({ ...to})能找到对应的路由为止。也就是说此时addRoutes()已经完成啦,找到对应的路由之后,接下来将执行前往对应路由的beforeEach((to, from, next) ,因此需要用代码来判断这一次是否就是前往对应路由的beforeEach((to, from, next),如果是,就执行next()放行。

\