• 首页
  • vue
  • TypeScript
  • JavaScript
  • scss
  • css3
  • html5
  • php
  • MySQL
  • redis
  • jQuery
  • 插件

    Vuex 的store接受plugins选项,这个选项暴露出每次mutation的钩子。Vuex 插件就是一个函数,它接收store作为唯一参数:

    const myPlugin = (store) => {
      // 当 store 初始化后调用
      store.subscribe((mutation, state) => {
        // 每次 mutation 之后调用
        // mutation 的格式为 { type, payload }
      })
    }
    

    然后像这样使用:

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


    在插件内提交 Mutation

    在插件中不允许直接修改状态——类似于组件,只能通过提交mutation来触发变化。

    通过提交mutation,插件可以用来同步数据源到store。例如,同步websocket数据源到store(下面是个大概例子,实际上createPlugin方法可以有更多选项来完成复杂任务):

    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]
    })
    


    生成 State 快照

    有时候插件需要获得状态的“快照”,比较改变的前后状态。想要实现这项功能,你需要对状态对象进行深拷贝:

    const myPluginWithSnapshot = (store) => {
      let prevState = _.cloneDeep(store.state)
      store.subscribe((mutation, state) => {
        let nextState = _.cloneDeep(state)
    
        // 比较 prevState 和 nextState...
        // 保存状态,用于下一次 mutation
        prevState = nextState
      })
    }
    

    生成状态快照的插件应该只在开发阶段使用,使用 webpack 或 Browserify,让构建工具帮我们处理:

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

    上面插件会默认启用。在发布阶段,你需要使用 webpack 的 DefinePlugin 或者是 Browserify 的 envify 使process.env.NODE_ENV !=='production'false


    内置 Logger 插件

    如果正在使用 vue-devtools ,你可能不需要此插件。

    Vuex 自带一个日志插件用于一般的调试:

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

    createLogger函数有几个配置项:

    const logger = createLogger({
      collapsed: false, // 自动展开记录的 mutation
      filter (mutation, stateBefore, stateAfter) {
        // 若 mutation 需要被记录,就让它返回 true 即可
        // 顺便,`mutation` 是个 { type, payload } 对象
        return mutation.type !== "aBlocklistedMutation"
      },
      actionFilter (action, state) {
        // 和 `filter` 一样,但是是针对 action 的
        // `action` 的格式是 `{ type, payload }`
        return action.type !== "aBlocklistedAction"
      },
      transformer (state) {
        // 在开始记录之前转换状态
        // 例如,只返回指定的子树
        return state.subTree
      },
      mutationTransformer (mutation) {
        // mutation 按照 { type, payload } 格式记录
        // 我们可以按任意方式格式化
        return mutation.type
      },
      actionTransformer (action) {
        // 和 `mutationTransformer` 一样,但是是针对 action 的
        return action.type
      },
      logActions: true, // 记录 action 日志
      logMutations: true, // 记录 mutation 日志
      logger: console, // 自定义 console 实现,默认为 `console`
    })
    

    日志插件还可以直接通过<script>标签引入,它会提供全局方法createVuexLogger

    要注意,logger 插件会生成状态快照,所以仅在开发环境使用。

    上篇:项目结构

    下篇:严格模式