Needs update to 2.1: https://github.com/vuejs/vuex/releases

Application State

Vuex is used for managing application state and it's very similar to Flux. Vuex uses a concept of application state, getters, mutations and actions. The application state contains variables where application data is stored, getters are computed state variables, mutations are used for interacting with state variables and actions are used for loading data (e.g. from a server). All these items are registered under the global namespace.

Getting Started

Let's start by installing the dependencies.

$ npm install --save vuex

Create a new file ./src/app/store/index.js and define the store.

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

Vue.use(Vuex);

import * as actions from './actions';
import * as getters from './getters';
import * as mutations from './mutations';
import * as state from './state';

export default new Vuex.Store({
  actions, 
  getters, 
  mutations, 
  state
});

Open the ./src/app/index.js file and attach the store.

...
import store from './store';

new Vue({
  ...
  store
});

Create a new file ./src/app/store/state.js and define state variables.

export var isFetching = false;
export var users = [];

Create a new file ./src/app/store/actions.js and add store actions.

export function fetchUsers ({commit}) {
  commit('startFetching');
  return new Promise((resolve) => {
    setTimeout(() => {
      commit('stopFetching');
      commit('addUser', {name: 'John Smith', enabled: true});
      commit('addUser', {name: 'Dona Black', enabled: false});
      resolve();
    }, 2000);
  });
}

Create a new file ./src/app/store/getters.js and define store computed variables.

export function enabledUsers (state) {
  return state.users.filter(u => u.enabled);
}

Create a new file ./src/app/store/mutations.js and define store mutations.

export function startFetching (state) {
  state.isFetching = true;
}

export function stopFetching (state) {
  state.isFetching = false;
}

export function addUser (state, data) {
  state.users.push(data);
}

We now have all the ingredients for retrieving and displaying a list of users. Add the code into one of your .vue file.

<template>
  <div>
    <div v-for="user in users">
      {{ user.name }}
    </div>
    <button v-on:click="loadMore">Load</button>
  </div>
</template>

<script>
export default {
  computed: {
    users () {
      return this.$store.state.users;
    }
  },
  methods: {
    loadMore () {
      this.$store.dispatch('fetchUsers');
    }
  }
}
</script>

State Hydration

Open the ./src/app/client-entry.js file and add the line below.

app.$store.replaceState(window.STATE);

Open the ./src/app/server-entry.js file and add a pre-fetch logic which will pre-populate the components with data.

...
export default (ctx) => {
  ...
  return Promise.all( // initialize components
    app.$router.getMatchedComponents().map(c => c.prefetch ? c.prefetch.call(app) : null)
  ).then(() => {
    ctx.state = app.$store.state; // set initial state
  }).then(() => {
    return app;
  });
};

Open the ./src/server/router/routes/app.js file and add the initial state source to the output.

page.on('end', () => {
  res.write(  `<script>window.STATE = JSON.parse('${JSON.stringify(ctx.state)}')</script>`);
  ...
});

Open the component file and define the prefetch method which loads data on the server and the beforeMount method which loads data on the client.

<script>
export default {
  ...
  prefetch () {
    return this.$store.dispatch('fetchUsers');
  },
  beforeMount () {
    if (!this.$store.state.users.length) {
      return this.$store.dispatch('fetchUsers');
    }
  }
}
</script>

results matching ""

    No results matching ""