一文帶你搞懂Vue中Vuex的使用
VUEX使用詳解
01-vuex基礎(chǔ)-介紹
組件共享數(shù)據(jù)/通信的方式有哪些?
- 父?jìng)髯油ㄐ?=》通過props把父組件的數(shù)據(jù)傳遞給子組件
- 子傳父 =》1. 父組件定義自定義事件和回調(diào)函數(shù)(接收子組件數(shù)據(jù))2. 通過this.$emit('自定義事件名', data)
結(jié)論:組件通信的目的=》共享數(shù)據(jù)給其它組件使用
Vuex 是一個(gè)專為 Vue.js 應(yīng)用程序開發(fā)的狀態(tài)管理模式。它采用集中式存儲(chǔ)管理應(yīng)用的所有組件的狀態(tài),并以相應(yīng)的規(guī)則保證狀態(tài)以一種可預(yù)測(cè)的方式發(fā)生變化。
我們理解:
- vuex是采用集中式管理組件依賴的共享數(shù)據(jù)的一個(gè)工具vue插件,可以解決不同組件數(shù)據(jù)共享問題。
- state 管理數(shù)據(jù),管理的數(shù)據(jù)是響應(yīng)式的,當(dāng)數(shù)據(jù)改變時(shí)驅(qū)動(dòng)視圖更新。=》類似組件的data
- mutations 更新數(shù)據(jù),state中的數(shù)據(jù)只能使用mutations去改變數(shù)據(jù)。
- actions 請(qǐng)求數(shù)據(jù),響應(yīng)成功后把數(shù)據(jù)提交給mutations
使用原則/場(chǎng)景:如果你不知道是否需要 vuex,那就是不需要它。適合在一些比較復(fù)雜和大型的項(xiàng)目中使用。
大型的項(xiàng)目:頁面數(shù)量=》大于100個(gè)=》大型項(xiàng)目
擴(kuò)展閱讀:
02-vuex基礎(chǔ)-初始化和基本使用
使用cli快速創(chuàng)建和配置項(xiàng)目
說明:注意選擇vuex插件
基本使用步驟
初始化:
- 第一步:
npm i vuex --save
=》創(chuàng)建項(xiàng)目沒選擇vuex,需要單獨(dú)安裝和初始化 - 第二步: 創(chuàng)建store.js
import vuex from 'vuex'
import vue from 'vue'
- 第三步:
Vue.use(vuex)
=>注冊(cè) - 第四步:
const store = new Vuex.Store({...配置項(xiàng)})
- 第五步:導(dǎo)出
export default store
- 第六步:導(dǎo)入main.js 在根實(shí)例配置 store ,選項(xiàng)指向 store 實(shí)例對(duì)象
store.js
// 初始化一個(gè)vuex的實(shí)例(數(shù)據(jù)倉庫) 導(dǎo)出即可 import Vuex from 'vuex' import Vue from 'vue' // 使用注冊(cè) Vue.use(Vuex) // 初始化 const store = new Vuex.Store({ // 配置(state|mutations|actions) }) export default store
main.js
+import store from '@/store' new Vue({ // 注入store實(shí)例=》所有組件=》訪問this.$store + store, render: h => h(App), }).$mount('#app')
03-vuex基礎(chǔ)-state
基本用法
管理數(shù)據(jù)=>類似組件data
// 初始化vuex對(duì)象 const store = new vuex.Store({ state: { // 管理數(shù)據(jù) count: 0 } })
獲取數(shù)據(jù)
1.在組件獲取state的數(shù)據(jù):原始用法插值表達(dá)式
<div>A組件 state的數(shù)據(jù):{{$store.state.count}}</div>
2.使用計(jì)算屬性
// 把state中數(shù)據(jù),定義在組件內(nèi)的計(jì)算屬性中 computed: { // 1. 最完整的寫法 // count: function () { // return this.$store.state.count // }, // 2. 縮寫 count () { return this.$store.state.count } } // 不能使用剪頭函數(shù) this指向的不是vue實(shí)例
輔助用法
說明:當(dāng)一個(gè)組件需要獲取多個(gè)狀態(tài)的時(shí)候,將這些狀態(tài)都聲明為計(jì)算屬性會(huì)有些重復(fù)和冗余。
作用:
- 把vuex中的state數(shù)據(jù)映射到組件的計(jì)算屬性中。
- 輔助函數(shù),生成計(jì)算屬性。
- 方便使用store中的數(shù)據(jù)
導(dǎo)入:
import { mapState } from 'vuex'
1.使用:mapState(對(duì)象) (了解)
// 使用mapState來生成計(jì)算屬性 mapState函數(shù)返回值是對(duì)象 // 使用mapState使用對(duì)象傳參 computed: mapState({ // 1. 基礎(chǔ)寫法 (state) 代表就是vuex申明的state count1: function (state) { return state.count }, // 2. 使用箭頭函數(shù) count2: state => state.count, // 3. vuex提供寫法 (count是state中的字段名稱) count3: 'count', // 4. 當(dāng)你的計(jì)算屬性 需要依賴vuex中的數(shù)據(jù) 同時(shí) 依賴組件中data的數(shù)據(jù) myCount (state) { return state.count + this.num } })
2.使用:mapState(數(shù)組)(了解)
// 使用mapState使用數(shù)組傳參 computed: mapState(['count']) =>返回對(duì)象
3.如果組件自己有計(jì)算屬性,state的字段映射成計(jì)算屬性=>推薦
computed: { // 通過mapState映射,生成計(jì)算屬性 =》count相當(dāng)于計(jì)算屬性變量 ...mapState(['count']) }
04-vuex基礎(chǔ)-mutations
基本用法
修改數(shù)據(jù)
vuex的store中聲明:
// 修改數(shù)據(jù)的配置 mutations: { // 定義修改數(shù)據(jù)的函數(shù) // 自增的函數(shù) // state 當(dāng)前申明的state選項(xiàng)中的數(shù)據(jù) // params 接受數(shù)據(jù) , payload 載荷(運(yùn)送數(shù)據(jù))建議對(duì)象{}形式 increment (state, payload) { // 此時(shí)的this獲取不到count數(shù)據(jù) state.count = state.count + payload.num } }
組件調(diào)用:
methods: { fn () { // 調(diào)用vuex申明的mutations函數(shù) // 第一個(gè)參數(shù):函數(shù)名稱 // 第二個(gè)參數(shù):調(diào)用函數(shù)的時(shí)候的傳參 官方叫payload this.$store.commit('increment', {num: 100}) } },
注意:
- Mutation 需遵守 Vue 的響應(yīng)規(guī)則
- Mutation 必須是同步函數(shù)
輔助用法
說明:
- 把vuex中的mutations的函數(shù)映射到組件的methods中
- 通俗:通過mapMutations函數(shù)可以生成methods中函數(shù)
導(dǎo)入:
import { mapMutations } from 'vuex'
使用:
methods: { // 使用對(duì)象 // 相當(dāng)于 methods申明了一個(gè)函數(shù)fn(params){ this.$store.commit('increment', params)} // ...mapMutations({ // // fn 是methods函數(shù)名稱 // // 'increment' vuex中的mutations中的函數(shù)名 // fn: 'increment' // }) // 使用數(shù)組 // 相當(dāng)于 methods申明了一個(gè)函數(shù)increment(params){ this.$store.commit('increment', params)} ...mapMutations(['increment']), // 調(diào)用 handlerAdd () { // this.$store.commit('add', { num: 10 }) this.increment({ num: 10 }) } },
注意:需要先在根節(jié)點(diǎn)注入 store
05-vuex基礎(chǔ)-actions
基本用法
說明:異步獲取后臺(tái)數(shù)據(jù)=》mutation 來記錄 action 產(chǎn)生的副作用
vuex定義:
// 異步獲取數(shù)據(jù) actions: { // actions 中的函數(shù)有默認(rèn)傳參 context // context 術(shù)語:執(zhí)行上下文 執(zhí)行環(huán)境 大白話:函數(shù)能夠使用到的對(duì)象(vuex實(shí)例===this.$store) getData ({commit}, num) { // 模擬異步的獲取數(shù)據(jù) window.setTimeout(()=>{ const data = num // 通過commit提交數(shù)據(jù)給mutations修改數(shù)據(jù) commit('add', data) },2000) // Promise形式 // return new Promise((r) => { // setTimeout(() => { // commit('add', num); // r() // }, 2000) // }) } }
組件使用:
getData () { // 發(fā)請(qǐng)求獲取數(shù)據(jù) // this.$store.dispatch('getData') this.$store.dispatch('getData',{ num: 10 }) },
注意:
- Action 提交的是 mutation,而不是直接變更狀態(tài)。
- Action 可以包含任意異步操作。
輔助用法
說明:
- mapActions輔助函數(shù),把a(bǔ)ctions中的函數(shù)映射組件methods中
- 通俗:通過mapActions函數(shù)可以生成methods中函數(shù)
methods: { // 相當(dāng)于 methods申明了一個(gè)函數(shù)fn(num){ this.$store.dispatch('getData', num)} // ...mapActions({ // fn: 'getData' // }) // 相當(dāng)于 methods申明了一個(gè)函數(shù)getData(num){ this.$store.dispatch('getData', num)} ...mapActions(['getData']), // 調(diào)用 handlerAdd2 () { // this.$store.dispatch('getData', { num: 10 }) this.getData({ num: 10 }) } }
注意:需要先在根節(jié)點(diǎn)注入 store
06-vuex基礎(chǔ)-getters
基本用法
除了state之外,有時(shí)我們還需要從state中派生出一些狀態(tài),這些狀態(tài)是依賴state的,此時(shí)會(huì)用到getters(類似組件中計(jì)算屬性,依賴值變化會(huì)重新執(zhí)行計(jì)算)
說明:類似vue組件中計(jì)算屬性computed
例如,state中定義count值
state: { count: 0 }
組件中,需要顯示count值減一
定義getters
getters: { // getters函數(shù)的第一個(gè)參數(shù)是 state // 必須要有返回值 countSub: state => state.count - 1 }
使用getters
<div>{{ $store.getters.countSub }}</div>
輔助用法
computed: { ...mapGetters(['countSub']) }
<div>{{ countSub }}</div>
07-vuex基礎(chǔ)-modules
為什么會(huì)有模塊化?
由于使用單一狀態(tài)樹,應(yīng)用的所有狀態(tài)會(huì)集中到一個(gè)比較大的對(duì)象。當(dāng)應(yīng)用變得非常復(fù)雜時(shí),store 對(duì)象就有可能變得相當(dāng)臃腫。
這句話的意思是,如果把所有的狀態(tài)都放在state中,當(dāng)項(xiàng)目變得越來越大的時(shí)候,Vuex會(huì)變得越來越難以維護(hù)
由此,又有了Vuex的模塊化
模塊化的簡(jiǎn)單應(yīng)用
應(yīng)用
定義兩個(gè)模塊 user 和 setting
需求:
- user中管理用戶的狀態(tài) token
- setting中管理 應(yīng)用的名稱 name
定義這兩個(gè)module數(shù)據(jù)
const store = new Vuex.Store({ modules: { user: { state: { token: '12345' } }, setting: { state: { name: 'Vuex實(shí)例' } } })
組件中分別顯示用戶的token和應(yīng)用名稱name
<template> <div> <div>用戶token {{ $store.state.user.token }}</div> <div>網(wǎng)站名稱 {{ $store.state.setting.name }}</div> </div> </template>
請(qǐng)注意: 此時(shí)要獲取子模塊的狀態(tài) 需要通過 $store.state
.模塊名稱
.屬性名
來獲取
簡(jiǎn)化數(shù)據(jù)獲取
看著獲取有點(diǎn)麻煩,我們可以通過之前學(xué)過的getters來改變一下
getters: { token: state => state.user.token, name: state => state.setting.name }
請(qǐng)注意:這個(gè)getters是根級(jí)別的getters哦
通過mapGetters引用
computed: { ...mapGetters(['token', 'name']) }
模塊化中的命名空間
命名空間 namespaced
這里注意理解
為什么引入命名空間
默認(rèn)情況下,模塊內(nèi)部的 action、mutation 和 getter 是注冊(cè)在全局命名空間的——這樣使得多個(gè)模塊能夠?qū)ν?mutation 或 action 作出響應(yīng)。
這句話的意思是 剛才的user模塊還是setting模塊,它的 action、mutation 和 getter 其實(shí)并沒有區(qū)分,都可以直接通過全局的方式調(diào)用 如
user: { state: { token: '12345' }, mutations: { // 這里的state表示的是user的state updateToken (state) { state.token = 678910 } } },
通過mapMutations調(diào)用
methods: { ...mapMutations(['updateToken']) } <button @click="updateToken">修改token</button>
但是,如果我們想保證內(nèi)部模塊的高封閉性,我們可以采用namespaced來進(jìn)行設(shè)置
如何使用命名空間
高封閉性?可以理解成 一家人如果分家了,此時(shí),你的爸媽可以隨意的進(jìn)出分給你的小家,你覺得自己沒什么隱私了,我們可以給自己的房門加一道鎖(命名空間 namespaced),你的父母再也不能進(jìn)出你的小家了
如
user: { namespaced: true, state: { token: '12345' }, mutations: { // 這里的state表示的是user的state updateToken (state) { state.token = 678910 } } },
使用帶命名空間的模塊 action/mutations
方案1:直接調(diào)用-帶上模塊的屬性名路徑
test () { this.$store.commit('user/updateToken') // 直接調(diào)用方法 }
方案2:輔助函數(shù)-指定模塊名調(diào)用(推薦)
methods: { ...mapMutations('user', ['updateToken']), test () { this.updateToken() } } <button @click="test">修改token</button>
08-vuex案例-新聞(預(yù)習(xí))
1-搭建項(xiàng)目
使用cli創(chuàng)建項(xiàng)目,選擇自定義=》添加router和vuex插件
- 使用vue-router插件 router.js
- 使用vuex插件 store.js
main.js
import Vue from 'vue' import App from './App.vue' // vuex實(shí)例 import store from './store' // router路由實(shí)例 import router from './router' Vue.config.productionTip = false new Vue({ render: h => h(App), // 掛載vuex實(shí)例 store, // 項(xiàng)目中所有組件就可以通過this.$store // 掛載router實(shí)例 router // 項(xiàng)目中所有組件就可以通過this.$router(跳轉(zhuǎn)路由) / this.$route(獲取路由參數(shù)) }).$mount('#app')
store.js
// 管理數(shù)據(jù) import Vuex from 'vuex' import Vue from 'vue' Vue.use(Vuex) const store = new Vuex.Store({ }) export default store
router.js
// 路由相關(guān)功能 import Vue from 'vue' import VueRouter from 'vue-router' Vue.use(VueRouter) const router = new VueRouter({ // TODO 路由規(guī)則 routes: [] }) export default router
2-創(chuàng)建組件和配置路由
需求說明:
使用vuex開發(fā)新聞列表和詳情
功能說明:
1.新聞列表功能
2.新聞詳情功能
封裝組件
- 新聞列表組件
- 新聞詳情組件
路由規(guī)則
- / 重定向 /list
- /detail
// 路由規(guī)則 routes: [ { path: '/', redirect: '/list' }, { path: '/list', component: Hot }, // 新聞列表 { path: '/detail/:id', component: Detail } // 新聞詳情 ]
3-列表功能
定義vuex數(shù)據(jù)、修改數(shù)據(jù)方法、獲取后臺(tái)數(shù)據(jù)方法,組件中獲取數(shù)據(jù)渲染
準(zhǔn)備:
后臺(tái)請(qǐng)求基礎(chǔ)地址:http://xxx
1.安裝axios:npm i axios
說明:src/utils/request.js
import axios from 'axios' // 后臺(tái)接口基礎(chǔ)地址 const BASE_URL = 'http://xxx' // 創(chuàng)建axios實(shí)例 const request = axios.create({ baseURL: BASE_URL }) export default request
第一步:申明數(shù)據(jù),根據(jù)頁面需要的數(shù)據(jù)進(jìn)行申明。
state: { // 新聞列表 list: [] },
第二步:定義修改數(shù)據(jù)的方法
mutations: { // payload = {list} 約定數(shù)據(jù)格式 setListPageData (state, payload) { state.list = payload.list } },
第三步:獲取數(shù)據(jù)的方法
actions: { // 獲取數(shù)據(jù) async getNews ({ commit }) { const { data: { data: { results } } } = await request({ url: 'articles', params: { channel_id: 0, timestamp: +new Date() } }) // console.log(res) commit('setListPageData', { list: results }) } }
第四步:調(diào)用獲取數(shù)據(jù)的方法
methods: { ...mapActions(['getNews']) }
created () { this.getNews() // this.$store.dispatch('getNews') },
第五步:獲取vuex的數(shù)據(jù)
computed: { ...mapState(['list']) },
第六步:渲染頁面
<div> <ul> <li v-for="item in list" :key="item.art_id"> <router-link :to="`/detail/${item.art_id}`">{{ item.title }}</router-link> </li> </ul> </div>
4-詳情功能(作業(yè))
點(diǎn)擊新聞列表某項(xiàng),查看新聞詳情
- 使用動(dòng)態(tài)路由功能 /detail/:id
- 詳情組件獲取id獲取詳情數(shù)據(jù)
第一步:路由規(guī)則
{ path: '/detail/:id', component: Detail }
router-link :to="`/detail/${item.art_id}`"
第二步:準(zhǔn)備數(shù)據(jù)
state: { // 列表 list: [], // 詳情 + detail: {} },
第三步:修改數(shù)據(jù)函數(shù)
mutations: { // payload = {detail} 約定數(shù)據(jù)格式 setDetailPageData (state, payload) { state.detail = payload.detail } },
第四步:獲取數(shù)據(jù)去修改數(shù)據(jù)的函數(shù)
actions: { // 詳情 async getDetailById ({ commit }, articleId) { const { data: { data } } = await request({ url: `articles/${articleId}` }) // console.log(data) commit('setDetailPageData', { detail: data }) } }
第五步:在組件使用數(shù)據(jù)
computed: { ...mapState(['detail']) },
第六步:在組件初始化獲取數(shù)據(jù)
created () { this.getDetailById(this.$route.params.id) },
methods: { ...mapActions(['getDetailById']) }
第七步:渲染頁面
<template> <div> <h1>{{ detail.title }}</h1> <h2>{{detail.art_id}}</h2> <!-- <h2>{{detail.art_id}}</h2> --> <article v-html="detail.content"></article> </div> </template>
重點(diǎn)總結(jié)
vuex核心知識(shí)
state 聲明數(shù)據(jù)
- this.$store.state.數(shù)據(jù)屬性名
- mapState 生成計(jì)算屬性(獲取數(shù)據(jù))
mutations 修改數(shù)據(jù)(同步)
- this.$store.commit('函數(shù)名稱','傳參')
- mapMutations 生成methods函數(shù)
actions 獲取后臺(tái)數(shù)據(jù)(異步)
- this.$store.dispatch('函數(shù)名稱','傳參')
- mapActions 生成methods函數(shù)
getters 派生數(shù)據(jù)
- this.$store.getters.函數(shù)名
- mapGetters 生成計(jì)算屬性(獲取數(shù)據(jù))
modules 模塊化
- 獨(dú)立的文件(對(duì)象)中定義:state、mutations、actions、getters
- 更好的管理項(xiàng)目狀態(tài)數(shù)據(jù)
以上就是一文帶你搞懂Vue中Vuex的使用的詳細(xì)內(nèi)容,更多關(guān)于Vue Vuex的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Vue如何解決子組件data從props中無法動(dòng)態(tài)更新數(shù)據(jù)問題
這篇文章主要介紹了Vue如何解決子組件data從props中無法動(dòng)態(tài)更新數(shù)據(jù)問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-10-10Vue不同項(xiàng)目之間傳遞、接收參數(shù)問題
這篇文章主要介紹了Vue不同項(xiàng)目之間傳遞、接收參數(shù)問題,主要針對(duì)是登錄操作,我們?yōu)榱送瓿蒘SO(Single Sign On)的效果,認(rèn)證和授權(quán)在UC完成,用戶發(fā)起資源請(qǐng)求,服務(wù)網(wǎng)關(guān)會(huì)進(jìn)行過濾,本文給大家介紹的非常詳細(xì),需要的朋友可以參考下2023-04-04vue實(shí)現(xiàn)簡(jiǎn)易的雙向數(shù)據(jù)綁定
這篇文章主要介紹了vue如何實(shí)現(xiàn)簡(jiǎn)易的雙向數(shù)據(jù)綁定,幫助大家更好的理解和使用vue框架,感興趣的朋友可以了解下2020-12-12vue粘貼復(fù)制功能的實(shí)現(xiàn)過程記錄
最近在項(xiàng)目中遇到點(diǎn)擊按鈕復(fù)制鏈接功能,所以這篇文章主要給大家介紹了關(guān)于vue粘貼復(fù)制功能的實(shí)現(xiàn)過程,文中通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考下2022-03-03vue本地構(gòu)建熱更新卡頓的問題“75?advanced?module?optimization”完美解決方案
這篇文章主要介紹了vue本地構(gòu)建熱更新卡頓的問題“75?advanced?module?optimization”解決方案,每次熱更新都會(huì)卡在?"75?advanced?module?optimization"?的地方不動(dòng)了,如何解決這個(gè)問題呢,下面小編給大家?guī)砹私鉀Q方案,需要的朋友可以參考下2022-08-08vue指令?v-bind的使用和注意需要注意的點(diǎn)
這篇文章主要給大家分享了?v-bind的使用和注意需要注意的點(diǎn),下面文章圍繞?v-bind指令的相關(guān)資料展開內(nèi)容且附上詳細(xì)代碼?需要的小伙伴可以參考一下,希望對(duì)大家有所幫助2021-11-11