海边的小溪鱼

vuePress-theme-reco 海边的小溪鱼    2017 - 2023
海边的小溪鱼 海边的小溪鱼

Choose mode

  • dark
  • auto
  • light
首页
分类
  • CSS
  • HTTP
  • Axios
  • jQuery
  • NodeJS
  • JavaScript
  • Vue2
  • Server
  • Vue3
标签
时间轴
更多
  • Gitee (opens new window)
Getee (opens new window)
author-avatar

海边的小溪鱼

28

文章

14

标签

首页
分类
  • CSS
  • HTTP
  • Axios
  • jQuery
  • NodeJS
  • JavaScript
  • Vue2
  • Server
  • Vue3
标签
时间轴
更多
  • Gitee (opens new window)
Getee (opens new window)

Vuex(状态管理)

vuePress-theme-reco 海边的小溪鱼    2017 - 2023

Vuex(状态管理)

海边的小溪鱼 2022-07-14 Vuex

Vuex的安装和配置、Vuex的基本使用(State、Mutation、Action、Getter)

# Vuex 的安装和配置

Vuex是实现组件全局状态(数据)管理的一种机制,可以方便的实现组件之间数据的共享

(1). 安装 Vuex 依赖包:npm install vuex@3.6.2 -S
(2). 在 项目下 新建 store/index.js 文件

// store/index.js 文件

import Vue from 'vue'

// 1. 导入 vuex
import Vuex from 'vuex'
Vue.use(Vuex)

// 2. 创建 store 实例对象(数据源)
export default new Vuex.Store({

    // (1) state:定义全局的数据(数据保存在内存中,可以在浏览器本地查看到)
    state: {
        count: 0,
    },

    // (2) mutations:定义全局的方法(用于修改 state 中的数据)
    mutations:{},

    // (3) actions:定义全局"异步操作"的方法(如:发请求、计时器)
    actions: {},

    // (4) getters:定义全局"包装数据"的方法(用于对 state 中的数据进行包装)
    getters: {},

})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

(3). 在 main.js 入口文件中,挂载 store 对象

// main.js 入口文件

import store from './store'
new Vue({
    router,
    // 将 store 对象,挂载到 vue 实例中
    // 所有的组件,可以直接获取到 store 中定义的全局数据、全局方法、等
    store,
    render: h => h(App)
}).$mount('#app')
1
2
3
4
5
6
7
8
9
10

(4). 组件中获取全局数据

<template>
    <div>
        <!-- 组件中获取 state 中的全局数据 -->
        <h1>{{ $store.state.count }}</h1>
    </div>
</template>
1
2
3
4
5
6

# 1. State 的使用(全局数据)

State 提供唯一的公共数据源,所有的共享数据都要放到 state 中进行存储

1. 在 store 实例对象中,定义 state 节点(用于定义全局数据)

// store/index.js 文件

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

// 创建 store 实例对象(数据源)
export default new Vuex.Store({
    // state:定义全局数据(数据保存在内存中,可以在浏览器本地查看到)
    state: {
        count: 0,
    },
})
1
2
3
4
5
6
7
8
9
10
11
12
13

2. 在组件中获取 state 中的数据:有两种方式

<template>
    <div>
        <!-- 方式1:组件中获取 state 中的全局数据 -->
        <h1>{{ $store.state.count }}</h1>
        <!-- 方式2:组件中获取 state 中的全局数据 -->
        <h1>{{ count }}</h1>
    </div>
</template>

<script>
// 2-1 按需导入 mapState 函数
import { mapState } from 'vuex' 
export default {
    // 2-2 使用 mapState 函数,将全局数据,映射为当前组件的计算属性
    computed: {
        // 将 count 全局数据,映射为当前组件的计算属性(在模板中直接渲染)
        ...mapState(["count"]) 
    }
};
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

注意:不建议在组件中直接修改 state 中的数据,建议通过 mutation 来修改 state 中的数据

# 2. Mutations 的使用(全局方法)

Mutations 用于变更 state 中的数据

1. 在 store 实例对象中,定义 Mutations 节点(用于修改 state 中的数据)

// store/index.js 文件

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

export default new Vuex.Store({
    state: {
        count: 0,
        num: 10
    },

    // mutations:定义全局方法(用于修改 state 中的数据)
    mutations:{
        // 定义方法(且第一个参数必须为 state 对象)
        add(state) {
            state.count++ // 让count值自增
        },
        setNum(state, newNum) {
            state.num = newNum // 接收一个参数,赋值给num
        }
    },
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

2. 在组件中调用 mutations 中的方法:有两种方式

<template>
    <div>
        <h1>当前值为:{{ $store.state.count }}</h1>
        <button @click="change">+1</button>
        <h2>{{ $store.state.num }}</h2>
    </div>
</template>

<script>
// 按需导入 mapMutation 函数
import { mapMutations } from 'vuex' 
    
export default {
    methods: {
        change() {
            // 方式1:使用 commit 来触发 mutations 中的 add方法
            this.$store.commit("add")
            // 触发 setNum 方法,并传入参数
            this.$store.commit("setNum", 100)
        },
        // 方式2:使用 mapMutation 函数,将 add、setNum 全局方法,映射为当前组件的方法
        ...mapMutations(["add", "setNum"]) 
        change() {
    		// 映射后的方法,直接调用(相当于组件自己的方法)
            this.add()
            this.setNum(200)
        },
    }
};
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30

注意:mutations 节点下,不能进行异步操作(如:计时器、发请求)

# 3. Actions 的使用(异步操作)

Actions 用于处理异步操作

1. 在 store 实例对象中,定义 Actions 节点(用于用于处理异步操作)

// store/index.js 文件

export default new Vuex.Store({
    state: {
        count: 0,
    },
    // mutations:定义全局方法(用于修改 state 中的数据)
    mutations:{
        // 定义方法(且第一个参数必须为 state 对象)
        addN(state, step) {
            state.count += step
        }
    },

    // actions:定义全局"异步操作"方法(如:计时器、axios请求)
    actions: {
        // 定义一个异步操作的方法
        addAsync(context,num) { // 第一个参数必须为context
            setTimeout(() => {
                context.commit("addN", num) // 通过 commit 触发 mutations 中的 addN 方法,并传入参数
            }, 1000)
        },
    }
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

2. 在组件中调用 actions 中的异步方法:有两种方式

<script>
// 按需导入 mapActions 函数
import { mapActions } from 'vuex' 
    
export default {
    methods: {
        change() {
            // 方式1:使用 dispatch 来触发 actions 中的 addAsync 异步方法,并传入参数
            this.$store.dispatch("addAsync", 5)
        },
        // 方式2:使用 mapActions 函数,将 addAsync 全局异步方法,映射为当前组件的异步方法
        ...mapActions(["addAsync"]) 
        change() {
    		// 映射后的方法,直接调用(相当于组件自己的方法)并传入参数
            this.addAsync(10)
        },
    }
};
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

注意:在 actions 中,不能直接修改 state 中的数据(需要通过 context.commit() 来触发 mutations 中的方法,间接变更数据)

# 4. Getters 的使用(包装数据)

Getters 用于包装 State 中的数据

1. 在 store 实例对象中,定义 Getters 节点(用于对 State 中的数据进行加工处理,形成新的数据,类似于计算属性)

// store/index.js 文件

export default new Vuex.Store({
    state: {
        count: 0,
    },

    // getters:定义全局"包装数据"的方法(用于对 state 中的数据进行包装)
    getters: {
        showNum(state) {
            return "当前最新的值为" + state.count // 包装数据,并返回
        },
        // 也可以这样写
        showNum: state => {
        	return "当前最新的值为" + state.count
    	}
    }
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

2. 在组件中获取 getters 中的方法返回的包装数据:有两种方式

<template>
    <div>
        <!-- 方式1:组件中获取 getters 中的方法返回的包装数据 -->
        <h1>{{ $store.getters.showNum }}</h1>
        <!-- 方式2 -->
        <h1>{{ showNum }}</h1>
    </div>
</template>

<script>
// 2-1 按需导入 mapGetters 函数
import { mapGetters } from 'vuex' 
export default {
    computed: {
        // 2-2 将 getters 中的方法返回的包装数据,映射为当前组件的计算属性
        ...mapGetters(["showNum"])  // 模板中直接渲染
    }
};
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

注意:Getters 不会修改 State 中的原数据,只起到包装数据的作用(State 中的数据发生变化时,Getters 中的数据也会跟着变化)

# 总结

总结:Vuex 的使用

1. 在 store/index.js 中,定义全局的数据和方法

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

export default new Vuex.Store({

    // 1. state:定义全局的数据(数据保存在内存中,可以在浏览器本地查看到)
    state: {
        count: 0,
    },

    // 2. mutations:定义全局的方法(用于修改 state 中的数据)
    mutations:{
        // 第一个参数必须为 state 对象
        add(state) {
            state.count ++
        },
        addN(state, num) {
            state.count += num
        }
    },

    // 3. actions:定义全局"异步操作"的方法(如:发请求、计时器)
    actions: {
        // 第一个参数必须为context
        addAsync(context,num) { 
            setTimeout(() => {
                // 通过 commit 触发 mutations 中的 add 方法,并传入参数
                context.commit("add", num) 
            }, 1000)
        },
    },

    // 4. getters:定义全局"包装数据"的方法(用于对 state 中的数据进行包装)
    getters: {
        showNum: state => {
            return "当前最新的值为" + state.count // 返回包装的数据
        }
    }

})

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42

2. 在组件中,获取全局数据 和 调用全局方法

<template>
    <div>
        <!-- 【1】获取 state 中的数据 -->
        <!-- 方法一:使用 $store.state.全局数据名称 直接渲染出 state 中的数据 -->
        <h1>{{ $store.state.count }}</h1>
        <!-- 方法二:使用 mapState 函数 -->
        <h2>{{ count }}</h2>
        
        <!-- 【2】 调用 mutations 中的方法 -->
        <!-- 方法一:使用 commit 来触发 mutations 中的 add 方法 -->
        <button @click="$store.commit('add')"></button>
        <!-- 方法二:使用 mapMutations 函数 -->
        <button @click="addN(5)"></button>
        
        <!-- 【3】 调用 actions 中的方法 -->
        <!-- 方法一:使用 dispatch 来触发 actions 中的 addAsync 方法 -->
        <button @click="$store.dispatch('addAsync')"></button>
        <!-- 方法二:使用 mapActions 函数 -->
        <button @click="addAsync(5)"></button>
        
        <!-- 【4】获取 getters 中的方法返回的包装数据 -->
        <!-- 方法一:使用 $store.getters.包装数据方法名 直接渲染返回的包装数据 -->
        <h1>{{ $store.getters.showNum }}</h1>
        <!-- 方法二:使用 mapGetters 函数 -->
        <h2>{{ showNum }}</h2>
    </div>
</template>

<script>
import { mapState, mapMutations, mapActions, mapGetters } from 'vuex' 
    
export default {
    computed: {
        // mapState 函数:将 state 中的 count 数据,映射为当前组件的计算属性
        ...mapState(["count"]) // 模板中直接渲染

        // mapGetters 函数: 将 getters 中的方法返回的包装数据,映射为当前组件的计算属性
        ...mapGetters(["showNum"]) // 模板中直接渲染
    },
    methods: {
        // mapMutations 函数:将 mutations 中的 addN 方法,映射为当前组件的方法
        ...mapMutations(["addN"]) // 模板中直接调用并传参
        
        // mapActions 函数:将 actions 中的 addAsync 异步方法,映射为当前组件的异步方法
        ...mapActions(["addAsync"]) // 模板中直接调用并传参
    }
};
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
帮助我们改善此页面! (opens new window)