Skip to content
Pre-release
Pre-release

@yyx990803 yyx990803 released this Jul 5, 2016 · 706 commits to dev since this release

Wasn't 1.0-rc just released?

Yes, the 1.0-rc is consolidating the current API in 0.8.x with very minor breaking changes and marking it as stable. Most current 0.8.x users should be able to easily migrate to 1.0 with minimal effort; However 2.0 introduces some more substantial changes and may not be an easy upgrade for 0.8.x users. We are releasing both in parallel - both will be maintained for bug fixes, the difference being that 1.0 is considered "done" and will not receive new features in the future.

Breaking Changes from 1.0

  • store.dispatch() is now used for triggering actions instead of mutations. To trigger a mutation, use the new store.commit() method. (See Actions & Getters in the Store section below)

  • store.dispatch() and store.commit() are no longer variadic: it now accepts a single payload value as the second argument:

    store.dispatch('action', payload)
    store.commit('mutation', payload)
  • The vuex component option has been deprecated. (See Component Binding Helpers section for new component binding usage below)

  • store.watch is deprecated. Use store.subscribe to react to mutations. reverted in 2.0.0-rc.3

Breaking Changes from 0.8.x

  • middlewares are replaced by plugins. A plugin is simply a function that receives the store instance:

    const myPlugin = store => {
      store.subscribe((mutation, state) => {
        console.log(`mutation fired: ${mutation.type}`)
        console.log(`with payload:`, mutation.payload)
      })
    }

New

Actions & Getters in the Store

You can now define actions directly inside the store and trigger them with store.dispatch(type, payload):

const store = new Vuex.Store({
  state: { count: 0 },
  mutations: {
    inc: state => state.count++
  },
  actions: {
    incAsync: ({ commit }, delay) => {
      setTimeout(() => commit('inc'), delay)
    }
  }
})

store.dispatch('incAsync', 1000) // increment after 1 second

Same for getters, except you access getters via store.getters[name]:

const store = new Vuex.Store({
  state: {
    count: 0
  },
  getters: {
    hasAny: state => state.count > 0
  }
})

// access the getter
store.getters.hasAny // -> false

Composable Action Flow

  1. To indicate the completion of an action, return a Promise from the action. store.dispatch will return that Promise if there is only a single handler called. If multiple action handlers are matched, it will return a Promise that resolves when all Promises returned by those handlers are resolved.

    const store = new Vuex.Store({
      actions: {
        doSomething: ({ commit }, payload) => {
          return callPromiseAPI(payload).then(res => {
             commit('some-mutation', { res })
          })
        }
      }
    })
    
    store.dispatch('doSomething', { id: 1 }).then(() => {
      // action done
    })
  2. Based on (1) and async/await, we can have very clean composition between async actions:

    const store = new Vuex.Store({
      actions: {
        one: async ({ commit }, payload) => {
          const res = await callPromiseAPI(payload)
          commit('some-mutation', { res })
        },
        two: async ({ dispatch, commit }) => {
          await dispatch('one')
          commit('done')
        }
      }
    })
    
    store.dispatch('two') // fires off complicated async flow

    The convention of returning Promises also allows Vuex to:

    1. better handle errors during async action flow.
    2. simplify store initialization during server-side rendering.

Component Binding Helpers

In Vuex 2.0, the vuex option will be deprecated in favor of just computed properties and methods. You are free to structure your Vuex store usage the way you prefer. However, we will be keeping the injection for this.$store so that you can do this:

export default {
  computed: {
    a () {
      return this.$store.getters.a
    }
  },
  methods: {
    b (...args) {
      this.$store.dispatch('b', …args)
    }
  }
}

The above alleviates the need to import the store everywhere. But it can get verbose when you have many getters and actions in the same component. Therefore we provide two helpers, mapGetters and mapActions:

import { mapGetters, mapActions } from 'vuex'

export default {
  computed: mapGetters(['a', 'b', 'c']),
  methods: mapActions(['d', 'e', 'f'])
}

So in the component, this.a maps to this.$store.getters.a, and this.d(...args) maps to this.$store.dispatch('d', ...args).

If you want to map a getter/action to a different local name, use an object instead:

import { mapGetters, mapActions } from 'vuex'

export default {
  computed: mapGetters({
    myComputed: 'a' // map this.myComputed to store.getters.a
  }),
  methods: mapActions({
    myMethod: 'b' // map this.myMethod() to store.dispatch('b')
  })
}

Finally, you can easily compose them with local computed properties and methods using Object spread operator:

import { mapGetters, mapActions } from 'vuex'

export default {
  computed: {
    localComputed () {  },
    ...mapGetters(['a', 'b', 'c', 'd'])
  },
  methods: {
    localMethod () {  },
    ...mapActions(['b'])
  }
}

Nested Modules Improvements

Actions, getters and mutations are all supported inside modules.

Similar to how a module mutation receives the sub-state-tree of that module, actions and getters defined in a module will receive the sub-state-tree as well. This makes modules portable without having to be aware of the path it is nested under.

Note that module actions, getters and mutations do all share the same registration namespace with other modules, so if you want to ensure your module is well-isolated, you should consider prefixing its mutation/action types and getter names.

New API methods

  • store.module(path, moduleOptions)

    Register a module into the store. The path argument can be either a string, or an Array of strings. When registering a nested module, its direct parent state tree must already be present.

  • store.subscribe((mutation, state) => { ... })

    Subscribe to state changes. Callback is called after each mutation. Typically used in plugins.

Reference

Assets 2
You can’t perform that action at this time.