Plugins

Try this lesson on Scrimba

Vuex stores accept the plugins option that exposes hooks for each mutation. A Vuex plugin is simply a function that receives the store as the only argument:

  1. const myPlugin = store => {
  2. // called when the store is initialized
  3. store.subscribe((mutation, state) => {
  4. // called after every mutation.
  5. // The mutation comes in the format of `{ type, payload }`.
  6. })
  7. }

And can be used like this:

  1. const store = new Vuex.Store({
  2. // ...
  3. plugins: [myPlugin]
  4. })

Committing Mutations Inside Plugins

Plugins are not allowed to directly mutate state - similar to your components, they can only trigger changes by committing mutations.

By committing mutations, a plugin can be used to sync a data source to the store. For example, to sync a websocket data source to the store (this is just a contrived example, in reality the createWebSocketPlugin function can take some additional options for more complex tasks):

  1. export default function createWebSocketPlugin (socket) {
  2. return store => {
  3. socket.on('data', data => {
  4. store.commit('receiveData', data)
  5. })
  6. store.subscribe(mutation => {
  7. if (mutation.type === 'UPDATE_DATA') {
  8. socket.emit('update', mutation.payload)
  9. }
  10. })
  11. }
  12. }
  1. const plugin = createWebSocketPlugin(socket)
  2. const store = new Vuex.Store({
  3. state,
  4. mutations,
  5. plugins: [plugin]
  6. })

Taking State Snapshots

Sometimes a plugin may want to receive “snapshots” of the state, and also compare the post-mutation state with pre-mutation state. To achieve that, you will need to perform a deep-copy on the state object:

  1. const myPluginWithSnapshot = store => {
  2. let prevState = _.cloneDeep(store.state)
  3. store.subscribe((mutation, state) => {
  4. let nextState = _.cloneDeep(state)
  5. // compare `prevState` and `nextState`...
  6. // save state for next mutation
  7. prevState = nextState
  8. })
  9. }

Plugins that take state snapshots should be used only during development. When using webpack or Browserify, we can let our build tools handle that for us:

  1. const store = new Vuex.Store({
  2. // ...
  3. plugins: process.env.NODE_ENV !== 'production'
  4. ? [myPluginWithSnapshot]
  5. : []
  6. })

The plugin will be used by default. For production, you will need DefinePluginPlugins - 图1 (opens new window) for webpack or envifyPlugins - 图2 (opens new window) for Browserify to convert the value of process.env.NODE_ENV !== 'production' to false for the final build.

Built-in Logger Plugin

If you are using vue-devtoolsPlugins - 图3 (opens new window) you probably don’t need this.

Vuex comes with a logger plugin for common debugging usage:

  1. import { createLogger } from 'vuex'
  2. const store = new Vuex.Store({
  3. plugins: [createLogger()]
  4. })

WARNING

Before v3.5.0, the createLogger function is exported at vuex/dist/logger package. Please checkout the “Before Vuex v3.5.0” section of this page.

The createLogger function takes a few options:

  1. const logger = createLogger({
  2. collapsed: false, // auto-expand logged mutations
  3. filter (mutation, stateBefore, stateAfter) {
  4. // returns `true` if a mutation should be logged
  5. // `mutation` is a `{ type, payload }`
  6. return mutation.type !== "aBlocklistedMutation"
  7. },
  8. actionFilter (action, state) {
  9. // same as `filter` but for actions
  10. // `action` is a `{ type, payload }`
  11. return action.type !== "aBlocklistedAction"
  12. },
  13. transformer (state) {
  14. // transform the state before logging it.
  15. // for example return only a specific sub-tree
  16. return state.subTree
  17. },
  18. mutationTransformer (mutation) {
  19. // mutations are logged in the format of `{ type, payload }`
  20. // we can format it any way we want.
  21. return mutation.type
  22. },
  23. actionTransformer (action) {
  24. // Same as mutationTransformer but for actions
  25. return action.type
  26. },
  27. logActions: true, // Log Actions
  28. logMutations: true, // Log mutations
  29. logger: console, // implementation of the `console` API, default `console`
  30. })

The logger file can also be included directly via a <script> tag, and will expose the createVuexLogger function globally.

Note the logger plugin takes state snapshots, so use it only during development.

Before Vuex v3.5.0

Before v3.5.0, the createLogger function is exported at vuex/dist/logger package.

  1. import createLogger from 'vuex/dist/logger'
  2. const store = new Vuex.Store({
  3. plugins: [createLogger()]
  4. })