记录学习过程,如有错误之处,欢迎指导。
我们通常在组件间数据中使用父子组件传输方法,只在父与子之间进行数据传递,但是多个父子组件进行数据传递或者没有关联的组件之间要使用同一组数据,如果还是这个方法的话十分繁琐,这个时候我们就可以使用Vuex。
概念
官网介绍:Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式,它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。
其实可以简单的看成是多个组件变量全部储存在一个对象里面,可以共同使用这些变量,并且能够进行响应式。
- State:驱动应用的数据源,用来存储公共数据。
- Mutation: 更改 Vuex 的 store 中的状态的唯一方法,每个 mutation 都有一个字符串的 事件类型 (type) 和 一个 回调函数 (handler)。
- Action :Action 类似于 mutation。不同在于:
Action 提交的是 mutation,而不是直接变更状态。
Action 可以包含任意异步操作。
使用场景
- 用户的登录状态,名称、头像等信息。
- 购物网站的收藏、购物车中的物品等。
- 需要多个组件共同使用的变量,都可以使用Vuex。
Vuex的安装及使用
Vuex的安装
安装: npm install vuex --save
通过 Vue.use() 来安装 Vuex
import Vue from "vue"
import Vuex from "vuex"
Vue.use(Vuex);
使用
- 我们需要在一个地方存放vuex,创建store文件夹,并且在这个文件夹下面创建index.js文件。
index.js
import Vue from 'vue'
import Vuex from 'vuex'
//1.安装插件
Vue.use(Vuex)
//2.创建对象
const store = new Vuex.Store({
state: {
counter:100
},
mutations: {
increment(state){
state.counter++;
},
decrement(state) {
state.counter--;
}
},
})
//3.暴露
export default store
2.在main.js中引入store对象,并且放在new Vue中。目的:使所有组件都可以使用这个store对象。
import Vue from 'vue'
import App from './App'
import store from "./store"
new Vue({
el: '#app',
store,
render: h => h(App)
})
3.使用store中的数据对象。
- 通过 this.$store.state 属性的方式来访问。
- 通过 this.$store.commit(‘mutation中定义的方法’) 来修改状态(只能通过mutation来修改状态,这样可以让我们更好的追踪每一个状态的变化。
在demo.vue中的使用
<template>
<div id="app">
<h2>{{$store.state.counter}}</h2>
<button @click="add">+</button>
<button @click="sub">-</button>
</div>
</template>
<script>
export default {
name: 'App',
data() {
return {}
},
methods: {
add() {
this.$store.commit('increment');
},
sub() {
this.$store.commit('decrement');
}
}
}
</script>
<style></style>
Vuex核心
state
单一状态树,可以称为单一数据源,所以每个应用仅仅包含一个store实例。单一状态树让我们能够直接地定位任一特定的状态片段,在调试的过程中也能轻易地取得整个当前应用状态的快照。(官网)
geeter
有时候我们需要从 store 中的 state 中派生出一些状态,例如对列表进行过滤并计数。如果有多个组件需要用过滤,我们可以复制过滤函数用在每一个组件中但是这种方法过于繁琐。
Vuex 允许我们在 store 中定义“getter”(可以认为是 store 的计算属性)。就像计算属性一样,getter 的返回值会根据它的依赖被缓存起来,且只有当它的依赖值发生了改变才会被重新计算。
const store = new Vuex.Store({
state: {
list: [
{id: 1, name: '前端1', num: 12},
{id: 2, name: '前端2', num: 14},
{id: 3, name: '前端3', num: 22},
{id: 4, name: '前端4', num: 20}
]
},
getters: {
getNum(state) {
return state.list.filter(item => {
return item.num < 25;
});
},
getStuLength(state, getters) {
return getters.getStu.length;
}
})
我们可以通过属性的形式进行访问
<h2>{{$store.getters.getNum}}</h2>
getter 也可以接受其他 getter 作为第二个参数:
const store = new Vuex.Store({
state: {
list: [
{id: 1, name: '前端1', num: 12},
{id: 2, name: '前端2', num: 14},
{id: 3, name: '前端3', num: 22},
{id: 4, name: '前端4', num: 20}
]
},
getters: {
getNum(state) {
return state.list.filter(item => {
return item.num < 25;
});
},
getLength(state, getters) {
return getters.getNum.length;
}
})
mutation
更改 Vuex 的 store 中的状态的唯一方法是提交 mutation。
Vuex 中的 mutation 非常类似于事件:每个 mutation 都有一个字符串的 事件类型 (type) 和 一个 回调函数 (handler)。
不传递参数
const store = new Vuex.Store({
state: {
count: 1
},
mutations: {
increment (state) {
// 变更状态
state.count++
}
}
})
使用:this.$store.commit(‘increment’)
传递参数
// ...
mutations: {
increment (state, payload) {
state.count += payload
}
}
使用: store.commit(‘increment’,10)
actions
Action 类似于 mutation,不同在于:
• Action 提交的是 mutation,而不是直接变更状态。
• Action 可以包含任意异步操作。
我们尽量不要在muation中进行异步操作,否则状态的改变无法被追踪,所以我们需要使用actions进行异步操作。
- 注册一个简单的action。
const store = new Vuex.Store({
state: {
count: 0
},
mutations: {
increment (state) {
state.count++
}
},
actions: {
increment (context) {
context.commit('increment')
}
}
})
Action 函数接受一个与 store 实例具有相同方法和属性的 context 对象,因此你可以调用 context.commit 提交一个 mutation,或者通过 context.state 和 context.getters 来获取 state 和 getters。
- 在组件中分发 Action
Action 通过 store.dispatch 方法触发:
this.$store.dispatch('increment')
// 以载荷形式分发
this.$store.dispatch('incrementAsync', {
amount: 10
})
// 以对象形式分发
this.$store.dispatch({
type: 'incrementAsync',
amount: 10
})
- 组合action
组合多个 action,以处理更加复杂的异步流程
store.dispatch 可以处理被触发的 action 的处理函数返回的 Promise,在this.$store.dispatch后面使用then方法。
this.$store.dispatch('actionA').then(() => {
// ...你想要的处理
})
module
由于使用单一状态树,应用的所有状态会集中到一个比较大的对象。当应用变得非常复杂时,store 对象就有可能变得相当臃肿。
为了解决以上问题,Vuex 允许我们将 store 分割成模块(module)。每个模块拥有自己的 state、mutation、action、getter、甚至是嵌套子模块——从上至下进行同样方式的分割(官网)。
const moduleA = {
state: () => ({ ... }),
mutations: { ... },
actions: { ... },
getters: { ... }
}
const moduleB = {
state: () => ({ ... }),
mutations: { ... },
actions: { ... }
}
const store = new Vuex.Store({
modules: {
a: moduleA,
b: moduleB
}
})
store.state.a // -> moduleA 的状态
store.state.b // -> moduleB 的状态