VUEX

image-20210207210747394

Action:异步操作

Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。Vuex 也集成到 Vue 的官方调试工具 devtools extension (opens new window),提供了诸如零配置的 time-travel 调试、状态快照导入导出等高级调试功能。

使用步骤:

store/index.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

export default new Vuex.Store({
state: {
counter: 0
},
mutations: {
increment(state) {
state.counter++
},
decrement(state) {
state.counter--
}
},
actions: {},
modules: {}
})

helloVue.vue

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<template>
<div>
<h1>{{ $store.state.counter }}</h1>
</div>
</template>

<script>
export default {
name: "helloVue"
}
</script>

<style scoped>

</style>

app.vue

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
49
<template>
<div id="app">
<h1>{{ $store.state.counter }}</h1>
<button @click="add">+</button>
<button @click="sub">-</button>
<hello-vue></hello-vue>
</div>
</template>

<script>
import helloVue from "@/components/helloVue";

export default {
components: {
helloVue
},
methods: {
add() {
this.$store.commit("increment")
},
sub() {
this.$store.commit("decrement")
}
}
}
</script>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
}

#nav {
padding: 30px;
}

#nav a {
font-weight: bold;
color: #2c3e50;
}

#nav a.router-link-exact-active {
color: #42b983;
}
</style>

注意:

  • 因为vue的官方不建议我们直接修改数据,这样的话我们的部署工具devtools就监听不到变化,所以我们要在idnex.js的 mutations修改数据
  • 我们在组件里面想要修改数据的时候,需要使用 ==this.$store.commit(“increment”)==,括号里面添加上mutations里面的函数名字

devtools

image-20210207213459845

Vuex的核心概念

Getters

相当于组件里面的计算属性,具体使用看代码:

需求:数值翻倍

无参

index.js

1
2
3
4
5
6
7
8
 state: {
counter: 0
},
getters: {
doubleCounter(state) {
return state.counter * 2;
}
}

使用:

1
2
<!--    Getters-->
<h1>{{ $store.getters.doubleCounter }}</h1>
有参

如果需要传递参数,那么就需要你使用getters的时候,返回的是一个函数而不是一个直接的结果:

1
2
3
4
5
6
7
8
 state: {
counter: 0
},
TriCounter(state) {
return (trigger) => {
return state.counter * trigger
}
}

使用:

1
<h1>{{ $store.getters.TriCounter(10) }}</h1>

需要注意的是我们在使用的时候需要传递一个参数,把getter当作一个函数来使用;

使用getter作为数据
1
2
3
4
5
6
state: {
counter: 0
},
fourCounter(state, getter) {
return state.counter * getter.doubleCounter*0
}

传递的时候,要在对应的getter上添加上第二个计算属性的函数名

mutations

==只可以写同步的代码,不可以写异步代码==

修改state的唯一途径

1
2
3
4
5
6
7
8
9
10
11
state: {
counter: 0
},
mutations: {
increment(state) {
state.counter++
},
decrement(state) {
state.counter--
}
},

给mutation传入一个参数:

1
2
3
4
5
6
7
8
state: {
counter: 0
},
mutations: {
addCount(state, count) {
state.counter = count * state.counter;
}
},
1
2
3
4
5
<h1>mutation-----------</h1>
<button @click="addSt(5)">+5</button>
addSt(count) {
this.$store.commit("addCount", count)
}

直接俄在使用的时候,在type后面把参数传出去

其他风格的提交方式:

1
2
3
4
5
6
addSt(count) {
this.$store.commit({
type: 'addCount',
count
})
}

一旦以这个方式提交,无论我们提交的数据有多复杂,对于我们的vuex来说就是一个对象,他会把数据进行一个封装,变成我们的一个对象使用

index.js

1
2
3
4
addCount(state, count) {
//count是一个对象
state.counter = count.count * state.counter;
}
给数据的添加和删除添加响应式;

vue.set()和vue.delete();

Action

执行异步操作的属性;例如ajax就要在这个里面获得

我们的vuex不会让我们直接在mutation异步操作数据;记住这个概念,不是不允许而是不可以直接修改,可以使用action,然后再获得mutation的数据再来修改数据

代码:

index.js

1
2
3
4
5
6
7
8
actions: {
addCounterAsync(context) {
return new Promise((resolve, reject) => {
//修改state只能式mutation
resolve(context.commit("addCounter"))
})
}
},

vue

1
2
3
4
addAction() {
this.$store.dispatch('addCounterAsync').then(res => {
console.log(res);
})

modules

因为vuex使用单一依赖原则,建议我们的store只有一个,所以我们就不用创建多个store对象,我们可以使用modules融合多个对象,实际上的呈现也是如此

代码:

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
const a = {
state: {
name: "saxon"
}
}
export default new Vuex.Store({
state: {
counter: 0
},
mutations: {
addCounter(state) {
state.counter++;
}
},
actions: {
addCounterAsync(context) {
return new Promise((resolve, reject) => {
//修改state只能式mutation
resolve(context.commit("addCounter"))
})
}
},
modules: {a},
getters: {}
})

vue

1
2
<h2>这是modules显示的内容----------------</h2>
<h2>{{ $store.state.a.name }}</h2>

使用的时候需要使用模块名,实际上渲染出来的效果显示式下面这样的;

image-20210209185346144

他变成了原来state里面的一个对象

==在modules里面修改数据==

1
2
3
4
5
6
7
8
9
10
const a = {
state: {
name: "saxon"
},
mutations: {
updateName(state) {
state.name = "saxon mo"
}
}
}

vue

1
2
3
updateName() {
this.$store.commit("updateName", " 最帅")
}

实际渲染中,他和我们在根目录上创建一个没有区别,结果是一样的;调用也一样;

image-20210209185930589

模块getter之间互相调用和获得根的state内容

1
2
3
4
5
6
7
8
getters: {
updateName2() {
return "---mo---"
},
fullName(state, getters, rootState) {
return state.name + getters.updateName2 + rootState.counter
}
}

使用action

1
2
3
4
5
actions: {
updateInfo(context) {
context.state.name = "莫松"
}
}

==组件里面的context上下文☞的不再是store==