Skip to content

Releases: vuejs/vuex

v2.1.1

17 Dec 00:42
Compare
Choose a tag to compare

Fixed

  • fix TypeScript definition for namespaced option.

v2.1.0

16 Dec 23:25
Compare
Choose a tag to compare

New

Module Namespacing

Thanks to the great work by @ktsn for bringing us this feature.

Modules can now be auto-namespaced by using the new namespaced: true option. The getters, actions and mutations inside a namespaced module will automatically be prefixed with a namespaced inferred from the module's registration path. For example:

  const store = new Vuex.Store({
    modules: {
      foo: {
        namespaced: true,
        // ...
      }
    }
  })

The foo module will automatically get assigned the namespace foo/.

Everything inside the module are auto resolved to respect the namespace, so toggling between namespaced or not does not affect the code inside the module itself.

See updated docs for more details.

Helpers for Namespaced Modules

You can now pass a namespace string as the first argument to the mapState, mapGetters, mapActions and mapMutations helpers, so that the mappings are resolved using that module as the context:

computed: {
  ...mapState('foo', {
    // state is the state of the `foo/` module instead of root
    bar: state => state.bar
  }
},
methods: {
  ...mapActions('foo', [
    // map this.doSomething() to this.$store.dispatch('foo/doSomething')
    'doSomething'
  ])
}

Updated docs.

v2.0.0

01 Oct 16:46
Compare
Choose a tag to compare
  • No changes from last RC.

Docs

v2.0.0-rc.6

24 Sep 21:55
Compare
Choose a tag to compare
v2.0.0-rc.6 Pre-release
Pre-release

New

  • Object-style commit is now supported. Note that there's a small difference between 2.0 and 1.0: in 2.0 the mutation objects received by store.subscribe will always be in the same format ({ type, payload }, regardless of whether it was committed via a normal commit or an object-style commit.

Changed

  • The logger is now exposed at vuex/dist/logger.js instead of vuex/logger.js. It is now built as UMD so can be used in browsers directly. It exposes the createVuexLogger global when used via <script> tags.

Fixed

  • #310 fix logger transformer option ignored (@ktsn)
  • #328 support circular structures in the logger (@ktsn)

v2.0.0-rc.5

15 Aug 16:45
Compare
Choose a tag to compare
v2.0.0-rc.5 Pre-release
Pre-release

Fixed

  • Avoid destroy watch callback when registering/unregistering modules (@ktsn)

Breaking Changes

  • The silent flag for silent dispatches should no longer be part of the payload, but rather declared in a new, 3rd argument options object:

    // before
    store.commit('TEST', { silent: true })
    
    // after
    store.commit('TEST', null, { silent: true })
  • Removed store.onActionsResolved as it is found unnecessary.

v2.0.0-rc.4

05 Aug 19:49
Compare
Choose a tag to compare
v2.0.0-rc.4 Pre-release
Pre-release

New

  • Now supports unregistering dynamic modules via store.unregisterModule(path: string | Array<string>). Note this method can only unregister modules registered dynamically via store.registerModule.

Breaking Changes

  • store.module renamed to store.registerModule.

v2.0.0-rc.3

11 Jul 21:06
Compare
Choose a tag to compare
v2.0.0-rc.3 Pre-release
Pre-release

Changes from 2.0.0-rc.1

New

  • reverted store.watch deprecation.

  • New method: store.onActionsResolved(cb)

    Call the callback when all current pending actions (ones that return Promises) have been resolved. This is useful for determining initial data fetch completion during server-side rendering.

  • New helper: mapState

    Directly map store state to computed properties.

    computed: {
      // other properties...
      ...mapState({
        count: state => state.count,
        withGetters (state, getters) {
          return state.count + getters.countPlusOne + this.prop // <- also has access to `this`
        }
      })
    }
  • New helper: mapMutations

    Same as mapActions except for committing mutations instead.

  • Actions now also have access to getters and root state (for module actions):

    actions: {
      example: ({ state, getters, rootState, commit }) => {
        // ...
      }
    }
  • Getters now also have access to other getters and root state (for module getters):

    getters: {
      example: (state, getters, rootState) => {
      }
    }

Fixed

  • #243 dynamically registering module should not throw in strict mode

v2.0.0-rc.1

05 Jul 01:46
Compare
Choose a tag to compare
v2.0.0-rc.1 Pre-release
Pre-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

v1.0.0-rc.2

05 Jul 01:45
Compare
Choose a tag to compare

Breaking Changes from rc.1

  • The store instance no longer exposes the event emit interface (on, off, emit, off).

  • Instead of store.on('mutation', cb), a new method store.subscribe is introduced. Typical usage inside a plugin would be:

    const myPlugin = store => {
      store.subscribe((mutation, state) => {
        // do something...
      })
    }

    See example internal plugins.

v1.0.0-rc

01 Jul 04:50
Compare
Choose a tag to compare

Note

Vuex 1.0 marks a stable version with small breaking changes from 0.6~0.8, but should be a relatively easy upgrade for current users.

There are some bigger breaking changes (also big improvements) planned for 2.0 here. Both 1.0 and 2.0 will be maintained in parallel for a reasonable amount of time.

New

  • Nested modules:

    A module can in turn contain sub-modules, so a module can be defined as:

    type Module = {
      state?: { [key: string]: any },
      mutations?: { [key: string]: Function },
      modules?: { [key: string]: Module }
    }

    Thanks to @ktsn for implementing this feature.

  • New method: store.replaceState(state)

    Allows explicitly replacing the store's root state. Note this should only be used for state snapshot restoration / time-travel purposes.

  • The store instance is now also an event emitter with on, off, once and emit methods.

Breaking Changes

  • Middlewares are replaced by plugins. A plugin is simply a function that receives the store as the only argument, and can listen to the mutation event on the store:

    const myPlugins = store => {
      store.on('mutation', (mutation, state) => {
        // ...
      })
    }

    For more details, see the updated docs.

  • Object style dispatch fix: in the docs, Object style dispatch was described as sending the dispatched object into the mutation handlers as the second argument, but in previous versions the implementation was incorrect. This caused confusions such as #184. In 1.0 it's been fixed to reflect what was described in the docs, however this technically is a breaking change.