美文网首页
第5讲 vuex看完这篇你就会了(1)

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

作者: 喔喔牛在路上 | 来源:发表于2020-09-18 17:40 被阅读0次

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更高级的用法,可以在下一篇文章中学到

相关文章

网友评论

      本文标题:第5讲 vuex看完这篇你就会了(1)

      本文链接:https://www.haomeiwen.com/subject/snijyktx.html