vuex-router-sync如何使用

天空還下著雪發表於2020-10-31

簡單來講vuex-router-sync外掛就是將vue-router的狀態同步到vuex

一、安裝

  • npm下載地址:https://www.npmjs.com/package/vuex-router-sync
> npm i vuex-router-sync --save

二、使用

import { sync } from 'vuex-router-sync'
import store from './vuex/store'
import router from './router'

sync(store, router, {moduleName: 'RouteModule'})

const app = new Vue({
  router,
  store,
}).$mount('#app');

列印store.state即可看到當前路由狀態

image

三、使用場景

假如您想在一個元件中顯示一條訊息,希望在幾乎每一個頁面上都顯示“Have a nice day, Jack”,除了首頁,因為首頁要顯示"Welcome back, Jack".
藉助vuex-router-sync,您可以輕鬆實現

const Top = {
  template: '<div>{{message}}</div>',
  computed: {
    message() {
      return this.$store.getters.getMessage;
    }
  },
};
const Bar = {
  template: '<div>{{message}}</div>',
  computed: {
    message() {
      return this.$store.getters.getMessage;
    }
  }
};

const routes = [{
    path: '/top',
    component: Top,
    name: 'top'
  },
  {
    path: '/bar',
    component: Bar,
    name: 'bar'
  },
];

const router = new VueRouter({
  routes
});

const store = new Vuex.Store({
  state: {
    username: 'Jack',
    phrases: ['Welcome back', 'Have a nice day'],
  },
  getters: {
    getMessage(state) {
      return state.route.name === 'top' ?
        `${state.phrases[0]}, ${state.username}` :
        `${state.phrases[1]}, ${state.username}`;
    },
  },
});

// sync store and router by using `vuex-router-sync`
sync(store, router);

const app = new Vue({
  router,
  store,
}).$mount('#app');

不然的話,你可能需要在vue-router的鉤子函式裡監聽,或在watch$route,然後修改store值來實現。

四、原理

在70多行的vuex-router-sync原始碼裡有以下幾段程式碼

store.registerModule(moduleName, {
  namespaced: true,
  state: cloneRoute(router.currentRoute),
  mutations: {
    'ROUTE_CHANGED': function ROUTE_CHANGED (state, transition) {
      store.state[moduleName] = cloneRoute(transition.to, transition.from)
    }
  }
})

首先是在我們的store中註冊了一個module,名字預設為route:

module中提供了一個叫ROUTE_CHANGEDmutation處理方法,然後還把router物件中的currentRoute儲存在了state中,這也是我們為什麼能夠通過this.$store.state.route拿到currentRoute的原因。

然後就是監聽store中的route物件的變化了,當route發生變化並且當前路由名字不等於需要跳轉到路由的時候,直接通過routerpush方法進行跳轉頁面:

var storeUnwatch = store.watch(
  function (state) { return state[moduleName]; },
  function (route) {
    var fullPath = route.fullPath;
    if (fullPath === currentPath) {
      return
    }
    if (currentPath != null) {
      isTimeTraveling = true
      router.push(route)
    }
    currentPath = fullPath
  },
  { sync: true }
)

storewatch方法跟vue中的watch是一個概念,也就是檢測某個屬性的變化,然後回撥。

最後通過router的全域性後置鉤子函式監聽當前路由物件,修改store中的當前state(當前路由物件):

// sync store on router navigation
var afterEachUnHook = router.afterEach(function (to, from) {
  if (isTimeTraveling) {
    isTimeTraveling = false
    return
  }
  currentPath = to.fullPath
  store.commit(moduleName + '/ROUTE_CHANGED', { to: to, from: from })
})

歡迎關注:https://www.fenxianglu.cn/

在這裡插入圖片描述

參考連結:

  • https://segmentfault.com/a/1190000019925019
  • https://blog.csdn.net/vv_bug/article/details/84064708

相關文章