插件

Vuex 存储接受 plugins 选项,该选项为每个 Mutation 公开钩子。Vuex 插件只是一个接收存储作为唯一参数的函数

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

并且可以像这样使用

const store = createStore({
  // ...
  plugins: [myPlugin]
})

在插件内部提交 Mutation

插件不允许直接修改状态 - 与您的组件类似,它们只能通过提交 Mutation 来触发更改。

通过提交 Mutation,插件可用于将数据源同步到存储。例如,将 Websocket 数据源同步到存储(这只是一个虚构的示例,实际上 createWebSocketPlugin 函数可以接受一些额外的选项来完成更复杂的任务)

export default function createWebSocketPlugin (socket) {
  return (store) => {
    socket.on('data', data => {
      store.commit('receiveData', data)
    })
    store.subscribe(mutation => {
      if (mutation.type === 'UPDATE_DATA') {
        socket.emit('update', mutation.payload)
      }
    })
  }
}
const plugin = createWebSocketPlugin(socket)

const store = createStore({
  state,
  mutations,
  plugins: [plugin]
})

获取状态快照

有时插件可能希望接收状态的“快照”,并比较 Mutation 后状态与 Mutation 前状态。为了实现这一点,您需要对状态对象执行深拷贝

const myPluginWithSnapshot = (store) => {
  let prevState = _.cloneDeep(store.state)
  store.subscribe((mutation, state) => {
    let nextState = _.cloneDeep(state)

    // compare `prevState` and `nextState`...

    // save state for next mutation
    prevState = nextState
  })
}

获取状态快照的插件仅应在开发期间使用。使用 webpack 或 Browserify 时,我们可以让我们的构建工具为我们处理。

const store = createStore({
  // ...
  plugins: process.env.NODE_ENV !== 'production'
    ? [myPluginWithSnapshot]
    : []
})

该插件将默认使用。对于生产环境,您需要 DefinePlugin 用于 webpack 或 envify 用于 Browserify 将 process.env.NODE_ENV !== 'production' 的值转换为最终构建的 false

内置日志记录插件

Vuex 带有一个用于常见调试用途的日志记录插件

import { createLogger } from 'vuex'

const store = createStore({
  plugins: [createLogger()]
})

createLogger 函数接受一些选项

const logger = createLogger({
  collapsed: false, // auto-expand logged mutations
  filter (mutation, stateBefore, stateAfter) {
    // returns `true` if a mutation should be logged
    // `mutation` is a `{ type, payload }`
    return mutation.type !== "aBlocklistedMutation"
  },
  actionFilter (action, state) {
    // same as `filter` but for actions
    // `action` is a `{ type, payload }`
    return action.type !== "aBlocklistedAction"
  },
  transformer (state) {
    // transform the state before logging it.
    // for example return only a specific sub-tree
    return state.subTree
  },
  mutationTransformer (mutation) {
    // mutations are logged in the format of `{ type, payload }`
    // we can format it any way we want.
    return mutation.type
  },
  actionTransformer (action) {
    // Same as mutationTransformer but for actions
    return action.type
  },
  logActions: true, // Log Actions
  logMutations: true, // Log mutations
  logger: console, // implementation of the `console` API, default `console`
})

日志记录文件也可以通过 <script> 标签直接包含,并将全局公开 createVuexLogger 函数。

请注意,日志记录插件获取状态快照,因此仅在开发期间使用。