Vue全家桶之---Vuex

447 阅读4分钟
Vuex主要作用是一个数据仓库,管理的是状态。可以存储数据,使得该项目下所有的页面可以访问该仓库中的数据或方法
这里前提需要搭建一个vue项目,并且有一个组件Count.vue,通过vue-router可以跳转到该组件,具体实现这里不再赘述

一、安装Vuex,初体验

npm i vuex -S

src 目录下新建一个文件夹 vuex , 在该目录下新建一个 store.js , 然后写入如下代码

import Vue from 'vue'    //引入vue
import Vuex from 'vuex'    //引入vuex
Vue.use(Vuex)    //在vue中使用vuex

现在有个需求是,需要在页面上显示一个 count , 并且这个 count 是从 vuex 中读取出来的,并且在页面中可以通过 两个按钮 分别改变 vuexcount 的 加减

首先,在 store.js 下写入如下代码:

//定义数据
const state = {
    count: 1
}

export default new Vuex.Store({
    state
})

Count.vue 文件中有如下代码:

<template>
    <div>
        <h2>{{$store.state.count}}</h2>
    </div>
</template>

<script>
    import store from '@/vuex/store';
    export default {
        data(){
            return{
                
            }
        },
        store
    }
</script>

接下来我们需要通过两个按钮来改变 count 的值

修改 Count.vue 为如下:

<template>
    <div>
        <h2>{{$store.state.count}}</h2>
        <p>
            <button>+</button>
            <button>-</button>
        </p>
    </div>
</template>

<script>
    import store from '@/vuex/store';
    export default {
        data(){
            return{
                
            }
        },
        store
    }
</script>

接下来我们需要在 vuex 中定义方法,在 store.js 文件添加如下内容:

//定义方法
const mutation = {
    add(state){
        state.count++;
    },
    reduce(state){
        state.count--;
    }
}

//将mutations添加到vuex
export default new Vuex.Store({
    state,
    mutations
})

注意:要想改变 Vuex state 的值,只能通过 mutations 改变

然后在 Count.vue 中调用 vuex 中定义的方法来修改 statecount 的值

//通过commit方法触发vuex的mutations的方法
...
    <p>
        <button @click="$store.commit('add')">+</button>
        <button @click="$store.commit('reduce')">-</button>
    </p>
...

二、State访问状态对象

state指的是状态对象,在SPA(单页应用)中,状态对象用来保存所有组件公用的状态,比如用户登录信息
需求是用不同方法在组件中输出state内的数据

首先打开 Count.vue 

2.1 第一种输出方式

<h2>{{$store.state.count}}</h2>

在第一节中就是用的是这种输出方式,在标签内写的太麻烦,请看第二种方式

2.2 第二种输出方式,计算属性(computed)

<template>
    <div>
        <h2>{{count}}</h2>
    </div>
</template>

<script>
import store from '@/vuex/store'
export default {
    computed:{
        count(){
            return this.$store.state.count
        }
    },
    store
}
</script>

2.3 第三种输出方式,mapState

<template>
    <div>
        <h2>{{count}}</h2>
    </div>
</template>

<script>
import store from '@/vuex/store'
import {mapState} from 'vuex'
export default {
    computed:mapState({
        count:state => state.count
    }),
    store
}
</script>

2.4 第四种输出方式,mapState(数组形式)

<template>
    <div>
        <h2>{{count}}</h2>
    </div>
</template>

<script>
import store from '@/vuex/store'
import {mapState} from 'vuex'
export default {
    computed:mapState(['count']),//数组中是字符串,该组件需要state里面的哪些数据,就将这些数据传在mapState数组中
    store
}
</script>

三、Mutations修改状态

Mutations中定义的方法是用来修改vuex中的state的状态的,有两个参数,第一个参数是state对象,第二个参数是pload,pload接收的是调用mutations种方法传的参数
这里有个需求是需要点击增加按钮之后自定义增加的数量,最开始的时候是加1

首先,先来改写一下 Mutationsadd 方法

const mutation = {
    add(state,pload){
        state.count+=pload;
    },
    reduce(state,pload){
        state.count--;
    }
}

Count.vue 文件中调用 Mutations 中定义的方法来修改 State 中的状态

...
    <p>
        <button @click="$store.commit('add',10)">+</button>
        <button @click="$store.commit('reduce')">-</button>
    </p>
...

这样就可以在 Count.vue 中每次点击 加号 按钮, State 中的 count 就会 加10

在vue文件中用 commit方法 触发 Mutations 中定义的方法,第一个参数是 Mutations 中定义的方法名,第二个参数是要传递给该方法的参数

3.1 引用方法

Count.vue 中同样先 引入 store,并且从 vuex 中引入 mapMutations

import store from '@/vuex/store'
import { mapState,mapMutations } from 'vuex'
export default {
    data(){
        return {
        
        }
    },
    computed:mapState(['count']),
    methods:mapMutations(['add','reduce'])
}

然后在 Count.vue 模板中直接调用该 reduce 方法

...
    <p>
        <button @click="$store.commit('add',10)">+</button>
        <button @click="reduce">-</button>
    </p>
...

四、Getters(Vuex中的计算属性)

相当于vue中的computed,计算属性

首先打开 store/index.js ,先定义 getter 要进行什么处理

const getter = {
    count:(state) => state.count += 100
}

回到 Count.vue修改 computed 写法

...
computed:{
    ...mapState(['count']),
    count:()=>{
        return this.$store.getters.count
    }
}
...

简写

import { mapGetters } from 'vuex'
...
computed:{
    ...mapState(['count']),
    ...mapGetters(['count'])
}
...

五、Actions(异步修改状态)

首先打开 store/index.js 

// 定义异步方法
const actions = {
    addAction(context){
        context.commit('add',10)
    },
    reduceAction({commit,dispatch}){
        commit('reduce')
    }
}

回到 Count.vue 在模板中这样写:

...
    <p>
        <button @click="addAction">+</button>
        <button @click="reduceAction">-</button>
    </p>
...

同样将 methods 改成如下写法

import { mapActions } from 'vuex'

...
methods:{
    ...mapMutations(['add','reduce']),
    ...mapActions(['addAction','reduceAction'])
}
...

六、module模块组

模块组的定义就是将state、mutations、actions、getter放在一个js文件中,该js称为一个模块,将多个模块放在一个modules里面形成模块组

6.1 声明模块组

首先打开 store/index.js 

// 模块文件里包含了该模块对应的state、mutations、actions、getter
import user from './user'
import goods from './goods'

const moduleA = {
    user
}

const moduleB = {
    goods
}

export default new Vuex.Store({
    modules:{
        a:moduleA,
        b:moduleB
    }
})

6.2 组件中使用

...
<p>{{$store.state.a.count}}</p>
...

<p>{{count}}</p>

<script>
...
computed : {
    // a指的store->modules下的模块名
    count() => this.$store.state.a.count
}
...
</script>

七、在Nuxt.js中使用Vuex

在Nuxt.js中如果使用Vuex,我们不需要安装引用,Nuxt已经帮我们解决了这个问题

只需要在Nuxt的store目录下创建js文件即可

每一个js文件都可以是一个模块(当然index.js除外,这是根模块)

首先创建一个 tools.js 模块

export const state = () => ({})

export const mutations = {}

export const actions = {
    getTools({commit,dispatch}){
        return axios.get('/tools/searchAll')
    }
}

在组件中使用,请参考如下代码

//如果要使用state
this.$store.state.count        //取跟模块下state中的count
this.$store.state.tools.count  //取tools模块下state中的count
 
//如果要使用mutations
this.$store.commit('SET_TOKEN',params)    //根模块下的mutations方法
this.$store.commit('tools/SET_TOKEN',params)    //tools模块下的mutations方法
 
//如果要使用actions
this.$store.dispatch('getTools')    //根模块下的actions中的getTools方法
this.$store.dispatch('tools/getTools')    //tools模块下的actions中的getTools方法