1.首先安装 vue-router 依赖
npm install vue-router
2.在 main.js 文件中,引入 router,挂载到根节点上
import router from './router'
new Vue({
router,
store,
render: h => h(Febs)
}).$mount('#app')
3.如何在 router 文件中做路由拦截呢?
const whiteList = ['/login'] // 定义白名单
// 全局前置守卫
router.beforeEach((to, from, next) => {
if (whiteList.indexOf(to.path) !== -1) {
// 清除数据
}
if (!userInfo && to.path !== '/login') {
next('/login')
} else {
next()
}
}
4.如果我们的登录不是一个单独的路由,而是一个登录弹框呢?那对于未登录的用户,我们将禁止用户页面跳转,并且弹出登录弹框,用于提示用户需要登录才能操作。
const authPages = ['/order'] // 需要登录的路由
router.beforeEach((to, from, next) => {
// 判断需要登录的路由 防止通过直接改变 url 进入相应页面
if (authPages.includes(to.path) && !store.state.user.userInfo.userId) {
store.commit('setLoginVisible', true) // 打开登录
next({ path: from.path || '/' }) // 将路由重置为 from.path
return
}
next()
})
5.那我们如何全局调用登录弹框呢?首先主体架构下,引入登录组件。
export default {
computed: {
...mapState({
loginVisible: state => state.user.loginVisible,
})
},
}
使用 Vuex 全局存储【登录框】数据状态。
const user = {
state: {
loginVisible: false, // 登录弹窗显示
},
mutations: {
setLoginVisible: (state, loginVisible) => {
state.loginVisible = loginVisible
},
}
}
export default user
Login 子组件中,通过 el-dialog 组件中 visible 属性来决定是否显示登录弹框信息。
.....
除了上述的路由拦截方法之外,当然我们也可以在路由跳转时进行判断是否登录。
goToModule (item) {
if (this.$utils.checkLogin()) {
this.$router.push({ path: item.url })
}
},
// 检查当前是否登录
checkLogin (openLoginDialog = true) {
if (!store.state.user.userInfo.userId && openLoginDialog) {
store.commit('setLoginVisible', true) // 未登录是打开登录弹窗
}
return !!store.state.user.userInfo.userId
},
补充:Vue-router 路由介绍
vue-router
提供的导航守卫注意用来通过跳转或取消的方式守卫导航。有多种机会植入路由导航过程中:全局的,单个路由独享的,或者组件级的。你可以通过观察 $route
对象来应对这些变化,或使用 beforeRouteUpdate
的组件内守卫。
使用 router.beforeEach 注册一个全局前置守卫。当一个导航栏触发时,全局前置守卫按照创建顺序调用。守卫是异步解析执行,此时导航在所有守卫 resolve 完之前一直处于等待中。
const router = new VueRouter({ ... })
router.beforeEach((to, from, next) => {
if (to.name !== 'Login' && !isAuthenticated) {
next({ name: 'Login' })
} else {
next()
}
})
router.afterEach((to, from) => {
// ...
})
to: Route
: 即将要进入的目标 路由对象
from: Route
: 当前导航正要离开的路由
next: Function
: 一定要调用该方法来 resolve 这个钩子。执行效果依赖 next
方法的调用参数。
next()
: 进行管道中的下一个钩子。如果全部钩子执行完了,则导航的状态就是 confirmed (确认的)。
next(false)
: 中断当前的导航。如果浏览器的 URL 改变了 (可能是用户手动或者浏览器后退按钮),那么 URL 地址会重置到 from
路由对应的地址。
next('/')
或者 next({ path: '/' })
: 跳转到一个不同的地址。当前的导航被中断,然后进行一个新的导航。你可以向 next
传递任意位置对象,且允许设置诸如 replace: true
、name: 'home'
之类的选项以及任何用在 router-link
的 to
prop 或 router.push
中的选项。
next(error)
: (2.4.0+) 如果传入 next
的参数是一个 Error
实例,则导航会被终止且该错误会被传递给 router.onError()
注册过的回调。
待补充
你可以在路由组件内直接定义以下路由导航守卫:beforeRouteEnter、beforeRouteUpdate、beforeRouteLeave。
beforeRouteEnter: 在渲染该组件的对应路由被 confirm 前调用,不能获取组件实例 this,因为当前守卫执行前,组件实例还没被创建。
beforeRouteUpdate:在当前路由改变,但该组件被复用时调用。
export default {
......
// 路由跳回来前判断是否需要刷新列表
beforeRouteUpdate (to, from, next) {
if (to.meta.needRefresh) {
this.$refs.tableList.getList()
delete to.meta.needRefresh
}
next()
},
}
这里我们可以看到根据 to.meta.needRefresh 来刷新列表,这里需要 router 配合。
export default [
{
path: 'registerMaintain',
name: 'registerMaintain',
meta: {
needRefresh: true,
},
component: RegisterMaintain,
children: [
......
]
},
]
beforeRouteLeave:导航离开该组件的对应路由时调用,可以访问组件实例 this。
// 增改详组件离开前判断是否需要给主页面组件加刷新标识
beforeRouteLeave (to, from, next) {
this.needRefresh && (to.meta.needRefresh = true)
next()
},
点击页面进行路由切换时,将页面中的滚动条滚动到页面顶部。这个时候我们就要介绍 Vue-router 中的 afterEach 钩子函数。
router.afterEach(() => {
// 切换路由页面回归顶部(滚动的是内容层,加定时器,不然路由立刻切换的时候无法获取dom节点)
setTimeout(() => {
const dom = document.querySelector('.framework-wrapper')
// IE下没有scrollTo属性,要做兼容判断
if (dom && dom.scrollTo) {
document.querySelector('.framework-wrapper').scrollTo(0, 0)
} else {
document.querySelector('.framework-wrapper').scrollTop = 0
}
}, 0)
})
当然我们也可以将其封装为一个工具方法来调用。