什么是Vuex?Vuex的使用?
1.vuex简介
官方文档说Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。简单的来说,它的作用就是将应用中所有的状态都放在一起,集中式来管理。
1.1什么时候使用Vuex?
组件之间的通信方式有父传子、子传父、兄弟组件通信,这些组件之间都存在着某种关系,当我们传值的时候可能会很方便,但是当两个没有关联(相隔甚远)的组件之间要使用同一组数据的时候,就需要用到vuex来进行统一管理公用的数据。
官方文档中有说明:vuex适用于开发大型单页面应用,如果是小系统,数据少,就没有必要。
如果您不打算开发大型单页应用,使用 Vuex 可能是繁琐冗余的。确实是如此——如果您的应用够简单,您最好不要使用 Vuex。一个简单的 store 模式 (opens new window)就足够您所需了。但是,如果您需要构建一个中大型单页应用,您很可能会考虑如何更好地在组件外部管理状态,Vuex 将会成为自然而然的选择。
2.vuex核心概念
2.1. store
每一个 Vuex 应用的核心就是 store(仓库)。从字面意义来讲,仓库就是来存储东西的,对于vuex来讲,它需要借用store对象来对公共数据进行统一管理,所有的数据都需要放在store的state中,并且每个vuex有且仅有一个对象。
2.2.1.安装插件
一般情况下,我们需要在src目录下新建一个store文件夹,在store中新建一个index.js文件,项目结构如下:
然后在index.js中安装vuex插件
import Vuex from 'vuex'
//1.安装插件
Vue.use(Vuex)
2.2.2.创建store对象
//2.创建Store对象
const store = new Vuex.Store({
state:{
counter: 100,
students: [
{ id: 110, name: 'lipan', age: 19 },
{ id: 111, name: 'ysl', age: 21 },
{ id: 112, name: 'li', age: 24 },
],
info: {
name: '小明',
age: 40,
height: 1.98
}
},
//mutations 中的代码必须是同步操作
//state状态的改变必须通过mutations
mutations:{
},
//action 类似于mutation 但是action是用来代替mutation进行异步操作的
actions:{
},
getters:{
},
modules: {
a: moduleA
}
})
2.2.3. 导出store对象
//3.导出store
export default store
2.3.vuex五大核心概念
- state – 存放的就是一些简单的数据,也就是状态
- 2.getters – state的计算属性
- 3.mutations – 更改状态的逻辑,同步操作
- 4.actions – 提交mutation,异步操作
- 5.mudules – 将store模块化
2.4.当在组件中获取vuex状态时
我们如何在 Vue 组件中展示状态呢?由于 Vuex 的状态存储是响应式的,从 store 实例中读取状态最简单的方法就是在计算属性中返回某个状态:
// 导入store
import store from 'store'
// 创建一个 Counter 组件
const Counter = {
template: `<div>{{ count }}</div>`,
computed: {
count () {
return store.state.count
}
}
}
每当 store.state.count 变化的时候, 都会重新求取计算属性,并且触发更新相关联的 DOM。然而,这种方式在每个需要使用 state 的组件中都需要频繁地导入,极不方便。
Vuex 通过 store 选项,提供了一种机制将状态从根组件“注入”到每一个子组件中(需调用 Vue.use(Vuex)):
import store from './store'
Vue.config.productionTip = false
/* eslint-disable no-new */
new Vue({
el: '#app',
store,
render: h => h(App)
})
通过在根实例中注册 store 选项,该 store 实例会注入到根组件下的所有子组件中,且子组件能通过 this.$store 访问到。
const Counter = {
template: `<div>{{ count }}</div>`,
computed: {
count () {
return this.$store.state.count
}
}
}
接下来我们来细说一下vuex五大核心概念
2.3.1. state
state上存放的,说的简单一些就是变量,也就是所谓的状态。没有使用 state 的时候,我们都是直接在 data 中进行初始化的,但是有了 state 之后,我们就把 data 上的数据转移到 state 上去了。另外有些状态是组件私有的状态,称为组件的局部状态,我们不需要把这部分状态放在store中去。
2.3.2. getters
有时候我们需要从 store 中的 state 中派生出一些状态,例如对列表进行过滤并计数:
getters: {
more20stu() {
return this.$store.state.students.filter(s => s.age >= 20);
},
getter其实就相当于vue组件中的computed属性,在组件中:
computed: {
more20stu() {
return this.$store.state.students.filter(s => s.age >= 20);
}
}
getters 接受 state 作为其第一个参数:
getters 也可以接受其他 getter 作为第二个参数:
const store = new Vuex.Store({
state:{
counter: 100,
students: [
{ id: 110, name: 'lipan', age: 19 },
{ id: 111, name: 'ysl', age: 21 },
{ id: 112, name: 'li', age: 24 },
],
info: {
name: '小明',
age: 40,
height: 1.98
}
},
getters: {
fullName(state) {
return state.name + '111'
},
fullName2(state, getters) {
console.log(getters);
return getters.fullName + '222'
},
fullName3(state, getters, rootState) {
return getters.fullName2 + rootState.counter
}
},
})
2.3.3. mutations
更改 Vuex 的 store 中的状态的唯一方法是提交 mutation,state中状态的更改只能放在mutation中。
我们可以向 store.commit 传入额外的参数,即 mutation 的 载荷(payload):payload也可以是一个对象,在大多数情况下,载荷应该是一个对象,这样可以包含多个字段并且记录的 mutation 会更易读
mutations: {
updateName(state, payload) {
state.info.name = payload
}
},
当在组件中需要更改state中数据时,只能通过提交(commit)mutation,然后在mutation中进行更改状态
updateName() {
this.$store.commit("updateName", "小花");
},
// 提交 mutation 的另一种方式是直接使用包含 type 属性的对象
updateName() {
this.$store.commit({
type:"updateName",
name:"小花"
});
},
2.3.4.actions
mutations中只能是同步操作,但是在实际的项目中,会有异步操作,那么actions就是为了异步操作而设置的,异步操作只能放在action中进行。
所以,当有异步操作的时候,我们需要在组件的methods中去提交actions,然后在actions中去异步提交(commit)mutation,最后在mutations中同步处理。只是提交actions的时候使用的是dispatch函数,而mutations则是用commit函数。
// 组件中
methods:{
syncUpdateName() {
this.$store.dispatch("aUpdateName");
},
}
// index.js文件中(store对象)
//content 这里相当于store
actions: {
aUpdateName(content) {
setTimeout(() => {
content.commit('updateName', '小宁')
}, 1000);
}
},
mutations: {
updateInfo(state) {
//state状态的改变必须通过mutations
state.info.name = '小龙';// 响应式
}
2.3.5. modules
当应用变得非常复杂时,store 对象就有可能变得相当臃肿。Vuex 允许我们将 store 分割成模块(module),每个模块拥有自己的 state、mutation、action、getter、甚至是嵌套子模块,从上至下进行同样方式的分割
modules: {
a: modulA,
b:modulB,
...
}
// 将modulA分离出去
const modulA = {
state: {
},
mutations: {
},
actions: {
},
getters: {
},
modules: {}
}