vuex最簡單佛玄、最直白硼一、最全的入門文檔

前言

我們經(jīng)常用element-ui做后臺管理系統(tǒng),經(jīng)常會遇到父組件給子組件傳遞數(shù)據(jù)般贼,下面一個簡單的例子,點擊按鈕,把彈框顯示變量數(shù)據(jù)通過子組件的props屬性傳遞腮介,子組件通過$emit事件監(jiān)聽把數(shù)據(jù)回傳給父組件。

父組件代碼:

<template>
  <div>
    <a href="javascript:;" @click="dialogshow = true">點擊</a>
    <common-dialog :show.sync="dialogshow"></common-dialog>
    彈框是否顯示:{{dialogshow}}
  </div>
</template>

<script>
import commondialog from '@/components/dialog'
export default {
    name: 'parent',
    components:{
        'common-dialog':commondialog
    },
    data () {
        return {
          dialogshow:false
        }
    },
    methods:{
        
    }
}
</script>

子組件代碼:

<template>
    <el-dialog :visible.sync="elDialogShow"  title="提示">
        <span>這是一段彈框信息</span>
        <span slot="footer" class="dialog-footer">
            <el-button @click="elDialogShow = false">取 消</el-button>
            <el-button type="primary" @click="elDialogShow = false">確 定</el-button>
        </span>
    </el-dialog>
</template>
<script>
    export default {
        name:'children',
        props:['show'],
        computed:{
            elDialogShow:{
                get(){
                    return this.show
                },
                set(value){
                    this.$emit('update:show',value)
                }
            }
        },
        data() {
            return {
                
            };
        }
    }
</script>

感覺這樣挺麻煩玉锌,父組件通過設(shè)置子組件的屬性(props)來向子組件傳遞數(shù)據(jù),而父組件想獲得子組件的數(shù)據(jù)疟羹,得向子組件注冊事件主守,在子組件觸發(fā)這個事件再把數(shù)據(jù)傳遞出來禀倔。一句話總結(jié)起來就是,props 向下傳遞數(shù)據(jù)参淫,事件向上傳遞數(shù)據(jù)救湖。

如果使用vuex,像下面這種方式就很簡單:

<!--父組件-->
<template>
  <div>
    <a href="javascript:;" @click="$store.state.show = true">點擊</a>
    <common-dialog></common-dialog>
    彈框是否顯示:{{$store.state.show}}
  </div>
</template>

<!--子組件-->
<el-dialog :visible.sync="$store.state.show"  title="提示">
    <!--其它代碼省略-->
</el-dialog>

安裝使用vuex

安裝:

npm install vuex --save

在main.js添加配置:

import vuex from 'vuex'
Vue.use(vuex)
var store = new vuex.Store({
    state:{
        show:false
    }
})
new Vue({
  el: '#app',
  router,
  store,
  components: { App },
  template: '<App/>'
})

然后子組件代碼就能有效運行了涎才。

<template>
    <el-dialog :visible.sync="$store.state.show"  title="提示">
        <span>這是一段彈框信息</span>
        <span slot="footer" class="dialog-footer">
            <el-button @click="$store.state.show = false">取 消</el-button>
            <el-button type="primary" @click="$store.state.show = false">確 定</el-button>
        </span>
    </el-dialog>
</template>
<script>
    export default {
        name:'children',
        data() {
            return {
                
            };
        }
    }
</script>

modules

前面我們把store對象寫到了main.js中鞋既,為了項目的好管理,我們可以新建一個store文件夾放于src文件夾下耍铜,在store文件夾下新建index.js,代碼如下:

import Vue from 'vue'
import vuex from 'vuex'
Vue.use(vuex);

export default new vuex.Store({
    state:{
        show:false
    }
})

那么對應(yīng)的main.js得改成如下:

//vuex
import store from './store'

new Vue({
  el: '#app',
  router,
  store,//使用store
  template: '<App/>',
  components: { App }
})

這樣雖然結(jié)構(gòu)看著清晰了邑闺,但是如果多個模塊,不同類型(比如用戶基本信息棕兼,用戶購物車等)放到同一個state下面不好管理陡舅,這就用modules

那么store文件夾下的index.js就變成了這樣伴挚,假如我們有app與user模塊:

import Vue from 'vue'
import Vuex from 'vuex'
import app from './modules/app'   //app模塊數(shù)據(jù)
import user from './modules/user'  //用戶模塊數(shù)據(jù)
import getters from './getters'  

Vue.use(Vuex)

const store = new Vuex.Store({
  modules: {
    app,
    user
  },
  getters
})

export default store

getters

這兒說明下靶衍,上面我在Store實例對象中引入了getters,是為了后面頁面可以直接調(diào)用經(jīng)常用到的狀態(tài)信息茎芋,也就相當(dāng)于vue實例里面的computed計算屬性颅眶,通過$store.getters.show方式得到相關(guān)數(shù)據(jù),即通過上面的getters引入知道田弥,是直接在store文件夾下創(chuàng)建了一個getters.js,代碼如下:

const getters = {
  show: state => state.app.show
}
export default getters

當(dāng)然這個getters也可以放到具體的模塊中涛酗,比如放到app模塊中,官網(wǎng)的這塊代碼結(jié)構(gòu)如下:

const moduleA = {
  state: { ... },
  mutations: { ... },
  actions: { ... },
  getters: { ... }
}

const moduleB = {
  state: { ... },
  mutations: { ... },
  actions: { ... }
}

const store = new Vuex.Store({
  modules: {
    a: moduleA,
    b: moduleB
  }
})

store.state.a // -> moduleA 的狀態(tài)
store.state.b // -> moduleB 的狀態(tài)

我們從index.js中看到皱蹦,我們在store文件夾下創(chuàng)建了一個modules文件夾煤杀,也就是在該文件夾下放各個需要區(qū)分的狀態(tài)模塊,比如user.js沪哺,app.js等沈自。

結(jié)構(gòu)如下圖:


上面我們通過$store.getters.show方式(即相當(dāng)于通過計算屬性)獲得show的值,當(dāng)然也可以通過$store.state.app.show獲得辜妓。

app.js代碼:

export default {
    state:{
        show:false
    }
}

mutations

在我們點擊按鈕出現(xiàn)彈框或者點擊彈框中的關(guān)閉按鈕枯途,需要修改app模塊中的show的狀態(tài),這時候就需要通過mutations進(jìn)行修改數(shù)據(jù)(同步操作)籍滴。

我們需要在app.js模塊代碼

export default {
    state:{
        show:false
    },
 
    mutations:{
        SET_DIALOG_STATE:(state,val) => { //改變彈框是否顯示的狀態(tài)
            state.show = val
        }
    }
}

父組件:

<template>
  <div>
    <a href="javascript:;" @click="$store.commit('SET_DIALOG_STATE',true)">點擊</a>
    <common-dialog></common-dialog>
    彈框是否顯示:{{$store.state.app.show}}
  </div>
</template>

<script>
import commondialog from '@/components/dialog'
export default {
    name: 'parent',
    components:{
        'common-dialog':commondialog
    },
    data () {
        return {
         
        }
    },
    
    methods:{
        
    }
}
</script>

子組件:

<template>
    <el-dialog :visible.sync="$store.getters.show"  title="提示">
        <span>這是一段彈框信息</span>
        <span slot="footer" class="dialog-footer">
            <el-button @click="$store.commit('SET_DIALOG_STATE',false)">取 消</el-button>
            <el-button type="primary" @click="$store.commit('SET_DIALOG_STATE',false)">確 定</el-button>
        </span>
    </el-dialog>
</template>

這兒就是用到了$store.commit('SET_DIALOG_STATE',false)來觸發(fā)mutations中的SET_DIALOG_STATE方法來改變狀態(tài)值
需要注意的是:

mutations中的方法是不分模塊的酪夷,比如你在app.js中定義了SET_DIALOG_STATE這個方法,也在user.js中定義了SET_DIALOG_STATE這個方法孽惰,那么在任一組件中調(diào)用$store.commit('SET_DIALOG_STATE',false)晚岭,會執(zhí)行所有的SET_DIALOG_STATE方法。
mutations里的操作必須是同步的勋功。
如果在mutations里執(zhí)行異步操作會發(fā)生什么事情 , 實際上并不會發(fā)生什么奇怪的事情 , 只是官方推薦 , 不要在 mutations里執(zhí)行異步操作而已坦报。

actions

我們在上面的app.js中通過mutations改變了一個狀態(tài)库说,那么如果需要改變多個狀態(tài)的值呢,需要執(zhí)行mutations中定義的多個方法(也就是說需要調(diào)用多次$store.commit()方法)片择,那么就需要actions

那么app.js代碼如需要改成如下:

export default {
    state:{
        show:false
    },
    getters:{
        showState(state){
            return state.show
        }
    },
    mutations:{
        SET_DIALOG_STATE:(state,val) => { //改變彈框是否顯示的狀態(tài)
            state.show = val
        }
    },
    actions:{
        set_dialog_state({commit,state},dialogVal){ //對象解構(gòu)
            commit('SET_DIALOG_STATE',dialogVal)
            //commit('mutations其它方法','其它方法需要改變的值') 
        }
        
        //等價于下面的:
        /*
        set_dialog_state(context,dialogVal){
            context.commit('SET_DIALOG_STATE',dialogVal)
            context.commit('mutations其它方法','其它方法需要改變的值') 
        }
        */
    }
}

那么父組件的調(diào)用方式就需要用$store.dispatch()方法潜的,父組件代碼如下:

  <div>
    <a href="javascript:;" @click="$store.dispatch('set_dialog_state',true)">點擊</a>
    <common-dialog></common-dialog>
    彈框是否顯示:{{$store.state.app.show}}
  </div>
</template>

<script>
import commondialog from '@/components/dialog'
export default {
    name: 'parent',
    components:{
        'common-dialog':commondialog
    },
    data () {
        return {
         
        }
    },
    
    methods:{
        
    }
}
</script>

子組件的代碼:

<template>
    <el-dialog :visible.sync="$store.getters.show"  title="提示">
        <span>這是一段彈框信息</span>
        <span slot="footer" class="dialog-footer">
            <el-button @click="$store.dispatch('set_dialog_state',false)">取 消</el-button>
            <el-button type="primary" @click="$store.dispatch('set_dialog_state',false)">確 定</el-button>
        </span>
    </el-dialog>
</template>

這兒就使用$store.dispatch('set_dialog_state',true)來觸發(fā)actions中的set_dialog_state方法。官方推薦 , 將異步操作放在 action 中字管。

mapGetters啰挪、mapState、mapMutations嘲叔、mapActions

很多時候 , $store.state.app.show 亡呵、$store.dispatch('set_dialog_state',true) 這種寫法又長又臭 , 很不方便 , 我們沒使用 vuex 的時候 , 獲取一個狀態(tài)只需要this.show , 執(zhí)行一個方法只需要this.set_dialog_state就行了 , 使用 vuex 使寫法變復(fù)雜了 ?

使用 mapState、mapGetters借跪、mapActions就變得簡單了政己。

mapGetters

比如子組件原來是這樣:

    <el-dialog :visible.sync="$store.getters.show"  title="提示">
        <span>這是一段彈框信息</span>
        <span slot="footer" class="dialog-footer">
            <el-button @click="$store.dispatch('set_dialog_state',false)">取 消</el-button>
            <el-button type="primary" @click="$store.dispatch('set_dialog_state',false)">確 定</el-button>
        </span>
    </el-dialog>
</template>

通過$store.getter.show得到狀態(tài)值,我們也可以這樣:

<template>
    <el-dialog :visible.sync="show"  title="提示">
        <span>這是一段彈框信息</span>
        <span slot="footer" class="dialog-footer">
            <el-button @click="$store.dispatch('set_dialog_state',false)">取 消</el-button>
            <el-button type="primary" @click="$store.dispatch('set_dialog_state',false)">確 定</el-button>
        </span>
    </el-dialog>
</template>
<script>
    import { mapGetters } from 'vuex'
    export default {
        name:'children',
        data() {
            return {
                
            };
        },
        computed:{
            ...mapGetters([
                'show'
            ])
        }
        
    }
</script>

mapGetters輔助函數(shù)僅僅是將 store 中的 getter 映射到局部計算屬性掏愁。

當(dāng)然我們也可以給getters里面的狀態(tài)show換一個名字歇由,比如叫dialogShow,那么子組件就需要改成如下:

<template>
    <el-dialog :visible.sync="dialogShow"  title="提示">
        <span>這是一段彈框信息</span>
        <span slot="footer" class="dialog-footer">
            <el-button @click="$store.dispatch('set_dialog_state',false)">取 消</el-button>
            <el-button type="primary" @click="$store.dispatch('set_dialog_state',false)">確 定</el-button>
        </span>
    </el-dialog>
</template>
<script>
    import { mapGetters } from 'vuex'
    export default {
        name:'children',
        data() {
            return {
                
            };
        },
        computed:{
            ...mapGetters({
                dialogShow:'show'
            })
        }
        
    }
</script>

mapState

上面我們通過$store.getters.show拿到狀態(tài)值,我們也可以通過$store.state.app.show拿到值果港,那么怎樣使用mapState呢沦泌?

子組件寫法:

<template>
    <el-dialog :visible.sync="show"  title="提示">
        <span>這是一段彈框信息</span>
        <span slot="footer" class="dialog-footer">
            <el-button @click="$store.dispatch('set_dialog_state',false)">取 消</el-button>
            <el-button type="primary" @click="$store.dispatch('set_dialog_state',false)">確 定</el-button>
        </span>
    </el-dialog>
</template>
<script>
    import { mapState } from 'vuex'
    export default {
        name:'children',
        data() {
            return {
                
            };
        },
        computed:{
            ...mapState({
                show:state => state.app.show
            })
        }
        
    }
</script>

上面使用的是箭頭函數(shù),也可以使用常規(guī)函數(shù)辛掠,如下:

<template>
    <el-dialog :visible.sync="showState"  title="提示">
        <span>這是一段彈框信息</span>
        <span slot="footer" class="dialog-footer">
            <el-button @click="$store.dispatch('set_dialog_state',false)">取 消</el-button>
            <el-button type="primary" @click="$store.dispatch('set_dialog_state',false)">確 定</el-button>
        </span>
    </el-dialog>
</template>
<script>
    import { mapState } from 'vuex'
    export default {
        name:'children',
        data() {
            return {
                
            };
        },
        computed:{
            ...mapState({
                show:state => state.app.show, //方式一 箭頭函數(shù)
                showState(state){  //方式二 常規(guī)函數(shù)
                    return state.app.show
                }
            })
        }
        
    }
</script>

mapMutations

你可以在組件中使用 $store.commit('xxx')提交 mutation谢谦,或者使用 mapMutations 輔助函數(shù)將組件中的 methods 映射為 store.commit 調(diào)用

父組件代碼如下:

<template>
  <div>
    <a href="javascript:;" @click="SET_DIALOG_STATE(true)">點擊</a>
    <common-dialog></common-dialog>
    彈框是否顯示:{{$store.state.app.show}}
  </div>
</template>

<script>
import { mapMutations } from 'vuex'
import commondialog from '@/components/dialog'
export default {
    name: 'parent',
    components:{
        'common-dialog':commondialog
    },
    data () {
        return {
         
        }
    },
    
    methods:{
        ...mapMutations(['SET_DIALOG_STATE'])
    }
}
</script>

給方法名換個名字:

<template>
  <div>
    <a href="javascript:;" @click="changeState(true)">點擊</a>
    <common-dialog></common-dialog>
    彈框是否顯示:{{$store.state.app.show}}
  </div>
</template>

<script>
import { mapMutations } from 'vuex'
import commondialog from '@/components/dialog'
export default {
    name: 'parent',
    components:{
        'common-dialog':commondialog
    },
    data () {
        return {
         
        }
    },
    
    methods:{
        ...mapMutations({
            changeState:'SET_DIALOG_STATE' //改變名字
        })
    }
}
</script>

mapActions

你在組件中使用$store.dispatch('xxx')分發(fā) action,或者使用 mapActions 輔助函數(shù)將組件的 methods 映射為 store.dispatch 調(diào)用

父組件代碼:

<template>
  <div>
    <a href="javascript:;" @click="set_dialog_state(true)">點擊</a>
    <common-dialog></common-dialog>
    彈框是否顯示:{{$store.state.app.show}}
  </div>
</template>

<script>
import { mapActions  } from 'vuex'
import commondialog from '@/components/dialog'
export default {
    name: 'parent',
    components:{
        'common-dialog':commondialog
    },
    data () {
        return {
         
        }
    },
    
    methods:{
        ...mapActions (['set_dialog_state'])
    }
}
</script>
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末萝衩,一起剝皮案震驚了整個濱河市回挽,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌猩谊,老刑警劉巖千劈,帶你破解...
    沈念sama閱讀 218,284評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異牌捷,居然都是意外死亡墙牌,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,115評論 3 395
  • 文/潘曉璐 我一進(jìn)店門暗甥,熙熙樓的掌柜王于貴愁眉苦臉地迎上來喜滨,“玉大人,你說我怎么就攤上這事撤防∷浞纾” “怎么了?”我有些...
    開封第一講書人閱讀 164,614評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長焰情。 經(jīng)常有香客問我陌凳,道長,這世上最難降的妖魔是什么内舟? 我笑而不...
    開封第一講書人閱讀 58,671評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮初橘,結(jié)果婚禮上验游,老公的妹妹穿的比我還像新娘。我一直安慰自己保檐,他們只是感情好耕蝉,可當(dāng)我...
    茶點故事閱讀 67,699評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著夜只,像睡著了一般垒在。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上扔亥,一...
    開封第一講書人閱讀 51,562評論 1 305
  • 那天场躯,我揣著相機(jī)與錄音,去河邊找鬼旅挤。 笑死踢关,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的粘茄。 我是一名探鬼主播签舞,決...
    沈念sama閱讀 40,309評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼柒瓣!你這毒婦竟也來了儒搭?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,223評論 0 276
  • 序言:老撾萬榮一對情侶失蹤芙贫,失蹤者是張志新(化名)和其女友劉穎搂鲫,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體屹培,經(jīng)...
    沈念sama閱讀 45,668評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡默穴,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,859評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了褪秀。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片蓄诽。...
    茶點故事閱讀 39,981評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖媒吗,靈堂內(nèi)的尸體忽然破棺而出仑氛,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 35,705評論 5 347
  • 正文 年R本政府宣布锯岖,位于F島的核電站介袜,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏出吹。R本人自食惡果不足惜遇伞,卻給世界環(huán)境...
    茶點故事閱讀 41,310評論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望捶牢。 院中可真熱鬧鸠珠,春花似錦、人聲如沸秋麸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,904評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽灸蟆。三九已至驯耻,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間炒考,已是汗流浹背可缚。 一陣腳步聲響...
    開封第一講書人閱讀 33,023評論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留票腰,地道東北人城看。 一個月前我還...
    沈念sama閱讀 48,146評論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像杏慰,于是被迫代替她去往敵國和親测柠。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,933評論 2 355

推薦閱讀更多精彩內(nèi)容