Vue狀態管理:vuex基礎


還是像以前一樣用一個簡單的案例來解釋vuex

首先,新建一個模板demo

1 vue init webpack-simple demo

我們需要兩個組件:一個輸入組件和一個顯示組件

在src文件夾中新建一個components文件夾,添加一個showInfo.vue

1 <template>
2     <h1>{{ msg }}</h1>
3 </template>
4 
5 <script>
6 export default {
7     props: ['msg']
8 }
9 </script>

然后,再添加一個changeInfo.vue

1 <template>
2     <input type="text" :value="msg">
3 </template>
4 
5 <script>
6 export default {
7     props: ['msg']
8 }
9 </script>

修改App.vue:

 1 <template>
 2   <div>
 3     <show-info :msg="msg"></show-info>
 4     <change-info :msg="msg"></change-info>
 5   </div>
 6 </template>
 7 
 8 <script>
 9 import showInfo from './components/showInfo'
10 import changeInfo from './components/changeInfo'
11 
12 export default {
13   components: {
14     showInfo,
15     changeInfo
16   },
17   data() {
18     return {
19       msg: 'Hello Vue!'
20     }
21   }
22 }
23 </script>

運行起來或許是這樣的:

缺點是信息傳遞仍然是使用綁定:msg="msg",而且由於vue組件之間傳輸信息的限制,現在修改輸入組件的文本並不會改變顯示組件的值。

現在來使用vuex來傳遞變量信息,首先安裝vuex:

1 npm install vuex --save

然后在src文件夾下新建vuex文件夾,並添加store.js

 1 import Vue from 'vue'
 2 import Vuex from 'vuex'
 3 Vue.use(Vuex)
 4 
 5 // 添加兩個常量state和mutations
 6 const state = {
 7     msg: 'Hello Vue!'
 8 }
 9 
10 const mutations = {
11     changeMessage(state, msg) {
12         state.msg = msg
13     }
14 }
15 
16 // 初始化已經創建的常量
17 export default new Vuex.Store({
18     state: state,
19     mutations: mutations
20 })

注意,在ES6中{state: state, mutations: mutations}可以簡寫為{state, mutations}

然后修改App.vue:

然后,在src/components/showInfo.vue中需要使用計算屬性來代替props:

 1 <template>
 2     <h1>{{ msg }}</h1>
 3 </template>
 4 
 5 <script>
 6 export default {
 7     computed: {
 8         msg() {
 9             return this.$store.state.msg
10         }
11     }
12 }
13 </script>

在changeInfo.vue中需要額外添加changeMsg方法:

 1 <template>
 2     <input type="text" :value="msg" @keyup="changeMsg">
 3 </template>
 4 
 5 <script>
 6 export default {
 7     computed: {
 8         msg() {
 9             return this.$store.state.msg
10         }
11     },
12     methods: {
13         changeMsg(e) {
14             this.$store.commit('changeMessage', e.target.value)
15         }
16     }
17 }
18 </script>

來看一下運行效果:

然而,現在的代碼是非常不好維護的,想象一下下面兩個場景:

1) 在一個大規模的應用中如果不同的組件都使用了$this.store.state.somevalue,一旦我們修改了somevalue的名字,就需要修改所有用到它的組件。

2) 如果有一個需要計算的值,例如計數器counter,如果其他的組件需要對它執行+1操作的話就得在組件中添加一個單獨的方法,導致代碼冗余。

 

首先,為了解決第一個問題,我們需要在vuex中引入一個getters.js文件:

1 export default {
2     getMessage(state) {
3         return state.msg
4     }
5 }

然后在store.js中引入getters.js

然后在兩個組件中修改引用store.state.msg方法

1 computed: {
2     msg() {
3         return this.$store.getters.getMessage
4     }
5 }

遺憾的是this.$store.getters這個符號仍然很長,我們一般都希望使用短一點的名字來表示變量,好消息是vue提供了mapGetters來幫助我們映射變量名,僅僅只需要引入並修改計算屬性:

 1 <!-- showInfo.vue -->
 2 <template>
 3     <h1>{{ getMessage }}</h1>
 4 </template>
 5 
 6 <script>
 7 import { mapGetters } from 'vuex'
 8 export default {
 9     computed: mapGetters(['getMessage'])
10 }
11 </script>

不過一個更好的方法是使用對象來代替mapGetters中的數組:

 1 <!-- showInfo.vue -->
 2 <template>
 3     <h1>{{ msg }}</h1>
 4 </template>
 5 
 6 <script>
 7 import { mapGetters } from 'vuex'
 8 export default {
 9     computed: mapGetters({
10         msg: 'getMessage'
11     })
12 }
13 </script>

現在,讓我們來體驗一下這種修改的好處吧。如果我們需要將輸入的所有字母轉化為大寫,只需要做一處修改src/vuex/getters.js:

1 export default {
2     getMessage(state) {
3         return (state.msg).toUpperCase()
4     }
5 }

這就像魔法一樣神奇!接着來解決第二個問題。

首先在store.js中添加counter屬性和相應的方法:

因此,在getters.js文件中:

1 export default {
2     getMessage(state) {
3         return (state.msg).toUpperCase()
4     },
5     getCounter(state) {
6         return (state.counter)
7     }
8 }

同時,在顯示組件showInfo.vue上顯示counter:

 1 <template>
 2     <div>
 3         <h1>{{ msg }}</h1>
 4         <div>The message was changed {{ counter }} times</div>
 5     </div>
 6 </template>
 7 
 8 <script>
 9 import { mapGetters } from 'vuex'
10 export default {
11     computed: mapGetters({
12         msg: 'getMessage',
13         counter: 'getCounter'
14     })
15 }
16 </script>

然后,在src/vuex中添加actions.js來管理函數調用的動作:

1 export default {
2     CHANGE_MSG({ commit }, msg) {
3         commit('changeMessage', msg)
4     },
5     ADD_COUNTER({ commit }) {
6         commit('addCounter')
7     }
8 }

然后像引用getters.js一樣在store.js中引用actions.js(同樣也用mapActions映射函數名),最后在changeInfo.vue組件中引用這兩個action:

 1 <!-- changeInfo.vue -->
 2 <template>
 3     <input type="text" :value="msg" 
 4     @keyup="chMsg($event.target.value)"
 5     @keyup.enter="addCnt">
 6 </template>
 7 
 8 <script>
 9 import { mapGetters } from 'vuex'
10 import { mapActions } from 'vuex'
11 export default {
12     computed: mapGetters({
13         msg: 'getMessage'
14     }),
15     methods: mapActions({
16         chMsg: 'CHANGE_MSG',
17         addCnt: 'ADD_COUNTER'
18     })
19 }
20 </script>

 源碼下載:https://files.cnblogs.com/files/viewts/vuex_demo.zip


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM