vuex-router-sync:路由状态管理,保持 vue-router 和 vuex 存储同步。
import { sync } from 'vuex-router-sync'
import router from '@/router'
import store from '@/store'
sync(store,router)
new Vue({
el: '#app',
router,
store,
components: { App },
template: ''
})
第1步:vuex模块动态注册
const moduleName = (options || {}).moduleName || 'route'
store.registerModule(moduleName, {
namespaced: true,
state: cloneRoute(router.currentRoute), // route 全部属性
mutations: {
// 改变 state 值
'ROUTE_CHANGED'(state, transition) {
store.state[moduleName] = cloneRoute(transition.to, transition.from)
}
}
})
第2步:store.watch => vueVm.$watch
watch(fn: Function, callback: Function, options?: Object): Function
响应式地侦听fn
的返回值,当值改变时调用回调函数。
fn
接收 store 的 state 作为第一个参数,其 getter 作为第二个参数。callback(newVal, oldVal)
,回调函数vm.$watch
方法的参数const storeUnwatch = store.watch(
// 监听 state[moduleName]
state => state[moduleName],
route => {
const {
fullPath
} = route
if (fullPath === currentPath) {
return
}
if (currentPath != null) {
isTimeTraveling = true
// 路由跳转
router.push(route)
}
currentPath = fullPath
}, {
sync: true
}
)
第3步:vue-router 全局后置导航钩子,钩子不会接受 next
函数也不会改变导航本身
// 监听路由变化
router.afterEach((to, from) => {
if (isTimeTraveling) {
isTimeTraveling = false
return
}
currentPath = to.fullPath
// 触发 mutation
store.commit(moduleName + '/ROUTE_CHANGED', {
to,
from
})
})
为了避免循环调用,isTimeTraveling 为true时,代表是当前组件触发的路由跳转,router.afterEach
监听到不做任何处理。
这里需要注意的点是,我们通过 @/router
和 @store
来获取相关实例!当然 vueVM.$options
也可以获取!