最初瞭解到eventBus和vuex並不清楚其原理只知道無腦用,甚至有些時候用的時候還不是很清楚,最近比較好奇這二者的區別,特以此文梳理vue
// event-bus.js
import Vue from 'vue'
export const EventBus = new Vue()
複製代碼
建立一個全局事件總線vuex
// main.js
Vue.prototype.$EventBus = new Vue()
複製代碼
export default new Vue({
data() {
return {
searchShow: true,
showBtn: true
}
},
methods: {
searchShowChange(value) {
if (typeof value === 'boolean') {
this.searchShow = false
} else {
this.searchShow = !this.searchShow
}
this.$emit('searchShowChange')
}
}
})
複製代碼
$on
/$emit
/$off
$off移除監聽者
beforeDestroy() {
//組件銷燬前須要解綁事件。不然會出現重複觸發事件的問題
this.bus.$off(this.$route.path);
}
複製代碼
當咱們的應用遇到多個組件共享狀態時,單向數據流的簡潔性很容易被破壞: 1.多個視圖依賴於同一狀態。 2.來自不一樣視圖的行爲須要變動同一狀態。設計模式
對於問題一,傳參的方法對於多層嵌套的組件將會很是繁瑣,而且對於兄弟組件間的狀態傳遞無能爲力。對於問題二,咱們常常會採用父子組件直接引用或者經過事件來變動和同步狀態的多份拷貝。以上的這些模式很是脆弱,一般會致使沒法維護的代碼。數組
是一個專爲 Vue.js 應用程序開發的狀態管理模式。它採用集中式存儲管理應用的全部組件的狀態,並以相應的規則保證狀態以一種可預測的方式發生變化。緩存
缺點:須要頻繁地導入,而且在測試組件時須要模擬狀態bash
computed: {
count () {
return store.state.count
}
}
複製代碼
子組件能經過 this.$store 訪問到app
const app = new Vue({
el: '#app',
// 把 store 對象提供給 「store」 選項,這能夠把 store 的實例注入全部的子組件
store,
components: { Counter },
template: `
<div class="app">
<counter></counter>
</div>
`
})
const Counter = {
template: `<div>{{ count }}</div>`,
computed: {
count () {
return this.$store.state.count
}
}
}
複製代碼
// 在單獨構建的版本中輔助函數爲 Vuex.mapState
import { mapState } from 'vuex'
export default {
// ...
computed: mapState({
// 箭頭函數可以使代碼更簡練
count: state => state.count,
// 傳字符串參數 'count' 等同於 `state => state.count`
countAlias: 'count',
// 爲了可以使用 `this` 獲取局部狀態,必須使用常規函數
countPlusLocalState (state) {
return state.count + this.localCount
}
})
}
複製代碼
computed: mapState([
// 映射 this.count 爲 store.state.count
'count'
])
複製代碼
computed: {
localComputed () { /* ... */ },
// 使用對象展開運算符將此對象混入到外部對象中
...mapState({
// ...
})
}
複製代碼
store.getters.doneTodos
複製代碼
getters: {
// ...
doneTodosCount: (state, getters) => {
return getters.doneTodos.length
}
}
複製代碼
注意,getter 在經過方法訪問時,每次都會去進行調用,而不會緩存結果。異步
getters: {
// ...
getTodoById: (state) => (id) => {
return state.todos.find(todo => todo.id === id)
}
}
store.getters.getTodoById(2) // -> { id: 2, text: '...', done: false }
複製代碼
mapGetters 輔助函數僅僅是將 store 中的 getter 映射到局部計算屬性async
import { mapGetters } from 'vuex'
export default {
// ...
computed: {
// 使用對象展開運算符將 getter 混入 computed 對象中
...mapGetters([
'doneTodosCount',
'anotherGetter',
// ...
])
}
}
//若是你想將一個 getter 屬性另取一個名字,使用對象形式
...mapGetters({
// 把 `this.doneCount` 映射爲 `this.$store.getters.doneTodosCount`
doneCount: 'doneTodosCount'
})
複製代碼
在大多數狀況下,載荷應該是一個對象,這樣能夠包含多個字段而且記錄的 mutation 會更易讀函數
mutations: {
increment (state, payload) {
state.count += payload.amount
}
}
store.commit('increment', {
amount: 10
})
//對象風格的提交方式
store.commit({
type: 'increment',
amount: 10
})
複製代碼
在組件中提交 Mutation
mapMutations
輔助函數將組件中的 methods 映射爲 store.commit 調用import { mapMutations } from 'vuex'
export default {
// ...
methods: {
...mapMutations([
'increment', // 將 `this.increment()` 映射爲 `this.$store.commit('increment')`
// `mapMutations` 也支持載荷:
'incrementBy' // 將 `this.incrementBy(amount)` 映射爲 `this.$store.commit('incrementBy', amount)`
]),
...mapMutations({
add: 'increment' // 將 `this.add()` 映射爲 `this.$store.commit('increment')`
})
}
}
複製代碼
注意事項
Vue.set(obj, 'newProp', 123)
, 或者以新對象替換老對象。
例如,利用對象展開運算符咱們能夠這樣寫:
state.obj = { ...state.obj, newProp: 123 }
使用常量替代 Mutation 事件類型
1.常量更容易避免程序出現錯誤。若是把一個值賦給程序中的一個常量,而該常量已經有一個值,編譯器就回報告錯誤。 2.在其多人協做的時候,方便統一管理,並且在其狀態管理當中調用方法時一眼就是看出是其mutation裏面的方法,有問題直接快速找到。
// mutation-types.js
export const SOME_MUTATION = 'SOME_MUTATION'
// store.js
import Vuex from 'vuex'
import { SOME_MUTATION } from './mutation-types'
const store = new Vuex.Store({
state: { ... },
mutations: {
// 咱們可使用 ES2015 風格的計算屬性命名功能來使用一個常量做爲函數名
[SOME_MUTATION] (state) {
// mutate state
}
}
})
複製代碼
actions: {
increment ({ commit }) {
commit('increment')
}
}
複製代碼
store.dispatch('increment')
// 以載荷形式分發
store.dispatch('incrementAsync', {
amount: 10
})
// 以對象形式分發
store.dispatch({
type: 'incrementAsync',
amount: 10
})
複製代碼
actions: {
checkout ({ commit, state }, products) {
// 把當前購物車的物品備份起來
const savedCartItems = [...state.cart.added]
// 發出結帳請求,而後樂觀地清空購物車
commit(types.CHECKOUT_REQUEST)
// 購物 API 接受一個成功回調和一個失敗回調
shop.buyProducts(
products,
// 成功操做
() => commit(types.CHECKOUT_SUCCESS),
// 失敗操做
() => commit(types.CHECKOUT_FAILURE, savedCartItems)
)
}
}
複製代碼
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')
})
}
複製代碼
//利用 async / await,咱們能夠以下組合 action
// 假設 getData() 和 getOtherData() 返回的是 Promise
actions: {
async actionA ({ commit }) {
commit('gotData', await getData())
},
async actionB ({ dispatch, commit }) {
await dispatch('actionA') // 等待 actionA 完成
commit('gotOtherData', await getOtherData())
}
}
複製代碼