Vuex狀態(tài)機的快速了解與實例應用
一. 速識概念:
1. 組件之間共享數(shù)據(jù)的方式:
通常有以下幾種方式:
- 父向子傳值:v-bind 屬性綁定;
- 子向父傳值:v-on 事件綁定;
- 兄弟組件之間共享數(shù)據(jù):EventBus;
2. vuex是什么:
- 按照官方的話來說,Vuex 是一個專為 Vue.js 應用程序開發(fā)的狀態(tài)管理模式。它采用集中式存儲管理應用的所有組件的狀態(tài),并以相應的規(guī)則保證狀態(tài)以一種可預測的方式發(fā)生變化。Vuex 也集成到 Vue 的官方調(diào)試工具 devtools extension (opens new window),提供了諸如零配置的 time-travel 調(diào)試、狀態(tài)快照導入導出等高級調(diào)試功能。
- 簡單來說,Vuex就是實現(xiàn)組件全局狀態(tài)(數(shù)據(jù))管理的一種機制,可以方便的實現(xiàn)組件之間數(shù)據(jù)的共享。
3.使用vuex優(yōu)點:
- 能夠在vuex中集中管理共享的數(shù)據(jù),易于開發(fā)和后期維護。
- 能夠高效地實現(xiàn)組件之間的數(shù)據(jù)共享, 提高開發(fā)效率。
- 存儲在vuex中的數(shù)據(jù)都是響應式的,能夠實時保持數(shù)據(jù)與頁面的同步。
- 解決了非父子組件的消息傳遞(將數(shù)據(jù)存放在state中)。
- 減少了AJAX請求次數(shù),有些情景可以直接從內(nèi)存中的state獲取。
一般情況下,只有組件之間共享的數(shù)據(jù),才有必要存儲到vuex中。而對于組件中的私有數(shù)據(jù),就沒必要了,依舊存儲在組件自身的data中即可。當然,如果你想要都存在vuex中也是可以的。
二. 基本使用:
1.安裝依賴包:
npm install vuex --save
2.導入依賴包:
import Vue from 'vue' import Vuex from 'vuex' Vue.use(Vuex)
3.創(chuàng)建store對象:
import Vue from 'vue' import Vuex from 'vuex' Vue.use(Vuex) const store = new Vuex.Store({ //state中存放的就是全局共享的數(shù)據(jù) state: { count: 0 } })
4. 將store對象掛載到vue實例中:
new Vue({ el: '#app', store })
此時所有組件就可以從store中獲取數(shù)據(jù)了。
三.創(chuàng)建項目:
下面為創(chuàng)建一個vue項目流程,后面會有案例:
(1)打開cmd窗口輸入 vue ui 打開vue的可視化面板:
(2)選擇新建項目路徑:
(3)命名:
(4)手動選擇配置,注意用的是vue2版本:
(5)創(chuàng)建:
(6)下一步:
(7)創(chuàng)建成功,到對應目錄打開vscode開始編程:
(8)運行項目:
四. 講解前提:
前提(注意):
寫一個計數(shù)器小案例,從案例中配合概念能更快上手vuex。所以下面核心概念中的代碼部分是基于這個小案例來演示的。目標:寫兩個子組件,有一個公共count值,在父組件中,其中一個組件實現(xiàn)點擊后count值減1,一個組件實現(xiàn)點擊后count值增1。
父組件 App.vue 初始代碼:
<template> <div id="app"> <my-add></my-add> <p>--------------------</p> <my-reduce></my-reduce> </div> </template> <script> // 引入組件 import Add from './components/Add.vue' import Reduce from './components/Reduce.vue' export default { name: 'App', data() { return { } }, components: { 'my-add': Add, 'my-reduce': Reduce } } </script>
子組件Add.vue初始代碼:
<template> <div> <p>count值為:</p> <button>+1</button> </div> </template> <script> export default{ data() { return { } }, } </script>
子組件Reduce.vue初始代碼:
<template> <div> <p>count值為:</p> <button>-1</button> </div> </template> <script> export default{ data() { return { } }, } </script>
store對象初始代碼為:
import Vue from 'vue' import Vuex from 'vuex' Vue.use(Vuex) export default new Vuex.Store({ state: { count: 0 } })
初始效果:
五.核心概念:
1.state:
按照官方的話來說,如下:Vuex 使用單一狀態(tài)樹——是的,用一個對象就包含了全部的應用層級狀態(tài)。至此它便作為一個“唯一數(shù)據(jù)源 (SSOT)”而存在。這也意味著,每個應用將僅僅包含一個 store 實例。
簡單來說,就是State提供唯一的公共數(shù)據(jù)源, 所有共享的數(shù)據(jù)都要統(tǒng)一放到Store的State中進行存儲。
1.1 組件中訪問state的第一種方式:
組件中直接輸入以下命令:
this.$store.state.引用的數(shù)據(jù)名字
如在Add.vue子組件中引用:
<template> <div> <p>count值為:{{this.$store.state.count}}</p> <button>+1</button> </div> </template> //下面部分代碼跟前面一樣無改變,所以省略了
看效果,顯示了count的值為0:
1.2 組件中訪問state的第二種方式:
(1)從 vuex 中按需導入 mapState 函數(shù)
import { mapState } from 'vuex'
(2)通過剛才導入的mapState函數(shù),將當前組件需要的全局數(shù)據(jù),映射為當前組件的computed計算屬性:
computed: { ...mapState([count]) }
小知識:computed用來監(jiān)控自己定義的變量,該變量不在data里面聲明,直接在computed里面定義,然后就可以在頁面上進行雙向數(shù)據(jù)綁定展示出結果或者用作其他處理;
如在Reduce.vue子組件中引用:
<template> <div> <p>count值為:{{count}}</p> <button>-1</button> </div> </template> <script> import {mapState} from 'vuex' export default{ data() { return { } }, computed: { ...mapState(['count']) } } </script>
看效果,同樣顯示了count的值為0:
2. mutation:
按照官方的話來說,更改 Vuex 的 store 中的狀態(tài)的唯一方法是提交 mutation。Vuex 中的 mutation 非常類似于事件:每個 mutation 都有一個字符串的 事件類型 (type) 和 一個 回調(diào)函數(shù) (handler)。這個回調(diào)函數(shù)就是我們實際進行狀態(tài)更改的地方,并且它會接受 state 作為第一個參數(shù)。
簡單來說就是Mutation用于變更Store中的數(shù)據(jù)。
①只能通過mutation變更Store數(shù)據(jù),不可以直接操作Store中的數(shù)據(jù)。
②通過這種方式雖然操作起來稍微繁瑣一些,但是可以集中監(jiān)控所有數(shù)據(jù)的變化。
比如,要實現(xiàn)count值自增加1的操作,那就在先motations里定義一個自增加1的函數(shù)。然后對應子組件想用,該組件就直接引入mutation并調(diào)用對應的函數(shù)就好。
如下,Add.vue子組件要實現(xiàn)自增加1功能:
先在狀態(tài)機里的mutations里定義一個能實現(xiàn)自增的函數(shù)add:
export default new Vuex.Store({ state: { count: 0 }, mutations: { //自增加1函數(shù) add(state){ state.count++ } } })
2.1 觸發(fā)mutation的第一種方式:
Add.vue子組件里給按鈕綁定點擊事件,并觸發(fā)mutation:
<template> <div> <p>count值為:{{this.$store.state.count}}</p> <button @click="btnAdd">+1</button> </div> </template> <script> export default{ data() { return { } }, methods: { btnAdd() { // 第一種引入mutation的方式,觸發(fā)add函數(shù) this.$store.commit('add') } } } </script>
看效果實現(xiàn)了點擊自增:
2.2 觸發(fā)mutation并傳參數(shù):
當然,當組件里調(diào)用mutation里函數(shù)時,也是可以傳參數(shù)的。
比如,有一個自增函數(shù),但增多少看調(diào)用時傳入的參數(shù):
export default new Vuex.Store({ state: { count: 0 }, mutations: { // 傳入?yún)?shù),第一個一定是state,第二個為傳入的參數(shù) //自增加 n 的函數(shù) addN(state,n){ state.count+= n } } })
對應組件調(diào)用時要傳入?yún)?shù):
methods: { btnAdd2() { // 引入mutation的方式,觸發(fā)addN函數(shù) // 并傳參,自增加6吧 this.$store.commit('addN',6) } }
2.1 觸發(fā)mutation的第二種方式:
(1)從 vuex 中按需導入 mapMutations 函數(shù)
import { mapMutations } from 'vuex'
(2)通過剛才導入的mapMutations函數(shù),將需要的mutations函數(shù),映射為當前組件的methods方法:
methods: { ...mapMutations(['add','addN']) }
實戰(zhàn),實現(xiàn)Reduce.vue組件的點擊自減1的功能要求:
狀態(tài)機添加自減函數(shù):
export default new Vuex.Store({ state: { count: 0 }, mutations: { //自增加1函數(shù) add(state){ state.count++ }, // 自減1的函數(shù) sub(state){ state.count-- } } })
Reduce.vue組件點擊按鈕實現(xiàn)自減1:
<template> <div> <p>count值為:{{count}}</p> <button @click="btnSub">-1</button> </div> </template> <script> //導入 import {mapState,mapMutations} from 'vuex' export default{ data() { return { } }, computed: { ...mapState(['count']) }, methods: { // 映射mutation里的sub函數(shù) ...mapMutations(['sub']), // 要自減,調(diào)用sub函數(shù) btnSub(){ this.sub() } } } </script>
看效果:
3.Action:
至此,第四大點里的案例已經(jīng)完成,已經(jīng)實現(xiàn)了自增和自減,現(xiàn)在對案例做改進,要我們點擊按鈕一秒后再自增和自減,該怎么實現(xiàn)?可以在狀態(tài)機里的mutation里的函數(shù)是加一個1秒定時器嗎,這肯定是不行的,因為mutation里不支持異步操作,那咋辦,當當當,Action閃亮登場。
Action 可以包含任意異步操作,所以它用來處理異步任務。
Action 提交的是 mutation,而不是直接變更狀態(tài)。記住它并不能直接修改state里的數(shù)據(jù),只有mutation能修改。就是說,如果通過異步操作變更數(shù)據(jù),必須通過Action,而不能使用Mutation,但是在Action中還是要通過觸發(fā)Mutation的方式間接變更數(shù)據(jù)。
先在狀態(tài)機里定義Action:
export default new Vuex.Store({ state: { count: 0 }, mutations: { //自增加1函數(shù) add(state){ state.count++ }, // 自減1的函數(shù) sub(state){ state.count-- } }, // 定義action,里面的addAsync函數(shù)實現(xiàn)1秒后執(zhí)行mutation里的add函數(shù) actions: { addAsync(context) { setTimeout(()=>{ // 必須通過context.commit()觸發(fā)mutation才行 context.commit('add') },1000) } } })
Action 函數(shù)接受一個與 store 實例具有相同方法和屬性的 context 對象,因此你可以調(diào)用 context.commit 提交一個 mutation。
3.1 觸發(fā)Action的第一種方式:
更改組件Add.vue代碼,引入Action,實現(xiàn)異步自增操作。
<template> <div> <p>count值為:{{this.$store.state.count}}</p> <button @click="btnAdd">+1</button> </div> </template> <script> export default{ data() { return { } }, methods: { btnAdd() { // 第一種引入Action的方式,觸發(fā)addAsync函數(shù) // 這里的dispatch專門用來調(diào)用action函數(shù) this.$store.dispatch('addAsync') } } } </script>
看效果,實現(xiàn)1秒后自增:
3.2 觸發(fā)Action異步任務并傳參數(shù):
當然,當組件里調(diào)用action里函數(shù)時,也是可以傳參數(shù)的。
比如,有一個點擊1秒后才執(zhí)行的自增函數(shù),但增多少看調(diào)用時傳入的參數(shù):
定義:
export default new Vuex.Store({ state: { count: 0 }, mutations: { // 傳入?yún)?shù),第一個一定是state,第二個為傳入的參數(shù) //自增加 n 的函數(shù) addN(state,n){ state.count+= n } }, actions: { // 有參數(shù) n,這個n又傳給了mutation里的addN函數(shù) addNAsync(context,n) { setTimeout(()=>{ context.commit('addN',n) },1000) } } })
對應組件調(diào)用時要傳入?yún)?shù):
methods: { btnAdd2() { // 調(diào)用dispatch函數(shù) // 觸發(fā)action時傳參數(shù),為 6 吧,表示自增6 this.$store.dispatch('addNAsync',6) } }
3.3 觸發(fā)Action的第二種方式:
(1)從 vuex 中按需導入 mapActions 函數(shù)
import { mapActions } from 'vuex'
(2)通過剛才導入的mapActions函數(shù),將需要的actions函數(shù),映射為當前組件的methods方法:
methods: { ...mapActions(['add','addN']) }
實戰(zhàn),實現(xiàn)Reduce.vue組件的點擊一秒后自減1的功能要求:
定義actions里的subAsync為一秒后自減函數(shù):
export default new Vuex.Store({ state: { count: 0 }, mutations: { //自增加1函數(shù) add(state){ state.count++ }, // 自減1的函數(shù) sub(state){ state.count-- } }, actions: { addAsync(context) { setTimeout(()=>{ context.commit('add') },1000) }, subAsync(context) { setTimeout(()=>{ context.commit('sub') },1000) } } })
更改Reduce.vue代碼,實現(xiàn)功能:
<template> <div> <p>count值為:{{count}}</p> <button @click="btnSub">-1</button> </div> </template> <script> //導入 import {mapState,mapActions} from 'vuex' export default{ data() { return { } }, computed: { ...mapState(['count']) }, methods: { // 映射Action里的函數(shù) ...mapActions(['subAsync']), // 要自減,調(diào)用subAsync函數(shù) btnSub(){ this.subAsync() } } } </script>
看效果:
4. Getter:
Getter用于對Store中的數(shù)據(jù)進行加工處理形成新的數(shù)據(jù)。且要注意的是它并不會修改state中的數(shù)據(jù)。
①Getter 可以對Store中已有的數(shù)據(jù)加工處理之后形成新的數(shù)據(jù),類似Vue的計算屬性。
②Store 中數(shù)據(jù)發(fā)生變化,Getter 的數(shù)據(jù)也會跟著變化。
如,有一個返回當前count+1的getter函數(shù):
export default new Vuex.Store({ state: { count: 0 }, getters: { showNum(state){ return`當前count值加1為:${state.count+1}` } } })
4.1 觸發(fā)getters的第一種方式:
this.$store.getters.名稱
在App.vue組件中顯示:
<template> <div id="app"> <my-add></my-add> <p>--------------------</p> <my-reduce></my-reduce> <p>--------------------</p> <h3>{{this.$store.getters.showNum}}</h3> </div> </template>
效果:
4.2觸發(fā)getters的第二種方式:
(1)從 vuex 中按需導入 mapGetters 函數(shù)
import { mapGetters } from 'vuex'
(2)通過剛才導入的mapGetters函數(shù),將當前組件需要的全局數(shù)據(jù),映射為當前組件的computed計算屬性:
computed: { ...mapGetters(['showNum']) }
還是在App.vue中使用把:
<template> <div id="app"> <my-add></my-add> <p>--------------------</p> <my-reduce></my-reduce> <p>--------------------</p> <h3>{{showNum}}</h3> </div> </template> <script> // 引入組件 import Add from './components/Add.vue' import Reduce from './components/Reduce.vue' // 導入 mapGetters函數(shù) import {mapGetters} from 'vuex' export default { name: 'App', data() { return { } }, components: { 'my-add': Add, 'my-reduce': Reduce }, // 引入 getter computed: { ...mapGetters(['showNum']) } } </script>
看,一樣的效果:
六.總結:
到此這篇關于Vuex狀態(tài)機的快速了解與實例應用的文章就介紹到這了,更多相關Vuex狀態(tài)機應用內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
vue實現(xiàn)兩級select聯(lián)動+input賦值+select選項清空
這篇文章主要介紹了vue實現(xiàn)兩級select聯(lián)動+input賦值+select選項清空過程,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-08-08詳解從零搭建 vue2 vue-router2 webpack3 工程
本篇文章主要介紹了詳解從零搭建 vue2 vue-router2 webpack3 工程,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-11-11Vue異步更新DOM及$nextTick執(zhí)行機制解讀
這篇文章主要介紹了Vue異步更新DOM及$nextTick執(zhí)行機制解讀,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-03-03elementUI+Springboot實現(xiàn)導出excel功能的全過程
這篇文章主要介紹了elementUI+Springboot實現(xiàn)導出excel功能,現(xiàn)在也對這個導出功能進行一個匯總整理寫出來,結合實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2022-09-09