單項(xiàng)數(shù)據(jù)流
單向數(shù)據(jù)流(Unidirectional data flow)方式使用一個(gè)上傳數(shù)據(jù)流和一個(gè)下傳數(shù)據(jù)流進(jìn)行雙向數(shù)據(jù)通信,兩個(gè)數(shù)據(jù)流之間相互獨(dú)立
簡單來說垢袱,單向數(shù)據(jù)流就是指只能從一個(gè)方向來改變數(shù)據(jù)和狀態(tài)。
Vuex
Vuex 是一個(gè)專為 Vue.js 應(yīng)用程序開發(fā)的狀態(tài)管理模式港柜。它采用集中式存儲管理應(yīng)用的所有組件的狀態(tài)请契,并以相應(yīng)的規(guī)則保證狀態(tài)以一種可預(yù)測的方式發(fā)生變化。
因?yàn)閱雾?xiàng)數(shù)據(jù)流在處理問題的時(shí)候非常簡單夏醉,但在vue項(xiàng)目的開發(fā)過程中會遇到一種情況就是多個(gè)組件需要共享同一種狀態(tài)時(shí)爽锥。無法處理兄弟組件之間的傳值。例如購物車的案例畔柔,購物車組件的數(shù)據(jù)要和顯示數(shù)據(jù)的兄弟組件之間的傳遞就會遇到這種問題氯夷。并且,當(dāng)有很多父子組件進(jìn)行傳值的時(shí)候靶擦,就會變得異橙迹混亂,加大維護(hù)的困難玄捕。所以Vuex就是為了解決這中問題而誕生踩蔚。
簡單講,可以把它理解為一個(gè)全局的“事件倉庫”(這也是Vuex的核心)枚粘。所有的數(shù)據(jù)更改都在這個(gè)倉庫中馅闽,在任何地方都可以在這條線上監(jiān)聽數(shù)據(jù)的改變。
- state馍迄,驅(qū)動應(yīng)用的數(shù)據(jù)源福也;
- view,以聲明方式將 state 映射到視圖攀圈;
- actions拟杉,響應(yīng)在 view 上的用戶輸入導(dǎo)致的狀態(tài)變化。
獲取state
1量承、最簡單的方法就是通過計(jì)算屬性。因?yàn)関ue是以數(shù)據(jù)驅(qū)動,所以當(dāng)state改變撕捍,會直接通過計(jì)算屬性來展現(xiàn)出來拿穴。
computed: {
count () {
return store.state.count
}
}
2、通過在根實(shí)例中注冊 store 選項(xiàng)忧风,該 store 實(shí)例會注入到根組件下的所有子組件中默色,且子組件能通過 this.$store 訪問到。
const app = new Vue({
el: '#app',
// 把 store 對象提供給 “store” 選項(xiàng)狮腿,這可以把 store 的實(shí)例注入所有的子組件
store,
components: { Counter },
template: `
<div class="app">
<counter></counter>
</div>
`
})
提交 mutation
更改 Vuex 的 store 中的狀態(tài)的唯一方法是提交 mutation腿宰,并且這個(gè)過程是同步的。:每個(gè) mutation 都有一個(gè)字符串的事件類型 (type) 和一個(gè)回調(diào)函數(shù) (handler)缘厢。這個(gè)回調(diào)函數(shù)就是我們實(shí)際進(jìn)行狀態(tài)更改的地方吃度,并且它會接受 state 作為第一個(gè)參數(shù)(也可以向 store.commit 傳入額外的參數(shù),即 mutation 的載荷(payload))
mutations: {
increment (state) {
// 變更狀態(tài)
state.count++
}
}
調(diào)用提交
store.commit('increment')
Action
- Action 提交的是 mutation贴硫,而不是直接變更狀態(tài)椿每。
- Action 可以包含任意異步操作。
- 異步邏輯都應(yīng)該封裝到 action 里面英遭。
Action 通過 store.dispatch 方法觸發(fā):
store.dispatch('increment')
購物車案例
checkout ({ commit, state }, products) {
// 把當(dāng)前購物車的物品備份起來
const savedCartItems = [...state.cart.added]
// 發(fā)出結(jié)賬請求间护,然后樂觀地清空購物車
commit(types.CHECKOUT_REQUEST)
// 購物 API 接受一個(gè)成功回調(diào)和一個(gè)失敗回調(diào)
shop.buyProducts(
products,
// 成功操作
() => commit(types.CHECKOUT_SUCCESS),
// 失敗操作
() => commit(types.CHECKOUT_FAILURE, savedCartItems)
)
}
}
在組件中分發(fā) Action
在組件中使用 this.$store.dispatch('xxx') 分發(fā) action,或者使用mapActions輔助函數(shù)將組件的 methods 映射調(diào)用(需要先在根節(jié)點(diǎn)注入 store):
import { mapActions } from 'vuex'
export default {
// ...
methods: {
...mapActions([
'increment', // 將 `this.increment()` 映射為 `this.$store.dispatch('increment')`
// `mapActions` 也支持載荷:
'incrementBy' // 將 `this.incrementBy(amount)` 映射為 `this.$store.dispatch('incrementBy', amount)`
]),
...mapActions({
add: 'increment' // 將 `this.add()` 映射為 `this.$store.dispatch('increment')`
})
}
}