346、Vuex 學習筆記05 -【項目結構、插件】 2020.04.27

1、 項目結構

Vuex 並不限制你的代碼結構。但是,它規定了一些需要遵守的規則:

應用層級的狀態應該集中到單個 store 對象中。

提交 mutation 是更改狀態的唯一方法,並且這個過程是同步的。

異步邏輯都應該封裝到 action 裏面。

只要你遵守以上規則,如何組織代碼隨你便。如果你的 store 文件太大,只需將 action、mutation 和 getter 分割到單獨的文件。

對於大型應用,我們會希望把 Vuex 相關代碼分割到模塊中。下面是項目結構示例:

├── index.html
├── main.js
├── api
│ └── … # 抽取出API請求
├── components
│ ├── App.vue
│ └── …
└── store
├── index.js # 我們組裝模塊並導出 store 的地方
├── actions.js # 根級別的 action
├── mutations.js # 根級別的 mutation
└── modules
├── cart.js # 購物車模塊
└── products.js # 產品模塊

2、插件

Vuex 的 store 接受 plugins 選項,這個選項暴露出每次 mutation 的鉤子。Vuex 插件就是一個函數,它接收 store 作爲唯一參數:

const myPlugin = store => {
  // 當 store 初始化後調用
  store.subscribe((mutation, state) => {
    // 每次 mutation 之後調用
    // mutation 的格式爲 { type, payload }
  })
}

然後像這樣使用:

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

2.1 在插件內提交 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 = new Vuex.Store({
  state,
  mutations,
  plugins: [plugin]
})

2.2 生成 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 = new Vuex.Store({
  // ...
  plugins: process.env.NODE_ENV !== 'production'
    ? [myPluginWithSnapshot]
    : []
})

3、參考文獻

[01] 項目結構 - Vuex官方文檔
[02] 插件 - Vuex官方文檔

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章