什么是Vuex?
1,Vuex 是一個專為 Vue.js 應用程序開發的狀態管理模式。它采用集中式存儲管理應用的所有組件的狀態,並以相應的規則保證狀態以一種可預測的方式發生變化
2,每一個 Vuex 應用的核心就是 store(倉庫)。“store”基本上就是一個容器,它包含着你的應用中大部分的狀態 (state)
3,其實也就是,應用中各個組件之間共享狀態的一個狀態庫,並可以時時映射到視圖
什么時候用的到Vuex?
1,如果你需要構建一個大中型應用的時候,會使用到很多組件嵌套,很多業務處理,此時需要是用Vuex更好地在組件外部管理所有的狀態。
2,如果你需要構建的應用是輕量的,則完全沒有必要引入Vuex,使用簡單的 store 模式 或者組件之間的傳遞方式即可實現功能。
一,vue cli中簡單使用Vuex示例
1,state用法
注:main.js為定義store的代碼,后面為接收state的幾種方式
- main.js
import Vue from 'vue' import Vuex from 'vuex' import App from './App.vue' import router from './router/' Vue.use(Vuex) const store = new Vuex.Store({ namespaced: false, state: { title: '標題', backFlag: false }, mutations: { updateTitle (state, title) { state.title = title }, updateBackFlag (state, backFlag) { state.backFlag = backFlag } } }) Vue.config.productionTip = false new Vue({ router, store, render: h => h(App) }).$mount('#app')
- 適合獲取狀態個數少的時候
<template> {{title}} {{backFlag}} </template> <script> export default { name: "第一種接收方式", computed: { title () { return this.$store.state.title; }, backFlag () { return this.$store.state.backFlag; } } } </script>
- 適合多個狀態的時候
<template> {{title}} {{backFlag}} </template> <script> import { mapState } from 'vuex' export default { name: "第二種接收方式", computed: mapState({
//'title',//此種方式也可以獲取狀態 title: state => state.title, backFlag: state => state.backFlag }) } </script>
- 適合與局部計算屬性混合使用的時候
<template> {{title}} {{backFlag}} </template> <script> import { mapState } from 'vuex' export default { name: "第三種接收方式", ...mapState({ title: state => state.title, backFlag: state => state.backFlag }) } </script>
2,Getter用法
注:Getter適用於狀態庫里面的數據需要進行一遍過濾,或者狀態值需要依賴其他狀態進行一定計算,此時可以使用Getter方法,進行計算並返回
- 定義getter代碼:
const store = new Vuex.Store({ namespaced: false, state: { todos: [ { id: 1, text: '第一條', done: false }, { id: 2, text: '第二條', done: false }, { id: 3, text: '第三條', done: true } ] }, mutations: { updateTodos (state, todos) { state.todos = todos } }, getters: { //根據id值,查詢todos狀態庫里的值 getTodoById: (state) => (id) => { return state.todos.find(todo => todo.id === id) }, //查詢todos狀態庫里done為true的值 doneTodos: state => { return state.todos.filter(todo => todo.done) } } })
- 接收getter代碼:
<template> <div>{{doneTodos}}</div> </template> <script> import { mapState,mapGetters } from 'vuex' export default { name: "test", computed: { //自動查詢doneTodos,為賦值為doneTodos ...mapGetters({ doneTodos: 'doneTodos' }) }, mounted:function() { //查詢todos狀態庫里done為true的值 console.info(this.$store.getters.doneTodos) //查詢todos狀態庫里done為true的值 console.info(this.$store.getters.getTodoById(2)) } }; </script> <style lang="less"> </style>
3,Mutation用法
注:更改 Vuex 的 store 中的狀態的唯一方法是提交 mutation,直接改變狀態,但Mutation必須是同步函數,如需要使用調用api等異步操作,請使用4 actions
- 定義Mutation代碼
const store = new Vuex.Store({ namespaced: false, state: { title: '標題', backFlag: false }, mutations: { updateTitle (state, title) { state.title = title }, updateBackFlag (state, backFlag) { state.backFlag = backFlag } } })
- 調用接收Mutation代碼
<template> <div>{{title}}</div> </template> <script> import { mapState,mapMutations } from 'vuex' export default { name: "test", computed: { //自動賦值title值 ...mapState({ title: state => state.title, }) }, mounted:function() { //第一種方法 動態更新title內容 this.$store.commit('updateTitle',"騰訊_首頁") //第二種方法 動態更新title內容 this.updateTitle('阿里_首頁') }, methods: { // 將 `this.add()` 映射為 `this.$store.commit('navbar/updateTitle')` ...mapMutations({ updateTitle: 'updateTitle' }) } }; </script> <style lang="less"> </style>
4,Action的用法
注:Action 類似於 mutation,不同在於:
- Action 提交的是 mutation,而不是直接變更狀態。
- Action 可以包含任意異步操作,可以使用promise、await等處理異步調用
- 定義Action
import HttpService from '../../service/httpService.js'; const store = new Vuex.Store({ namespaced: false, state: { title: '標題', backFlag: false }, mutations: { updateTitle (state, title) { state.title = title }, updateBackFlag (state, backFlag) { state.backFlag = backFlag } }, actions: { updateTitleAsync (context,obj) { return new Promise((resolve, reject) => { let channelId = '001' HttpService.queryGoods(channelId) .then(data => { context.commit('updateTitle',obj.title) resolve() }) .catch(error => { console.info(error); }); }) } } })
- 接收action代碼
<template> <div>{{title}}</div> </template> <script> import { mapState,mapMutations,mapActions } from 'vuex' export default { name: "test", //自動賦值title值 ...mapState({ title: state => state.title, }) }, mounted:function() { // this.updateTitleAsync("異步賦值,不關心返回值") this.updateTitleAsync({ title: "異步賦值,切需立即使用返回值" }).then(() => {
//console.info(context.backFlag) console.info(this.$store.state.title) }) }, methods: { // 將 `this.updateTitleAsync()` 映射為 `this.$store.dispatch('increment')` ...mapActions({ updateTitleAsync: 'updateTitleAsync' }) } }; </script> <style lang="less"> </style>
5,Module的用法
注:當應用比較復雜時,狀態比較多並難管理時,Vuex 允許我們將 store 分割成模塊(module)
- 創建module模塊
const store new Vuex.Store({ modules: {
//navbar模塊: navbar: { namespaced: true, state: { title: '默認值', backFlag: false }, mutations: { updateTitle (state, title) { state.title = title }, updateBackFlag (state, backFlag) { state.backFlag = backFlag } } } } })
- 如何接收使用模塊值,參考如下,加上模塊名稱即可
<template> <div>{{title}}</div> </template> <script> import { mapState,mapMutations } from 'vuex' export default { name: "test", computed: { //自動賦值title值 ...mapState({ title: state => state.navbar.title, }) }, mounted:function() { //第一種方法 動態更新title內容 this.$store.commit('navbar/updateTitle',"騰訊_首頁") //第二種方法 動態更新title內容 this.updateTitle('阿里_首頁') }, methods: { // 將 `this.add()` 映射為 `this.$store.commit('navbar/updateTitle')` ...mapMutations({ updateTitle: 'navbar/updateTitle' }) } }; </script> <style lang="less"> </style>
GitHub示例地址 vue-ht-cli