亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

如何使用 Vuex的入門教程

 更新時(shí)間:2022年02月28日 09:46:28   作者:前端不釋卷leo  
在vue中當(dāng)我們管理數(shù)據(jù)的時(shí)候比較亂,我們要用到下面的這個(gè)庫(kù),本文主要介紹了如何使用 Vuex的入門教程,具有一定的參考價(jià)值,感興趣的可以了解一下

前言

本人曾對(duì) Vuex 作過詳細(xì)介紹,但是今天去回顧的時(shí)候發(fā)現(xiàn)文章思路有些繁瑣,不容易找到重點(diǎn)。于是,在下班前幾分鐘,我對(duì)其重新梳理了一遍。

tips:本文的案例均為Vue2版本。

一、基本概念

Vuex 是一個(gè)專為 Vue.js 應(yīng)用程序開發(fā)的狀態(tài)管理模式。它采用集中式存儲(chǔ)管理應(yīng)用的所有組件的狀態(tài),并以相應(yīng)的規(guī)則保證狀態(tài)以一種可預(yù)測(cè)的方式發(fā)生變化。

初識(shí)vuex

    vuex有什么用?

    比如, vue做了一個(gè)音樂app, 里面的播放組件, 這組件應(yīng)該是在所有的頁(yè)面都有用到的.

    希望在所有的頁(yè)面都能控制播放器的 暫停/播放, 或者說都可以選擇是否 隨便播放/單曲循環(huán).

    這就涉及到了多組件之間的傳參,而且是非常復(fù)雜的傳參.這時(shí)候使用vuex是合適的.

二、項(xiàng)目場(chǎng)景

如果你的項(xiàng)目里有很多頁(yè)面(組件/視圖),頁(yè)面之間存在多級(jí)的嵌套關(guān)系,此時(shí),如果這些頁(yè)面都需要共享一個(gè)狀態(tài)的時(shí)候,此時(shí)就會(huì)產(chǎn)生以下兩個(gè)問題:

  • 多個(gè)視圖依賴同一個(gè)狀態(tài)
  • 來自不同視圖的行為需要變更同一個(gè)狀態(tài)

解決方案(初版):

  • 對(duì)于第一個(gè)問題,假如是多級(jí)嵌套關(guān)系,你可以使用父子組件傳參進(jìn)行解決,雖有些麻煩,但好在可以解決;對(duì)于兄弟組件或者關(guān)系更復(fù)雜組件之間,雖然可以通過各種各樣的辦法解決,可實(shí)在很不優(yōu)雅,而且等項(xiàng)目做大了,代碼量愈發(fā)巨大,實(shí)在令人心煩。
  • 對(duì)于第二個(gè)問題,你可以通過父子組件直接引用,或者通過事件來變更或者同步狀態(tài)的多份拷貝,但是這種模式很脆弱,使得代碼難以維護(hù),而且同樣會(huì)讓代碼量劇增。

思路:

  • 把各個(gè)組件都需要依賴的同一個(gè)狀態(tài)抽取出來,全局統(tǒng)一管理。
  • 在這種模式下,任何組件都可以直接訪問到這個(gè)狀態(tài),或者當(dāng)狀態(tài)發(fā)生改變時(shí),所有的組件都相應(yīng)更新。

此時(shí),Vuex 就誕生了。 這就是它背后的基本思想,借鑒了 Flux、Redux。與其他模式不同的是,Vuex 是專門為 Vue 設(shè)計(jì)的狀態(tài)管理庫(kù),以利用 Vue.js 的細(xì)粒度數(shù)據(jù)響應(yīng)機(jī)制來進(jìn)行高效的狀態(tài)更新。

三、如何使用

1、安裝

進(jìn)入項(xiàng)目,鍵入以下命令:

npm install vuex --save

2、State 初始值

在 src 路徑下創(chuàng)建 store 文件夾,并在該文件夾下新增 index.js 文件:

import Vue from 'vue';
import Vuex from 'vuex';
?
Vue.use(Vuex);
?
const store = new Vuex.Store({
? ? state: {
? ? ? ? // 定義一個(gè)name,以供全局使用
? ? ? ? name: 'leo'
? ? }
});
?
export default store;

修改 main.js: 

import Vue from 'vue';
import App from './App';
import store from './store'; ? // 引入我們前面導(dǎo)出的store對(duì)象
?
Vue.config.productionTip = false;
?
new Vue({
? ? el: '#app',
? ? store, ? // 把store對(duì)象添加到vue實(shí)例上
? ? components: { App },
? ? template: '<App/>'
});

最后修改 App.vue:

<template>
? ? <div></div>
</template>
?
<script>
? ? export default {
? ? ? ? mounted() {
? ? ? ? ? ? // 使用this.$store.state.xxx可以直接訪問到倉(cāng)庫(kù)中的狀態(tài)
? ? ? ? ? ? console.log(this.$store.state.name); ? // 'leo'
? ? ? ? }
? ? }
</script>

建議一:this.$store.state.xxx 放在計(jì)算屬性中,這樣可以讓你的代碼看起來更優(yōu)雅一些。 

export default {
? ? mounted() {
? ? ? ? console.log(this.getName); ? // 'leo'
? ? },
? ? computed:{
? ? ? ? getName() {
? ? ? ? ? ? return this.$store.state.name;
? ? ? ? }
? ? }
}

建議二:每次都寫 this.$store.state.xxx 讓你感到厭煩,造成代碼冗余,可以使用 mapState。

<script>
import { mapState } from 'vuex'; ? // 從vuex中導(dǎo)入mapState
export default {
? ? mounted() {
? ? ? ? console.log(this.name); ? // 'leo'
? ? },
? ? computed: {
? ? ? ? ...mapState(['name']) ? // 經(jīng)過解構(gòu)后,自動(dòng)就添加到了計(jì)算屬性中,此時(shí)就可以直接像訪問計(jì)算屬性一樣訪問它
? ? }
}
</script>

你甚至可以給它取別名:

...mapState({ userName: 'name' }) ? // 賦別名的話,這里接收對(duì)象,而不是數(shù)組

3、Getters 修飾值

設(shè)想一個(gè)場(chǎng)景,你已經(jīng)將 store 中的 name 展示到頁(yè)面上了,而且是很多頁(yè)面都展示了,此時(shí)客戶要求在每個(gè) name 前都加上“hello”。

最容易想到的辦法就是去每個(gè)用到 name 的頁(yè)面一個(gè)一個(gè)加上“hello”,顯然這種方式并不友好,原因如下:

第一,假如你在A、B、C三個(gè)頁(yè)面都用到了 name,那么你要在這A、B、C三個(gè)頁(yè)面都修改一遍,多個(gè)頁(yè)面你就要加很多遍這個(gè)方法,造成代碼冗余,很不好。

第二,假如下次客戶讓你把“hello”改成“greet”的時(shí)候,你又得把三個(gè)頁(yè)面(甚至更多)都改一遍,這時(shí)候你是拿石頭砸自己的腳。

吸取上面的教訓(xùn),我們有一個(gè)新的思路:直接在 store 中對(duì) name 進(jìn)行一些操作或者加工,從源頭解決問題!這時(shí)候,Getter 閃亮登場(chǎng)! 

首先,在 store 對(duì)象中增加 getters 屬性:

const store = new Vuex.Store({
? ? state: {
? ? ? ? name: 'leo'
? ? },
? ? // 在store對(duì)象中增加getters屬性
? ? getters: {
? ? ? ? getMessage(state) { ? // 獲取修飾后的name,第一個(gè)參數(shù)state為必要參數(shù),必須寫在形參上
? ? ? ? ? ? return `hello ${state.name}`;
? ? ? ? }
? ? }
});

在組件中使用:

export default {
? ? mounted() {
? ? ? ? console.log(this.$store.state.name);
? ? ? ? console.log(this.$store.getters.getMessage); ? // 注意不是$store.state了,而是$store.getters
? ? }
}

建議使用 mapGetters:

<script>
import { mapState, mapGetters } from 'vuex';
export default {
? ? mounted() {
? ? ? ? console.log(this.name); ? // 'leo'
? ? ? ? console.log(this.getMessage); ? // 'hello leo'?
? ? },
? ? computed: {
? ? ? ? ...mapState(['name']),
? ? ? ? ...mapGetters(['getMessage'])
? ? },
}
</script>

你也可以給它取別名: 

...mapGetters({ greetMsg: 'getMessage' }) ? // 賦別名的話,這里接收對(duì)象,而不是數(shù)組

4、Mutations 修改值

說到修改值,有的人可能會(huì)想到這樣寫:

this.$store.state.xxx = XXX;

首先,這是一種錯(cuò)誤的寫法。為什么說是錯(cuò)誤的寫法?因?yàn)檫@個(gè) store 倉(cāng)庫(kù)比較奇怪,你可以隨便拿,但是你不能隨便改,舉個(gè)例子:

假如你打開朋友圈,看到你的好友發(fā)了條動(dòng)態(tài),但是動(dòng)態(tài)里有個(gè)錯(cuò)別字,你要怎么辦呢?你可以幫他改掉嗎?當(dāng)然不可以!我們只能通知他本人去修改,因?yàn)槭莿e人的朋友圈,你是無權(quán)操作的,只有他自己才能操作。同理,在 Vuex 中,我們不能直接修改倉(cāng)庫(kù)里的值,必須用 Vuex 自帶的方法去修改。這個(gè)時(shí)候,Mutation 閃亮登場(chǎng)!

首先,修改 store/index.js:

const store = new Vuex.Store({
? ? state: {
? ? ? ? name: 'leo',
? ? ? ? number: 0,
? ? },
? ? mutations: { ? // 增加nutations屬性
? ? ? ? setNumber(state) { ? // 增加一個(gè)mutations的方法,方法的作用是讓number從0變成5,state是必須默認(rèn)參數(shù)
? ? ? ? ? ? state.number = 5;
? ? ? ? }
? ? }
});

然后,修改 App.vue:

<script>
export default {
? ? mounted() {
? ? ? ? console.log(this.$store.state.number); ? // 舊值,0
? ? ? ? this.$store.commit('setNumber');
? ? ? ? console.log(this.$store.state.number); ? // 新值,5
? ? },
}
</script>

如果我們想傳動(dòng)態(tài)參數(shù)怎么辦?

首先,修改 store/index.js:

const store = new Vuex.Store({
? ? state: {
? ? ? ? name: 'leo',
? ? ? ? number: 0,
? ? },
? ? mutations: {
? ? ? ? setNumber(state, num) { ? // 增加一個(gè)帶參數(shù)的mutations方法
? ? ? ? ? ? state.number = num;
? ? ? ? },
? ? },
});

相應(yīng)地,修改 App.vue:

<script>
export default {
? ? mounted() {
? ? ? ? console.log(this.$store.state.number); ? // 舊值,0
? ? ? ? this.$store.commit('setNumber', 666);
? ? ? ? console.log(this.$store.state.number); ? // 新值,666
? ? },
}
</script>

上面的這種傳參的方式雖然可以達(dá)到目的,但是并不推薦。建議傳遞一個(gè)對(duì)象,看起來更美觀,對(duì)象的名字你可以隨意命名,一般命名為 payload:

mutations: {
? ? setNumber(state, payload) { ? // 增加一個(gè)帶參數(shù)的mutations方法,并且官方建議payload為一個(gè)對(duì)象
? ? ? ? state.number = payload.number;
? ? },
},

相應(yīng)地,修改 App.vue:

<script>
export default {
? ? mounted() {
? ? ? ? console.log(this.$store.state.number); ? // 舊值,0
? ? ? ? this.$store.commit('setNumber', { number: 666 }); ?// 調(diào)用的時(shí)候需要傳遞一個(gè)對(duì)象
? ? ? ? console.log(this.$store.state.number); ? // 新值,666
? ? },
}
</script>

建議使用 mapMutations:

<script>
import { mapMutations } from 'vuex';
export default {
? ? mounted() {
? ? ? ? this.setNumber({ number: 666 });
? ? },
? ? methods: { ? // 注意,mapMutations是解構(gòu)到methods里面的,而不是計(jì)算屬性了
? ? ? ? ...mapMutations(['setNumber'])
? ? }
}
</script>

你也可以給它取別名: 

methods:{
? ? ...mapMutations({ changeNumber: 'setNumber' }) ? // 賦別名的話,這里接收對(duì)象,而不是數(shù)組
}

注意:Mutations 里面的函數(shù)必須是同步操作,不能包含異步操作。

Mutations 只能進(jìn)行同步操作,所以,我們馬上開始下一節(jié),看看使用 Actions 進(jìn)行異步操作的時(shí)候應(yīng)該注意什么!

5、Actions 異步修改值

Vuex 不希望你將異步操作放在 Mutations 中,所以就給你設(shè)置了一個(gè)區(qū)域,讓你進(jìn)行異步操作,這就是 Actions。

首先,修改 store/index.js:

const store = new Vuex.Store({
? ? state: {
? ? ? ? name: 'leo',
? ? ? ? number: 0,
? ? },
? ? mutations: {
? ? ? ? setNumber(state, payload) {
? ? ? ? ? ? state.number = payload.number;
? ? ? ? },
? ? },
? ? actions: { ? // 增加actions屬性
? ? ? ? setNum(content) { ? // 增加setNum方法,默認(rèn)第一個(gè)參數(shù)是content,其值是復(fù)制的一份store
? ? ? ? ? ? return new Promise(resolve => { ?// 模擬異步操作,1秒后修改number為666
? ? ? ? ? ? ? ? setTimeout(() => {
? ? ? ? ? ? ? ? ? ? content.commit('setNumber', { number: 666 });
? ? ? ? ? ? ? ? ? ? resolve();
? ? ? ? ? ? ? ? }, 1000);
? ? ? ? ? ? });
? ? ? ? }
? ? }
});

然后,修改 App.vue:

async mounted() {
? ? console.log(this.$store.state.number); ? // 舊值,0
? ? await this.$store.dispatch('setNum'); ? // 等待異步操作完成
? ? console.log(this.$store.state.number); ? // 新值,666
}

其實(shí) action 就是去提交 mutation 的。異步操作都在 action 中消化了,最后再去提交 mutation。 

當(dāng)然,你也可以進(jìn)行動(dòng)態(tài)傳參。

首先,修改 store/index.js:

actions: {
? ? setNum(content, payload) { ? // 增加payload參數(shù)
? ? ? ? return new Promise(resolve => {
? ? ? ? ? ? setTimeout(() => {
? ? ? ? ? ? ? ? content.commit('setNumber', { number: payload.number });
? ? ? ? ? ? ? ? resolve();
? ? ? ? ? ? }, 1000);
? ? ? ? });
? ? },
}

相應(yīng)地,修改 App.vue:

async mounted() {
? ? console.log(this.$store.state.number); ? // 舊值,0
? ? await this.$store.dispatch('setNum', { number: 888 });
? ? console.log(this.$store.state.number); ? // 新值,888
}

建議使用 mapActions:

<script>
import { mapActions } from 'vuex';
export default {
? ? methods: {
? ? ? ? ...mapActions(['setNum']), ? // 解構(gòu)到methods中
? ? },
? ? async mounted() {
? ? ? ? await this.setNum({ number: 888 }); ?// 直接調(diào)用即可
? ? }
}
</script>

你也可以給它取別名:

...mapActions({ changeNumber: 'setNum' }) ? // 賦別名的話,這里接收對(duì)象,而不是數(shù)組

tips:在 actions 里面,方法的形參可以直接將 commit 解構(gòu)出來,方便后續(xù)操作。 

actions: {
? ? setNum({ commit }) { ? // 直接將content結(jié)構(gòu)掉,解構(gòu)出commit,下面就可以直接調(diào)用了
? ? ? ? return new Promise(resolve => {
? ? ? ? ? ? setTimeout(() => {
? ? ? ? ? ? ? ? commit('xxx'); ?// 直接調(diào)用
? ? ? ? ? ? ? ? resolve();
? ? ? ? ? ? }, 1000);
? ? ? ? });
? ? },
},

四、總結(jié)

下班前這幾分鐘,你知道了如何使用 Vuex。你會(huì)安裝它,配置它,讀取 state 的值,甚至修飾讀(Getters),然后你會(huì)修改里面的值(Mutations),如果有異步操作并且需要修改 state,那你就要使用 Actions。

一張神奇的圖。

五、建議

何時(shí)使用 Vuex ?

這個(gè)問題因人而異,如果你不需要開發(fā)大型的單頁(yè)應(yīng)用,此時(shí)你完全沒有必要使用 Vuex,比如你的頁(yè)面就兩三個(gè),使用 Vuex 后增加的文件比你現(xiàn)在的頁(yè)面還要多,完全沒這個(gè)必要。

假如你的項(xiàng)目達(dá)到了中大型應(yīng)用的規(guī)模,此時(shí)你很可能會(huì)考慮如何更好地在組件外部對(duì)狀態(tài)進(jìn)行統(tǒng)一管理,甚至?xí)帜K(Vuex 中的 module,不展開),它將會(huì)是一個(gè)不錯(cuò)的選擇。

到此這篇關(guān)于如何使用 Vuex的入門教程的文章就介紹到這了,更多相關(guān)Vuex 入門教程內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論