第5讲 vuex看完这篇你就会了(1)

vuex和vue-router一样都是vue的核心插件,它是vue的状态管理,对于跨组件之间的传值,可以将这些值放到状态state里进行管理

1. state用法

在第2讲里,我已经对src/store这个文件夹进行了改造,这里先在src/store/state.js里新增一个值,然后来讲解vuex的用法

const state = {
    menuType: 1
}

export default state

这样就将menuType放入到了vuex里,让vuex来管理这个值,接下来示范一下在组件中调用这个值:

<template>
    <section>
        {{menuType}}
    </section>
</template>
<script>
export default {
    computed: {
        menuType () {
            return this.$store.state.menuType
        }
    },
    data () {
        return {
            
        }
    },
    methods: {
        
    },
}
</script>

那要是放在模块里的值,应该怎样去获取呢?

再来看一下,我在第2讲中新建的src/store/module/user.js文件,这是一个模块,如果在user.js里新增一个值,在组件里应该怎么获取呢?

const state = {
    userName: '张三'
}
const getters = {}
const mutations = {}
const actions = {}

export default {
    state,
    getters,
    mutations,
    actions
}

在组件里调用这个值

<template>
    <section>
        {{menuType}}
        {{userName}}
    </section>
</template>
<script>
export default {
    computed: {
        menuType () {
            return this.$store.state.menuType
        },
        userName () {
            return this.$store.state.user.userName // 调用模块里的值
        }
    },
    data () {
        return {
            
        }
    },
    methods: {
        
    },
}
</script>

除了上面提到的组件里获取值的方式,还可以利用vuex提供的辅助函数mapSate来获取值:

<template>
    <section>
        {{menuType}}
        {{userName}}
    </section>
</template>
<script>
import {mapState} from 'vuex'
export default {
    computed: {
        ...mapState({
            menuType: state => state.menuType,
            userName: state => state.user.userName
        })
    },
    data () {
        return {
            
        }
    },
    methods: {
        
    },
}
</script>

也可以采用简写的方式:

    computed: {
        ...mapState({
            menuType: state => state.menuType,
            userName: state => state.user.userName
        })
    },
    // 简写成
    computed: {
        ...mapState({
            userName: state => state.user.userName
        }),
        ...mapState([
            'menuType',
        ]),
    },

2. getter用法

相当于vue里的computed属性,比如menuType = 1,在我自己的项目里,它代表着菜单类型,1代表ping拨测菜单,2代表网页拨测菜单,在组件里获取这个值的时候,多次重复判断没有意义,咱们就可以放到getter里面进行判断

找到src/store/getter.js:

const getters = {
    menuType: state => {
        if (state.menuType == 1) {
            return 'ping拨测'
        } else {
            return '网页拨测'
        }
    }
}

export default getters

然后在组件里去获取这个值:

<template>
    <section>
        {{menuTypeName}}
    </section>
</template>
<script>
export default {
    computed: {
        menuTypeName () {
            return this.$store.getters.menuType
        }
    },
    data () {
        return {
            
        }
    },
    methods: {
        
    },
}
</script>

同样也可以利用vuex提供的辅助函数mapGetters来获取值:

computed: {
        ...mapGetters([
            'menuType'
        ])
    },

写在模块里的getters如何获取呢?

咱们在src/store/module/user.js新增如下代码:

const state = {
    userName: '张三'
}
const getters = {
    userName: state => {
        return state.userName + '是管理员'
    }
}
const mutations = {}
const actions = {}

export default {
    state,
    getters,
    mutations,
    actions
}

利用vuex辅助函数mapGetters来获取写在模块里的getters:

<template>
    <section>
        {{userName}}
    </section>
</template>
<script>
import {mapState, mapGetters} from 'vuex'
export default {
    computed: {
        // menuTypeName () {
        //     return this.$store.getters.menuType
        // },
        ...mapGetters([
            'userName'
        ])
    },
    data () {
        return {
            
        }
    },
    methods: {
        
    },
}
</script>

3. mutation用法

前面两小节主要讲的是如何获取vuex里的值,如果想修改vuex里的值,就需要通过commit提交一个mutation来修改

找到src/store/mutations.js文件,新增如下代码:

const mutations = {
    SET_MENU_TYPE (state, params) {
        state.menuType = params
    }
}

export default mutations

然后在组件里调用这个mutation:

<template>
    <section>
        <p>{{menuType}}</p>
        <button @click="handleChangeMenuType('2')">修改menuType的值</button>
    </section>
</template>
<script>
import {mapState} from 'vuex'
export default {
    computed: {
        ...mapState([
            'menuType',
        ]),
    },
    data () {
        return {
        }
    },
    methods: {
        handleChangeMenuType (params) {
            this.$store.commit('SET_MENU_TYPE', params)
        }
    },
}
</script>

同样,vuex也提供了辅助函数mapMutations来快速设置值:

<template>
    <section>
        <p>{{menuType}}</p>
        <button @click="handleChangeMenuType('2')">修改menuType的值</button>
    </section>
</template>
<script>
import {mapState, mapMutations} from 'vuex'
export default {
    computed: {
        ...mapState([
            'menuType',
        ]),
    },
    data () {
        return {
        }
    },
    methods: {
        ...mapMutations([
            'SET_MENU_TYPE'
        ]),
        handleChangeMenuType () {
            this.SET_MENU_TYPE('2')
        }
    },
}
</script>

还是同样的问题,放在模块里的值,应该怎样去提交mutation呢?我举个例子:

还是在src/store/module/user.js增加如下代码:

const state = {
    userName: '张三'
}
const getters = {
    userName: state => {
        return state.userName + '是管理员'
    }
}
const mutations = {
    SET_USER_NAME (state, params) {
        state.userName = params
    }
}
const actions = {}

export default {
    state,
    getters,
    mutations,
    actions
}

然后在组件里调用这个写在模块里的mutation:

<template>
    <section>
        {{taskId}}
        <ul>
            <li>今天你吃药了嘛?</li>
        </ul>
        <p>{{userName}}</p>
        <button @click="handleChangeMenuType">修改menuType的值</button>
    </section>
</template>
<script>
import {mapState, mapGetters, mapMutations} from 'vuex'
export default {
    computed: {
        ...mapGetters([
            'userName'
        ])
    },
    data () {
        return {
        }
    },
    methods: {
        ...mapMutations([
            'SET_USER_NAME'
        ]),
        handleChangeMenuType () {
            this.SET_USER_NAME('李四')
        }
    },
}
</script>

4. action用法

上面讲的调用mutation来修改vuex里的值,这个过程进行的是同步操作,如果某个值需要异步操作才能修改成功,此时就需要调用action,它是专门处理异步请求,然后改变vuex里的值的

比如,项目里的导航菜单,需要后端动态返回,像请求数据这些操作,肯定是异步操作,此时,我就在这里模拟一个请求,来修改menuList这个值

const state = {
    menuType: 1,
    menuList: []
}

export default state

首先在src/store/mutations.js里新建一个mutation:

const mutations = {
    SET_MENU_TYPE (state, params) {
        state.menuType = params
    },
    SET_MENU_LIST (state, params) {
        state.menuList = params
    }
}

export default mutations

其次新建src/api/app.js文件,在里面模拟一个异步请求的接口:

export const getMenuList = () => {
    return new Promise((resolve, reject) => {
        const err = null
        setTimeout(() => {
            if (!err) {
                resolve({
                    code: 200,
                    data: {
                        menuList: [
                            {name: '创建任务'},
                            {name: '任务列表'}
                        ]
                    }
                })
            } else {
                reject(err)
            }
        })
    })
}

找到src/store/actions.js文件,新增如下代码:

import {getMenuList} from '@/api/app'

const actions = {
    updateMenuList ({commit}) {
        getMenuList().then(res => {
            const {code, data: {menuList}} = res
            commit('SET_MENU_LIST', menuList)
        }).catch(err => {
            console.log(err)
        })
    }
}

export default actions

题外话:在调用一个异步函数,并且接收其返回的值,可以采用es7的async/await函数,写法如下:

import {getMenuList} from '@/api/app'

const actions = {
    async updateMenuList({commit}) {
        try {
            const {code, data: {menuList}} = await getMenuList()
            commit('SET_MENU_LIST', menuList)
        } catch (err) {
            console.log(err)
        }
    }
}

export default actions

然后在组件里调用这个action:

<template>
    <section>
        <button @click="handleChangeMenuList">异步获取菜单list</button>
        <ul>
            <li v-for="(item, index) in menuList" :key="index">{{item.name}}</li>
        </ul>
    </section>
</template>
<script>
import {mapState, mapGetters, mapMutations} from 'vuex'
export default {
    computed: {
        ...mapState([
            'menuList',
        ]),
    },
    data () {
        return {
        }
    },
    methods: {
        handleChangeMenuList () {
            this.$store.dispatch('updateMenuList')
        }
    },
}
</script>

同样,vuex也提供了辅助函数mapActions来调用action:

<template>
    <section>
        <button @click="handleChangeMenuList">异步获取菜单list</button>
        <ul>
            <li v-for="(item, index) in menuList" :key="index">{{item.name}}</li>
        </ul>
    </section>
</template>
<script>
import {mapState, mapGetters, mapMutations, mapActions} from 'vuex'
export default {
    computed: {
        ...mapState([
            'menuList',
        ]),
    },
    data () {
        return {
        }
    },
    methods: {
        ...mapActions([
            'updateMenuList'
        ]),
        handleChangeMenuList () {
            this.updateMenuList()
        }
    },
}
</script>

还是同样的问题,写在模块里的action如何调用?

找到src/api/app.js文件,新增一个异步接口:

export const getUserName = () => {
    return new Promise((resolve, reject) => {
        const err = null
        setTimeout(() => {
            if (!err) {
                resolve({
                    code: 200,
                    data: {
                        name: '李四'
                    }
                })
            } else {
                reject(err)
            }
        })
    })
}

然后在src/store/module/user.js文件里的actions里新增一个方法:

import {getUserName} from '@/api/app'

const state = {
    userName: '张三'
}
const getters = {
    userName: state => {
        return state.userName + '是管理员'
    }
}
const mutations = {
    SET_USER_NAME (state, params) {
        state.userName = params
    }
}
const actions = {
    async getUserName ({commit}) {
        try {
            const {code, data: {name}} = await getUserName()
            commit('SET_USER_NAME', name)
        } catch (error) {
            console.log(err)
        }
    }
}

export default {
    state,
    getters,
    mutations,
    actions
}

最后在组件里调用:

<template>
    <section>
        <button @click="handleChangeMenuList">异步获取菜单list</button>
        <ul>
            <li v-for="(item, index) in menuList" :key="index">{{item.name}}</li>
        </ul>
        <button @click="handleChangeUserName">异步获取userName</button>
        <p>{{userName}}</p>
    </section>
</template>
<script>
import {mapState, mapGetters, mapMutations, mapActions} from 'vuex'
export default {
    computed: {
        ...mapState([
            'menuList',
        ]),
        ...mapGetters([
            'userName'
        ])
    },
    data () {
        return {
        }
    },
    methods: {
        ...mapMutations([
            'SET_USER_NAME'
        ]),
        ...mapActions([
            'updateMenuList',
            'getUserName'
        ]),
        handleChangeMenuList () {
            this.updateMenuList()
        },
        handleChangeUserName () {
            this.getUserName()
        }
    },
}
</script>

以上就是vuex的基本用法,通过这篇文章,我相信在项目中使用vuex是没有任何问题的,关于vuex更高级的用法,可以在下一篇文章中学到

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,670评论 5 460
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,928评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,926评论 0 320
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,238评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,112评论 4 356
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,138评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,545评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,232评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,496评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,596评论 2 310
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,369评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,226评论 3 313
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,600评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,906评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,185评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,516评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,721评论 2 335