导航守卫
全局导航守卫
全局钩子
// client/index.js
router.beforeEach((to, from, next) => { // 跳转前
console.log('before each invoked')
next() // next 必须执行,才能跳转
})
router.beforeResolve((to, from, next) => {
console.log('before resolve invoked')
next()
})
router.afterEach((to, from) => { // 跳转后,不需要 next
console.log('after each invoked')
})
复制代码
beforeEach
进行数据校验,比如验证页面,用户需要登录后才能显示,设置跳转到 login 页面
// client/index.js
router.beforeResolve((to, from, next) => {
console.log('before resolve invoked')
if (to.fullPath === '/app') {
next('/login') // 或者 next({path: '/login})
} else {
next()
}
})
复制代码
路由配置中增加钩子
beforeEnter 调用顺序是在 beforeEach 和 beforeResolve 之间。
// client/config/routes.js
export default [
{
path: '/app',
component: Todo,
beforeEnter (to, from, next) {
console.log(' app route before enter')
next()
}
}
]
复制代码
组件内部增加钩子
// todo.vue
export default {
beforeRouteEnter (to, from, next) {
console.log('todo before enter')
next()
},
beforeRouteUpdate (to, from, next) {
console.log('todo update enter')
next()
},
beforeRouteLeave (to, from, next) {
console.log('todo leave enter')
next()
},
复制代码
点击跳转 login 时
控制台
todo leave enter 组件被离开
before each invoked 新路由进入之前
before resolve invoked
after each invoked
复制代码
点击跳转 app 时
before each invoked
app route before enter 路由配置的 beforeEnter
todo before enter 组件内的 beforeEnter
before resolve invoked 而beforeResolve 要等全局的 beforeEach、路由配置的 beforeEnter、组件内都触发才出发
after each invoked
复制代码
同一个组件在不同路由下面显示的情况下 beforeRouteUpdate 才会触发
例如**路由传参的情况下,切换路由,组件会进行复用。**如果不这样做,需要通过 watch 监听 id。
// routes.js
{
path: '/app/:id',
component: Todo
},
复制代码
// app.vue
<template>
<div id="app">
<div id="cover"></div>
<router-link to="/app/123">app123</router-link>
<router-link to="/app/456">app456</router-link>
<router-link to="/login">login</router-link>
</div>
</template>
复制代码
// todo.vue
beforeRouteEnter (to, from, next) {
console.log('todo before enter', this)
next(vm => {
console.log('after enter vm.id is ', vm.id)
})
},
beforeRouteUpdate (to, from, next) {
console.log('todo update enter')
next()
},
beforeRouteLeave (to, from, next) {
console.log('todo leave enter')
if (global.confirm('are you sure?')) {
next()
} else {
}
},
复制代码
路由钩子在组件内部的应用
beforeRouteEnter 和 beforeRouteUpdate 获取数据,当我们进入页面,数据已经渲染好了
beforeRouteEnter (to, from, next) {
console.log('todo before enter', this)
next(vm => {
console.log('todo enter vm.id is ', vm.id)
})
},
复制代码
beforeRouteLeave 弹出确认框,是否离开
beforeRouteLeave (to, from, next) {
console.log('todo leave enter')
if (global.confirm('are you sure?')) {
next()
} else {
}
},
复制代码
关于 beforeRouteUpdate
路由参数不同,组件相同时,生命周期是不会触发,导致数据不更新,应该使用 beforeRouteUpdate 或者 watch
命名视图
不同的 router-view 显示不同的组件
// client/app.vue
<template>
<div id="app">
<transition name="fade">
<router-view />
</transition>
<router-view name="a"/>
</div>
</template>
复制代码
// client/config/routes.js
export default [
{
path: '/app',
components: {
default: Todo,
a: Login
}
},
{
path: '/login',
components: {
default: Login,
a: Todo
}
}
]
复制代码
常见的三栏布局,菜单切换,可以用这种方式,当然传统的 layout 也可以实现。
异步路由(异步加载组件)
当路由非常多时,通过 webpack 一次性打包所有代码,导致 js 文件非常大,初始加载时间非常长。
异步路由:对于不同的路由,只加载对应代码和项目核心代码;而对应页面的代码,访问时再加载。
使用
使用异步路由,只需在对应组件使用 import 引入对应组件即可,这样当我们访问路由时,才会加载。
// import Todo from '../views/todo/todo.vue'
// import Login from '../views/login/login.vue'
export default [
{
path: '/app/:id',
props: 'true',
component: () => import('../views/todo/todo.vue')
}
},
{
path: '/login',
component: () => import('../views/login/login.vue')
}
]
复制代码
安装 babel 插件
程序不支持直接在 component 部分写 import,需要安装 babel 插件。
npm i babel-plugin-syntax-dynamic-import -D
// .babelrc
{
"presets": [
"env"
],
"plugins": [
"transform-vue-jsx",
"syntax-dynamic-import" // 添加配置
]
}
复制代码
注意
核心代码中不要使用异步加载的组件,这样我们切换路由会没有效果。