vuex的應用和解決的實際問題
阿新 • • 發佈:2018-01-17
alt 回調 而不是 font incr const 不足 ali 什麽
這是vuex的語法結構內容
簡單的理解vuex:
new Vue({
// state
data () {
return {
count: 0
}
},
// view
template: `
<div>{{ count }}</div>
`,
// actions
methods: {
increment () {
this.count++
}
}
})
state,驅動應用的數據源;(單向數據流)
view,以聲明方式將 state 映射到視圖;(靜態顯示出來的數據源)
actions,響應在 view 上的用戶輸入導致的狀態變化 (數據源變化追蹤)
---------------------------------------------------------------------------------
vuxe解決了:
1.多個組件共享狀態時,單向數據流的簡潔性很容易被破壞:
2.多個視圖依賴於同一狀態。
3.來自不同視圖的行為需要變更同一狀態。
---------------------------------------------------------------------------------
vuex使用場景:
中大型單頁應用,考慮如何更好地在組件外部管理狀態,簡單應用不建議使用。
---------------------------------------------------------------------------------
Vuex 的狀態存儲是響應式的
state:
從 store 實例中讀取狀態最簡單的方法就是在計算屬性中返回某個狀態
如:
view層:
template: `
<div>{{ count }}</div>
`
computed: {
count () {
return store.state.count
}
}
(這種方式頻繁操作的話繁瑣於是有了更好的解決方式,因為在每個需要使用 state 的組件中都需要頻繁地導入)
Vuex 通過 store 選項,提供了一種機制將狀態從根組件“註入”到每一個子組件中(需調用 Vue.use(Vuex))
通過在根實例中註冊 store 選項,該 store 實例會註入到根組件下的所有子組件中,且子組件能通過 this.$store 訪問到
computed: {
count () {
return this.$store.state.count
}
}
(這種方式比較好)
-----------------------------------------------------------------------------------
當一個組件需要獲取多個狀態時候,將這些狀態都聲明為計算屬性會有些重復和冗余。此時可以用使用 mapState 輔助函數幫助我們生成計算屬性(少寫好多代碼的)
import { mapState } from ‘vuex‘
export default {
computed: mapState({
// ES6箭頭函數可使代碼更簡練
count: state => state.count,
countAlias: ‘count‘, //傳字符串參數‘count‘等同於`state => state.count`
countPlusLocalState (state) {
return state.count + this.localCount // 為了能夠使用`this`獲取局部狀態,必須使用常規函數
}
})
}
當映射的計算屬性的名稱與 state 的子節點名稱相同時,我們也可以給 mapState 傳一個字符串數組。
computed: mapState([
‘count‘//映射 this.count為store.state.count
])
對象展開運算符(簡單的mapState可以傳數組和對象對象時候前面的屬性是自定義的別名)
computed: {
localComputed () { /* ... */ },
...mapState({ // 使用對象展開運算符將此對象混入到外部對象中
})
}
-----------------------------------------------------------------------------------
同state,vuex裏面的getter也是如此:
computed: {
doneTodosCount () {
return this.$store.state.todos.filter(todo => todo.done).length //對數據源進行基本的操作
}
}
(最初始是如果有多個組件需要用到此屬性,我們要麽復制這個函數,或者抽取到一個共享函數然後在多處導入它)
進而:
Vuex允許我們在store中定義“getter”可以認為是 store 的計算屬性)。就像計算屬性一樣,getter 的返回值會根據它的依賴被緩存起來,且只有當它的依賴值發生了改變才會被重新計算。
mapGetters 輔助函數
mapGetters 輔助函數僅僅是將 store 中的 getter 映射到局部計算屬性:
import { mapGetters } from ‘vuex‘
export default {
computed: {
...mapGetters([ //使用對象展開運算符將getter混入computed對象中
‘doneTodosCount‘,(實際就是導出一個方法,可以獲取裏面的東西和一些操作)
‘anotherGetter‘,
// ...
])
}
}
如果你想將一個getter屬性另取一個名字,使用對象形式:
mapGetters({
doneCount: ‘doneTodosCount‘ //映射`this.doneCount`為`store.getters.doneTodosCount`
})
-----------------------------------------------------------------------------------
更改 Vuex 的 store 中的狀態的唯一方法是提交 mutation:
Vuex中的mutation非常類似於事件:每個mutation都有一個字符串的 事件類型 (type)和一個 回調函數 (handler)。這個回調函數就是我們實際進行狀態更改的地方,並且它會接受 state 作為第一個參數:
const store = new Vuex.Store({
state: {
count: 1
},
mutations: {
increment (state) {
// 變更狀態
state.count++
}
}
})
(最初始是這樣的,但是註意一定是同步操作,異步是不行的)
你不能直接調用一個 mutation的回調,需要store.commit(‘increment‘)
向store.commit傳入額外的參數,叫做mutation的 載荷(payload)
mutations: {
increment (state, n) {
state.count += n
}
}
store.commit(‘increment‘, 10)
在大多數情況下,載荷應該是一個對象,這樣可以包含多個字段並且記錄的 mutation 會更易讀:
mutations: {
increment (state, payload) {
state.count += payload.amount
}
}
store.commit(‘increment‘, {
amount: 10
})
(傳進去的是什麽,調用的是時候也是傳對應的值就好了)
提交的另外一種方式:對象風格的提交方式(此時回調是不變的)
store.commit({
type: ‘increment‘,
amount: 10
})
Vuex 中的 mutation 也需要與使用 Vue 一樣遵守一些註意事項:
1.最好提前在你的 store 中初始化好所有所需屬性。
2.當需要在對象上添加新屬性時,你應該使用 Vue.set(obj, ‘newProp‘, 123), 或者
以新對象替換老對象:state.obj = { ...state.obj, newProp: 123 }
一般會獨立開來(使用mutation-types.js存放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
}
}
})
你可以在組件中使用this.$store.commit(‘xxx‘)提交 mutation或者使用 mapMutations 輔助函數(需要在根節點註入 store):
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‘)`
})
}
}
-----------------------------------------------------------------------------------
Action 類似於 mutation,不同在於:
1.Action 提交的是 mutation,而不是直接變更狀態。
2.Action 可以包含任意異步操作。
簡單的:
const store = new Vuex.Store({
state: {
count: 0
},
mutations: {
increment (state) {
state.count++
}
},
actions: {
increment (context) {
context.commit(‘increment‘)
}
}
})
Action 函數接受一個與 store 實例具有相同方法和屬性的context(函數上下文)對象,因此你可以調用 context.commit 提交一個 mutation,或者通過 context.state 和 context.getters 來獲取 state 和 getters。
context對象並不是store實例本身
提交:
actions: {
increment ({ commit }) {
commit(‘increment‘)
}
}
分發(觸發)Action:
store.dispatch(‘increment‘)
異步操作:
actions: {
incrementAsync ({ commit }) {
setTimeout(() => {
commit(‘increment‘)
}, 1000)
}
}
Actions 支持同樣的載荷方式和對象方式進行分發:
//以載荷形式分發
store.dispatch(‘incrementAsync‘, {
amount: 10
})
//以對象形式分發
store.dispatch({
type: ‘incrementAsync‘,
amount: 10
})
你在組件中使用 this.$store.dispatch(‘xxx‘) 分發 action,或者使用mapActions輔助函數
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‘)`
})
}
}
組合action:
實際項目沒用過async/await大概理解就是等待執行完上一個方法後(結束後)再走下一步(下一個方法)
// 假設 getData() 和 getOtherData() 返回的是 Promise
actions: {
async actionA ({ commit }) {
commit(‘gotData‘, await getData())
},
async actionB ({ dispatch, commit }) {
await dispatch(‘actionA‘) // 等待 actionA 完成
commit(‘gotOtherData‘, await getOtherData())
}
}
-----------------------------------------------------------------------------------
Module(Vuex 允許我們將 store 分割成模塊(module)解決store 對象臃腫)
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的應用和解決的實際問題