vuex, vue-router and vuex-router-sync

router sync

by simati

HTML

<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>
<script src="https://unpkg.com/vuex/dist/vuex.js"></script>

<div id="app">
  <p>
    <router-link to="/top">Go to Top</router-link>
    <router-link to="/bar">Go to Bar</router-link>
  </p>
  <router-view></router-view>
</div>

CSS

.router-link-active {
  color: red;
}

JavaScript

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');












// vuex-router-sync pasted here because no proper cdn service found
function sync(store, router, options) {
  var moduleName = (options || {}).moduleName || 'route'

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

  var isTimeTraveling = false
  var currentPath

  // sync router on store change
  store.watch(
    function (state) { return state[moduleName] },
    function (route) {
      if (route.fullPath === currentPath) {
        return
      }
      isTimeTraveling = true
      var methodToUse = currentPath == null
        ? 'replace'
        : 'push'
      currentPath = route.fullPath
      router[methodToUse](route)
    },
    { sync: true }
  )

  // sync store on router navigation
  router.afterEach(function (to, from) {
    if (isTimeTraveling) {
      isTimeTraveling = false
      return
    }
    currentPath = to.fullPath
   ...