【Vue】15 VueX
【什麼是VueX?】
VueX是一個專門為Vue.js應用程式開發的狀態管理模式,
採用集中式儲存管理應用的所有元件狀態,
以相應的規則保證按照一種可預測的方式發生改變。
即把多個元件的變數統一放到一個地方管理
在專案中安裝Vuex
npm install vuex
新建store目錄和一個index.js
並寫入以下程式碼:
import Vue from 'vue'; import VueX from 'vuex'; Vue.use(VueX); const store = new VueX.Store({ state : { count : 0 }, mutations : { increment(state) { state.count++; }, decrement(state) { state.count--; } } }); export default store;
其次,我們要讓所有的Vue元件,都能使用store,
就需要在main.js中引入,引入方式與router一樣
import Vue from 'vue' import App from './App.vue' import router from "./router"; // ./router/index.js 因為是index.js,可以預設不寫 import store from "./store"; Vue.config.productionTip = false new Vue({ render: h => h(App), router, store }).$mount('#app');
在任意一個Vue元件中插值引入:
<template> <div> <h2>樣本的標題</h2> <p>樣本的標籤</p> <p>{{$store.state.count}}</p> </div> </template> <script> export default { name: "sample" } </script> <style scoped> </style>
可以看到這裡已經完全取出來了
然後再編寫兩個按鈕和對應的事件:
<template> <div> <h2>樣本的標題</h2> <p>樣本的標籤</p> <p> <button @click="decrease">減少</button> {{$store.state.count}} <button @click="increase">增加</button> </p> </div> </template> <script> export default { name: "sample", methods : { decrease() { this.$store.commit("decrement"); }, increase() { this.$store.commit("increment"); } } } </script> <style scoped> </style>
檢視效果:
然後再主頁面也渲染這個變數:
可以發現,是一樣的:
就是為了一些公共變數而存在的
【State】
Vuex提出使用單一狀態樹,(單一資料來源),就是將一堆公共的資料放到一起去管理
state的意義類似Vue例項的data物件,所有的資料資訊存放state中,但是訪問不建議也像vue那樣直接引用
【Gettter】
我們需要從state中獲取一些經過改變後的資料,可以使用getter
store的index.js
import Vue from 'vue'; import VueX from 'vuex'; Vue.use(VueX); const store = new VueX.Store({ state : { count : 0, studentList : [ { id : 1, name : "張三", age : 23, gender : true }, { id : 2, name : "李四", age : 24, gender : true }, { id : 3, name : "王五", age : 25, gender : true }, { id : 4, name : "阿偉", age : 26, gender : true }, { id : 5, name : "傑哥", age : 27, gender : true }, ] }, mutations : { increment(state) { state.count++; }, decrement(state) { state.count--; } }, getters : { getStudentByAge(state) { return state.studentList.filter(e => e.age > 24); } } }); export default store;
在元件中可以通過this.$store.getters.xxx獲取
<p> {{$store.getters.getStudentByAge}} </p>
效果:
【Mutations】
用於對state中的資料進行修改,或者是傳值,類似vue例項的methods
呼叫mutations中的方法,需要這樣:
this.$store.commit('方法名稱',引數列表)
【Actions】
需要注意的是,我們不會在mutations進行非同步操作:【使用規範】
但是在某些特定需求的情況下必須使用:比如ajax非同步請求
這時候我們就可以使用actions處理:
作用就是為了代替mutations來完成這種功能
context引數,是和Store物件具有相同方法和屬性的物件
即我們可以使用context.commit呼叫mutations
import Vue from 'vue'; import VueX from 'vuex'; Vue.use(VueX); const store = new VueX.Store({ state : { count : 0, studentList : [ { id : 1, name : "張三", age : 23, gender : true }, { id : 2, name : "李四", age : 24, gender : true }, { id : 3, name : "王五", age : 25, gender : true }, { id : 4, name : "阿偉", age : 26, gender : true }, { id : 5, name : "傑哥", age : 27, gender : true }, ] }, mutations : { increment(state) { state.count++; }, decrement(state) { state.count--; } }, getters : { getStudentByAge(state) { return state.studentList.filter(e => e.age > 24); } }, actions : { increa(context) { context.commit('increment'); } } }); export default store;
呼叫actions的方法需要使用dispatch分發
<template> <div> <h2>樣本的標題</h2> <p>樣本的標籤</p> <p> <button @click="decrease">減少</button> {{$store.state.count}} <button @click="increase">增加</button></p> </div> </template> <script> export default { name: "sample", methods : { decrease() { this.$store.commit("decrement"); }, increase() { // this.$store.commit("increment"); this.$store.dispatch('increa'); } } } </script> <style scoped> </style>
其實對比發現,就是多一個action處理:
actions可用於非同步操作,即可以使用Promise,
在非同步操作中放入Promise,成功或者失敗後,呼叫對應函式
import Vue from 'vue'; import VueX from 'vuex'; Vue.use(VueX); const store = new VueX.Store({ state : { count : 0, studentList : [ { id : 1, name : "張三", age : 23, gender : true }, { id : 2, name : "李四", age : 24, gender : true }, { id : 3, name : "王五", age : 25, gender : true }, { id : 4, name : "阿偉", age : 26, gender : true }, { id : 5, name : "傑哥", age : 27, gender : true }, ] }, mutations : { increment(state) { state.count++; }, decrement(state) { state.count--; } }, getters : { getStudentByAge(state) { return state.studentList.filter(e => e.age > 24); } }, actions : { increa(context) { context.commit('increment'); }, mp(context) { return new Promise(resolve => { setTimeout(() => { context.commit("decrement"); resolve(); }, 1000); }); } } }); export default store;
元件這裡:
<template> <div> <h2>樣本的標題</h2> <p>樣本的標籤</p> <p> <button @click="decrease">減少</button> {{$store.state.count}} <button @click="increase">增加</button></p> </div> </template> <script> export default { name: "sample", methods : { decrease() { // this.$store.commit("decrement"); this.$store.dispatch('mp').then(res => { alert("資料跟新完畢"); }); }, increase() { // this.$store.commit("increment"); this.$store.dispatch('increa'); } } } </script> <style scoped> </style>
每次點選減少按鈕就會晚一秒執行,然後再彈窗警告:
【Modules】
模組,vuex使用了單一狀態樹,當我們的狀態過多時,使用store管理可能臃腫,這時候可以按照模組區劃分vuex的store資料
當然,store還是可以統一管理module的
每個module即一個小的vuex,都具備上面的那些屬性【getters,state,actions . . .】
import Vue from 'vue'; import VueX from 'vuex'; Vue.use(VueX); const user = { state : { studentList : [ { id : 1, name : "張三", age : 23, gender : true }, { id : 2, name : "李四", age : 24, gender : true }, { id : 3, name : "王五", age : 25, gender : true }, { id : 4, name : "阿偉", age : 26, gender : true }, { id : 5, name : "傑哥", age : 27, gender : true }, ], token : "", name : '', header : '', }, getters : { getStudentByAge(state) { return state.studentList.filter(e => e.age > 24); } } } const baseData = { state : { count : 0, }, mutations : { increment(state) { state.count++; }, decrement(state) { state.count--; } }, actions : { increa(context) { context.commit('increment'); }, mp(context) { return new Promise(resolve => { setTimeout(() => { context.commit("decrement"); resolve(); }, 1000); }); } } } const store = new VueX.Store({ modules : { user, baseData } }); export default store;
元件中的呼叫也需要更改:
<p> {{$store.state.baseData.count}} </p> <p> {{$store.getters.getStudentByAge}} </p>
如果再index.js有太多的模組,可以抽取成檔案,引入使用: