11
votes

I am developing a single-page-application using vue-cli3 and npm.

The problem: Populating a basic integer value (stored in a vuex state) named counter which was incremented/decremented in the backend to the frontend, which displays the new value.

The increment/decrement mutations are working fine on both components (Frontend/Backend), but it seems like the mutations don't work on the same route instance: When incrementing/ decrementing the counter in backend, the value is not updated in the frontend and otherwise.

store.js:

Contains the state which needs to be synced between Backend/Frontend.

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

export default new Vuex.Store({
  state: {
    counter: 10
  },
  mutations: {
    increment (state) {
      state.counter++
    },
    decrement (state) {
      state.counter--
    }
  }
})

index.js:

Defines the routes that the vue-router has to provide.

import Vue from 'vue'
import Router from 'vue-router'
import Frontend from '@/components/Frontend'
import Backend from '@/components/Backend'

Vue.use(Router)

export default new Router({
  routes: [
    {
      path: '/',
      name: 'Frontend',
      component: Frontend
    },
    {
      path: '/backend',
      name: 'Backend',
      component: Backend
    }
  ],
  mode: 'history'
})

main.js:

Inits the Vue instance and provides the global store and router instances.

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

Vue.config.productionTip = false

sync(store, router)

new Vue({
  router,
  store,
  render: h => h(App)
}).$mount('#app')

Frontend.vue/Backend.vue:

Both (Frontend/Backend) use the same code here. They use the state counter in order to display and modify it.

<template>
  <div> Counter: {{ getCounter }}
    <br>
    <p>
      <button @click="increment">+</button>
      <button @click="decrement">-</button>
    </p>
  </div>
</template>

<script>
export default {
  name: 'Frontend',
  methods: {
    increment () {
      this.$store.commit('increment')
    },
    decrement () {
      this.$store.commit('decrement')
    }
  },
  computed: {
    getCounter () {
      return this.$store.state.counter
    }
  }
}
</script>

It would be awesome if someone sould tell me what I am missing or if I have misunderstood the concept of vuex and vue-router.

2
Hey, maybe you can sync with this: github.com/vuejs/vuex-router-syncLeonard Klausmann
I don't understand your backend, is it just another vue file, or an actual server?Len Joseph
Thanks @LeonardKlausmann, but I am already using vuex-router-sync, as you can see in sync(store, router) in main.js. But i guess this is just for syncing the current route of vue-router in a vuex-state. Hence not the solution for my problem.sebikolon
@I'mOnlyVueman it is just another vue file with the same content as in Frontend.vue. I tried to keep the application as simple as possible in order to get vuex working.sebikolon
Then what you need to do if you want the state to reflect the backend file is: 1) create a prop in your backend that holds the current counter value 2) in the frontend, create a beforeMount() function that takes the backend prop as a parameter and uses it as a payload to a vuex mutation. Recommend using mapMutations to trigger the mutation from the function. 3) when the frontend is created, the beforeMount function would read the prop from backend, then commit a mutation with the prop value to update the state. 4) By the time frontend mounts, state should have the value you want it toLen Joseph

2 Answers

1
votes

Just get the counter from the store for both components. You don't need data as store is already reactive.

<template>
  <div> Counter: {{ counter }}
    <br>
    <p>
      <button @click="increment">+</button>
      <button @click="decrement">-</button>
    </p>
  </div>
</template>

<script>
import { mapState, mapMutations } from 'vuex';

export default {
  name: 'Frontend',
  methods: {
    ...mapMutations([
      'increment',
      'decrement',
    ])
  },
  computed: {
    ...mapState({
        counter: state => state.counter,
    })
  }
}
</script>

For reference:

0
votes

@sebikolon component properties that are defined in data () => {} are reactive, methods are not, they are called once. Instead of {{ getCounter }}, just use {{ $store.state.counter }}. OR initiate property in each component that gets the value of your state.

data: function () {
    return {
        counter: $store.state.counter,
    }
}