大型單頁面應(yīng)用需要Vuex管理全局/模塊的狀態(tài)擅这,大型單頁面組件如果靠事件(events)/屬性(props)通訊傳值會(huì)把各個(gè)組件耦合在一起。
快速入門
- 安裝vuex庫
cnpm install -S vuex
- 創(chuàng)建Vuex.Store
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex);
const store = new Vuex.Store({
//組件數(shù)據(jù)源景鼠,單一的state屬性
state: {
clickCount: 0
},
//相當(dāng)于屬性仲翎,封裝獲取state
getters: {
getClickCount: state => {
return state.clickCount;
}
},
//封裝引起狀態(tài)變化的方法
mutations: {
increment(state) {
state.clickCount++;
}
},
//類似于 mutation痹扇,不同在于actions支持異步,不是直接變更狀態(tài)溯香,而是提交到mutation
actions: {
increment(context) {
context.commit('increment')
},
async incrementAsync({ commit }) {
return new Promise((resolve, reject) => {
setTimeout(() => {
try {
commit('increment');
resolve(new Date().getTime() + ' 成功執(zhí)行');
} catch (e) {
reject(e);
}
}, 1000)
});
}
}
});
export default store;
- Vue實(shí)例加入store
new Vue({
router: router,
store: store,
render: h => h(App),
}).$mount('#app')
- 組件獲取store值
<script>
import { mapGetters } from "vuex";
export default {
computed: mapGetters({ count: ["getClickCount"] }),
};
</script>
- 組件觸發(fā)更新
<script>
export default {
data() {
return { times: 0 };
},
methods: {
increment() {
this.times++;
//分發(fā)到action
this.$store.dispatch("incrementAsync");
//提交到mutations
this.$store.commit("increment");
},
},
};
</script>
解析
Vuex 是什么鲫构?
Vuex 是一個(gè)專為 Vue.js 應(yīng)用程序開發(fā)的狀態(tài)管理模式。它采用集中式存儲(chǔ)管理應(yīng)用的所有組件的狀態(tài)玫坛,并以相應(yīng)的規(guī)則保證狀態(tài)以一種可預(yù)測的方式發(fā)生變化结笨。Vuex 也集成到 Vue 的官方調(diào)試工具devtools extension,提供了諸如零配置的 time-travel 調(diào)試湿镀、狀態(tài)快照導(dǎo)入導(dǎo)出等高級(jí)調(diào)試功能炕吸。
State - 數(shù)據(jù)源
Vuex 使用單一狀態(tài)樹——是的,用一個(gè)對(duì)象就包含了全部的應(yīng)用層級(jí)狀態(tài)勉痴。
Vue通過store選項(xiàng)赫模,調(diào)用Vue.use(Vuex)注入到每一個(gè)子組件中(類似路由)
組件獲取State
computed: {
count () {
return this.$store.state.count
}
}
或者使用輔助函數(shù)mapState
computed: mapState({
// 箭頭函數(shù)可使代碼更簡練
count: state => state.count
})
Getter - 數(shù)據(jù)封裝讀取(類似屬性)
Getter 接受 state 作為其第一個(gè)參數(shù)
getters: {
doneTodos: state => {
return state.todos.filter(todo => todo.done)
},
getTodoById: (state) => (id) => {
return state.todos.find(todo => todo.id === id)
}
}
通過屬性訪問
store.getters.doneTodos
通過方法訪問
store.getters.getTodoById(2)
Getters 也提供了一個(gè)輔助函數(shù)方便訪問(mapGetters )
Mutation - 進(jìn)行狀態(tài)更改的地方
定義Mutation
mutations: {
increment (state, n) {
state.count += n
}
}
組件觸發(fā)變更
store.commit('increment', 1)
Mutations也提供輔助函數(shù)(mapMutations)
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')`
})
}
}
注意事項(xiàng)
- Mutation 必須是同步函數(shù)
- 最好提前在你的 store 中初始化好所有所需屬性蒸矛。
- 需要在對(duì)象上添加新屬性時(shí)使用 Vue.set 或 替換舊對(duì)象
Action - 對(duì)Mutation封裝
Action 類似于 mutation瀑罗,不同在于:
- Action 提交的是 mutation,而不是直接變更狀態(tài)雏掠。
- Action 可以包含任意異步操作斩祭。
定義Action
actions: {
increment ({ commit }) {
commit('increment')
}
}
組件分發(fā)Action
store.dispatch('increment')
支持異步方式分發(fā)
actions: {
async incrementAsync({ commit }) {
return new Promise((resolve, reject) => {
setTimeout(() => {
try {
commit('increment');
resolve(new Date().getTime() + ' 成功執(zhí)行');
} catch (e) {
reject(e);
}
}, 1000)
});
}
}
組件調(diào)用異步分發(fā)
this.$store.dispatch("incrementAsync").then(
(data) => {
console.log(data);
},
(err) => {
console.log(err);
}
);