Vuex使用详解,附加项目遇到的问题(简单明了)
?
Vuex的定義、個人理解和結構解析
?
vuex定義:vuex是一個專門為vue.js設計的集中式狀態管理架構。
vuex的個人理解:
是存儲公有狀態數據state的一個倉庫(store);解決了大型應用時組件傳參的繁雜和不易維護性;vuex的狀態儲存是響應的,store中狀態發生改變后相應組件會得到更新;不能直接修改store中的狀態,唯一途徑是顯示的提交(commit)mutation, 可以通過getter獲取state的派生值;
?
Vuex結構組成:
Store(倉庫):
State(狀態):負責存儲應用的狀態數據,可以理解為數據容器;組件中獲取vuex中的數據時使用this.$store.state.stateName來獲取;
Mutations(變化):利用它來更改狀態state數據,本質是處理數據的函數,其接收唯一參數值state。我們可以在methods方法中使用this.$store.commit(‘mutationName’);來觸發一個mutation的方法;必須是同步函數,否則devtool中的數據將會出現問題;
Actions:通過觸發mutation來修改state狀態,重要的是可以異步改變state狀態,在methods方法中使用this.$store.dispatch(actionName);直接觸發
Getters:有些狀態需要進行二次處理就可以使用getters,可以在方法中使用this.$store.getters.valueName對派生出來的狀態數據進行訪問;當依賴發生改變時會改變
?
mapActions、mapMutations、mapGetters、mapState:是利用輔助函數將actions、mutations、getters、state映射到本地計算屬性或methods方法中去;使用前需引入映射如:? ? import {mapGetters} from ‘vuex’
?
vuex的demo實踐:
第一步:創建項目
? ? 基于vue-cli腳手架生成一個vue項目;
? ? 常用命令:
? ? ? ? npm i vue-cli --g ? ? ? ? ? ? ? ? ? ? 來安裝vue-cli
? ? ? ? ?vue --vesion? 或? vue -V ? ? ?? 來檢查vue安裝是否成功
? ? ? ? ?vue init webpack 項目名 ? ? ? 來創建vue-cli 腳手架項目
?
注意:當運行 npm i vue-cli --g 安裝vue-cli報 “?WARN deprecated coffee-script@1.12.7: CoffeeScript on NPM has moved to "coffeescript" (no hyphen) ” 錯誤時可以嘗試 使用 ? cnpm i vue-cli --g? 安裝
?
第二步:檢查項目是否創建成功,安裝vuex
? ? ? ? ? npm run dev ? ? ? ? ? ? ? ? ? ? ?? 來運行vue項目
? ? ? ? ? npm i vuex --save ? ? ? ? ? ? ??來安裝vuex
?
第三步:代碼實現父子組件通過vuex傳遞參數Demo
效果:
?
1、項目文件結構如下: 創建父子組件文件和store.js文件
?
2、Store.js文件引用vuex如下:
import Vue from 'vue'; import Vuex from 'vuex';//vue引用vuex Vue.use(Vuex);//state狀態數據容器 const state={testMsg:"state中的一行測試文本",parentMsg:"父組件原始文本",childMsg:"子組件原始文本",count:99, }//修改satate的方法,就是state狀態數據的處理函數 const mutations= {changeParentMsg:function(state,str){state.parentMsg=str;},changeChildMsg:function(state,str){state.childMsg=str;}, }//異步,通過commit觸發mutations中的方法來修改state const actions={changeParentTxt({commit},data){commit('changeParentMsg',data);},changeChildTxt:function(context,data){context.commit('changeChildMsg',data);},//上述兩個方法中的參數使用{commit}和context均有效,context代表store本身 }//對獲取到的state數據進行過濾修改 const getters={countNum:function(state){if(state.count>100){return state.count+100;}else {return state.count-50;}} }//創建store實例,將在main.js文件中將它加入到vue實例對象中 export default new Vuex.Store({ //export default 是封裝代碼,使外部可用state, //依此加入到store對象中mutations,actions,getters, });3、Main.js文件在vue實例中引用store對象:
將store實例從根組件中‘注入’到子組件中,子組件通過‘this.$store’調用
?
4、組件文件:
? ? ?HelloWorld.vue
<template><div class="hello"><h3>測試文本如下:</h3><p>在組件模板中直接輸出獲取值:{{$store.state.testMsg}}</p><hr><Parent></Parent><hr><h4>getters獲取state的值修改后如下:</h4><p>{{$store.getters.countNum}}</p></div> </template><script> import Parent from './Parent' export default {name: 'HelloWorld',data () {return {msg: 'Welcome to Your Vue.js App'}},components:{Parent}, } </script><!-- Add "scoped" attribute to limit CSS to this component only --> <style scoped> h1, h2 {font-weight: normal; } ul {list-style-type: none;padding: 0; } li {display: inline-block;margin: 0 10px; } a {color: #42b983; }</style>? ? ?Parent.vue
<template><div><div class="parentContainer"><div><h3>父組件的內容:</h3><p class="txt">{{oldtxt}}</p></div><button class="btn" @click="changeParentTxt()">點擊更改父組件內容</button><button class="btn" @click="changeChildTxt()">點擊更改子組件內容</button></div><Child></Child></div> </template> <style>.parentContainer {height:150px;width:350px;background-color: lightblue;color:#fff;margin:10px auto;}.txt {border:1px solid red;padding:10px;}.btn {background-color: #fff;color: #000;} </style> <script>import Child from './Child'export default {name:"Parent",data(){return {}},components:{Child,},computed:{oldtxt:function(){return this.$store.state.parentMsg;}},methods:{changeParentTxt:function(){let newParentTxt="更改后的父組件內容變長的很多!!!";this.$store.dispatch('changeParentTxt',newParentTxt);},changeChildTxt:function(){let newChildTxt="這里是父組件點擊修改后的文本內容....";this.$store.dispatch('changeChildTxt',newChildTxt);},},} </script>?
? ? ?Child.vue
<template><div class="childContainer"><div><h3>子組件的內容:</h3><p class="txt">{{oldtxt}}</p></div><button class="btn" @click="changeChildTxt2()">點擊更改子組件內容</button><button class="btn" @click="changeParentTxt2()">點擊更改父組件內容</button></div> </template> <style>.childContainer {height:150px;width:350px;background-color: lightcoral;color:#fff;margin:10px auto;}.txt {border:1px solid red;padding:10px;}.btn {background-color: #fff;color: #000;} </style> <script>export default {name:"Child",data(){return {}},computed:{oldtxt:function(){return this.$store.state.childMsg;}},methods:{changeParentTxt2:function(){let newParentTxt="我這是通過子組件修改父組件state后獲取到的文字!!!";this.$store.dispatch('changeParentTxt',newParentTxt);},changeChildTxt2:function(){let newChildTxt="點擊子組件按鈕后內容變成了這樣!!!";this.$store.dispatch('changeChildTxt',newChildTxt);},},} </script>?
Vuex在項目中代碼使用詳解
1、組件模板獲取state狀態數據:將狀態對象賦值給內部對象,也就是將stroe.js中的值賦值給模板中的data中的值,有三種賦值方式:
? ? ? ①使用computed計算屬性直接賦值;
? ? ? ②使用mapState輔助函數來賦值(將state值映射到局部計算屬性);
? ? ? ③使用mapState的數組來賦值;
<div>computed計算屬性獲取的值:{{count01}}</div><div>使用mapState輔助函數來賦值:{{count02}} </div><div>使用mapState的數組來賦值:{{count}} </div> computed:{ //多個computed時,后面的會覆蓋前面的count01(){ //普通計算屬性return this.$store.state.count;},...mapState({ //mapState(obj)對象輔助函數賦值count02:(state)=>{return state.count} //ES6的箭頭函數}),...mapState(['count']) //mapState(arr)數組來賦值}?
2、getters獲取的是經過加工過濾后的state狀態數據。
//store.js中getters定義 //對獲取到的state數據進行過濾修改 const getters={changeCount:function(state){if(state.count>100){return state.count*2;}else {return state.count-1;}} }const mutations= {addCount:function(state,num){return state.count+=num;}, } // 組件模板中使用mapGetters <template><div class="childContainer"><h3>原值:{{count}}</h3><h3>getter加工過濾后的值:{{changeCount}}</h3><button @click="$store.commit('addCount',20)">點擊數字加20</button></div> </template> <script> import {mapState,mapMutations, mapGetters} from 'vuex'export default {name:"Child",data(){return {}},computed:{...mapState(['count']),...mapGetters(['changeCount']),},methods:{...mapMutations(['reduceCount']),},} </script>同理在組件模板可以通過this.$store.getters.changeCount來獲取store中過濾更改后的count值;
mapGetters輔助函數和mapState輔助函數類似是將store中的getter 映射到局部計算屬性computed中,mapGetters使用前先import引入;
?
3、組件模板更改store中的state值通過mutations中的方法:mutations同步更改狀態($store.commit('mutationName'))的方式:
? ?? ①使用this.$store.commit('mutationName');
//store.js //mutations中更改satate的方法,就是state狀態數據的處理函數 const mutations= {addCount:function(state,num){return state.count+=num;},reduceCount:function(state,num){return state.count-=num;}, } <button class="btn" @click="$store.commit('addCount',50)">點擊使用commit直接觸發mutations中的方法</button>? ?
②使用mapMutations輔助函數將mutations中的方法映射到methods中;?
a、組件中首先需要使用import 引入mapMutations和mapState(依賴性),如
import {mapState,mapMutations} from 'vuex'b、將mutations中的方法映射到methods中;?
methods:{...mapMutations(['reduceCount']), },c、組件模板中直接使用映射的方法如:
<button class="btn" @click="reduceCount(20)">通過mapMutations觸發mutations中的方法</button>?
4、actions異步更改狀態state,actions方法通過mutations中方法來更改state,actions中的方法有兩種寫法如下:
//異步,通過commit觸發mutations中的方法來修改state const actions={changeParentTxt({commit},data){commit('changeParentMsg',data);},changeChildTxt:function(context,data){context.commit('changeChildMsg',data);},//上述兩個方法中的參數使用{commit}和context均有效,context代表store本身 }mapActions的使用類似mapMutations將方法映射到methods中,組件模板使用前先 import 引用mapActions、mapMutations、mapState;
methods:{changeCountNum:function(){this.$store.dispatch("countNum_action",99); //$store.dispatch("actionName");直接觸發actions中的方法}, },?
5、module模塊組:為解決state狀態對象過多而雜的問題,我們將一個store劃分為多個module模塊,每個模塊擁有自己的state、mutations、actions、getters使用如下
①store.js中是聲明modules
//聲明模塊組module const moduleA={state:{name:'zhangsan',age:27},mutations:{},actions:{},getters:{} };const moduleB={state:{name:'wangwu',age:26},mutations:{},actions:{},getters:{} };export default new Vuex.Store({modules:{a:moduleA,b:moduleB} //使用a做為moduleA的別名,b同理 });②模板組件中獲取指定module中的state數據有以下兩種方式
<div>模塊A的name值是:{{$store.state.b.name}}</div> computed:{moduleAname:function(){return this.$store.state.a.name;} },?
PS附加:
1、如果store文件太大,也可以將 action、mutation 和 getter 分割到單獨的文件。分割的文件需要export? default 導出,并在store.js文件中的import 導入,如下
//mymutations.js 文件 const mutations= {changeParentMsg:function(state,str){state.parentMsg=str;},changeChildMsg:function(state,str){state.childMsg=str;}, } export default mutations import state from './mystate' import mutations from './mymutation' import actions from './myactions'export default new Vuex.Store({state, mutations,actions,getters, });2、在vue 的構造器里邊只能有一個computed屬性,如果你寫多個,只有最后一個computed屬性可用;
?
3、vuex數據在頁面刷新時數據會丟失問題,解決思路是vuex更改state數據時同時存儲到sessionStorage,當getters獲取state數據時判斷state為空時對應sessionStorage是否存在,為true則獲取sessionStorage賦值給丟失了數據的stateName,如下:
//store.js中定義getters獲取時為空會判斷從sessionStorage獲取值或初始值 const getters={countNum:function(state){if(!state.count){state.count=10; //首次num數值為空初始值賦值為10let sessionVal=sessionStorage.getItem("count_num");if(sessionVal){state.count=parseInt(sessionVal);}}return state.count} }//store.js中定義mutations更改state后存儲到sessionStorage const mutations= {change_numCount:function(state,data){state.count=data;sessionStorage.setItem('count_num',data);}, } //組件模板中觸發更改state狀態數據的action方法 methods:{changeCountNum:function(){ this.$store.dispatch("countNum_action",99);}, },?
參考網址:https://blog.csdn.net/H5_QueenStyle12/article/details/75386359
https://blog.csdn.net/mjzhang1993/article/details/78321903
總結
以上是生活随笔為你收集整理的Vuex使用详解,附加项目遇到的问题(简单明了)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: [NOI2009] 植物大战僵尸
- 下一篇: codeforces 7.22 E Pe