Vuex2.0

Vuex 是什麼?

Vuex 是一個專爲 Vue.js 應用程序開發的狀態管理模式。它採用集中式存儲管理應用的所有組件的狀態,並以相應的規則保證狀態以一種可預測的方式發生變化。Vuex 也集成到 Vue 的官方調試工具 devtools extension,提供了諸如零配置的 time-travel 調試、狀態快照導入導出等高級調試功能。

狀態自管理應用包含以下幾個部分:

  • state,驅動應用的數據源;
  • view,以聲明方式將state映射到視圖;
  • actions,響應在view上的用戶輸入導致的狀態變化。

Vuex 背後的基本思想,借鑑了 FluxRedux、和 The Elm Architecture。與其他模式不同的是,Vuex 是專門爲 Vue.js 設計的狀態管理庫,以利用 Vue.js 的細粒度數據響應機制來進行高效的狀態更新。


State

單一狀態樹

Vuex 使用 單一狀態樹 —— 是的,用一個對象就包含了全部的應用層級狀態。至此它便作爲一個『唯一數據源(SSOT)』而存在。這也意味着,每個應用將僅僅包含一個 store 實例。單一狀態樹讓我們能夠直接地定位任一特定的狀態片段,在調試的過程中也能輕易地取得整個當前應用狀態的快照。

在 Vue 組件中獲得 Vuex 狀態

那麼我們如何在 Vue 組件中展示狀態呢?由於 Vuex 的狀態存儲是響應式的,從 store 實例中讀取狀態最簡單的方法就是在計算屬性中返回某個狀態:

// 創建一個 Counter 組件
const Counter = {
  template: `<div>{{ count }}</div>`,
  computed: {
    count () {
      return store.state.count
    }
  }
}

每當 store.state.count 變化的時候, 都會重新求取計算屬性,並且觸發更新相關聯的 DOM。

Getters

有時候我們需要從 store 中的 state 中派生出一些狀態,例如對列表進行過濾並計數:

computed: {
  doneTodosCount () {
    return this.$store.state.todos.filter(todo => todo.done).length
  }
}

如果有多個組件需要用到此屬性,我們要麼複製這個函數,或者抽取到一個共享函數然後在多處導入它 —— 無論哪種方式都不是很理想。

Vuex 允許我們在 store 中定義『getters』(可以認爲是 store 的計算屬性)。Getters 接受 state 作爲其第一個參數:

const store = new Vuex.Store({
  state: {
    todos: [
      { id: 1, text: '...', done: true },
      { id: 2, text: '...', done: false }
    ]
  },
  getters: {
    doneTodos: state => {
      return state.todos.filter(todo => todo.done)
    }
  }
})

Getters 會暴露爲 store.getters 對象:

store.getters.doneTodos // -> [{ id: 1, text: '...', done: true }]


Mutations

更改 Vuex 的 store 中的狀態的唯一方法是提交 mutation。Vuex 中的 mutations 非常類似於事件:每個 mutation 都有一個字符串的 事件類型 (type) 和 一個 回調函數 (handler)。這個回調函數就是我們實際進行狀態更改的地方,並且它會接受 state 作爲第一個參數:

const store = new Vuex.Store({
  state: {
    count: 1
  },
  mutations: {
    increment (state) {
      // 變更狀態
      state.count++
    }
  }
})

你不能直接調用一個 mutation handler。這個選項更像是事件註冊:“當觸發一個類型爲 increment 的 mutation 時,調用此函數。”要喚醒一個 mutation handler,你需要以相應的 type 調用 store.commit 方法:

store.commit('increment')


Actions

Action 類似於 mutation,不同在於:

  • Action 提交的是 mutation,而不是直接變更狀態。
  • Action 可以包含任意異步操作。

分發 Action

Action 通過 store.dispatch 方法觸發:

store.dispatch('increment')


Modules

使用單一狀態樹,導致應用的所有狀態集中到一個很大的對象。但是,當應用變得很大時,store 對象會變得臃腫不堪。

爲了解決以上問題,Vuex 允許我們將 store 分割到模塊(module)。每個模塊擁有自己的 state、mutation、action、getters、甚至是嵌套子模塊——從上至下進行類似的分割:

const moduleA = {
  state: { ... },
  mutations: { ... },
  actions: { ... },
  getters: { ... }
}

const moduleB = {
  state: { ... },
  mutations: { ... },
  actions: { ... }
}

const store = new Vuex.Store({
  modules: {
    a: moduleA,
    b: moduleB
  }
})

store.state.a // -> moduleA 的狀態
store.state.b // -> moduleB 的狀態

項目結構

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

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

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

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

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

對於大型應用,我們會希望把 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   # 產品模塊

請參考購物車示例

API 參考

上面是官網的一些intro,在這裏記錄一下。

vuex更新數據流程:

  • dispatch可以是view視圖中觸發,也可以是程序業務邏輯來觸發
  • actions通過commit方法發出一個改變事件
  • mutations中具體操作state的改變
  • state的改變通過getter暴露給view,state改變後會立即通知用getter關聯起來的view。
  • 創建一個Vuex.Store的實例,用於Vue實例。

PS:

Vuex引入一個store對象來實現數據更新的操作,不再是Vue實例自己來實現數據更新;

它可以讓(之前的)組件之間通訊來告知共享狀態的更新,變爲組件和store之間的通訊。

在使用mapState時,

// 爲了能夠使用 `this` 獲取局部狀態,

必須使用常規函數,如:

countPlusLocalState (state)

{

return state.count + this.localCount;

}

推薦一個博客,寫的Vuex教程不錯。

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