Vuex 是什么?
vuex 是一个专门为vue.js应用程序开发的状态管理模式
。采用集中式存储管理
应用的所有组件的状态。(可以理解为在data中的属性,需要共享给其他组件使用的部分,也就是说,是我们需要共享的data,使用vuex进行统一集中式的管理。)
为什么要用 vuex ?
组件通信的类型
- 父子通信
- 跨级通信
- 兄弟通信
- 路由视图级别通信
什么是“状态管理模式”?
这个状态自管理应用包含以下几个部分:
- state,驱动应用的数据源;
- view,使用状态数据源的视图
- actions,使用状态数据源的视图
new Vue({
// state
data () {
return {
count: 0
}
},
// view
template: `
<div>{{ count }}</div>
`,
// actions
methods: {
increment () {
this.count++
}
}
})
这种模式遵循的是 单向数据流
模式
核心概念
- state:存储状态(变量)
- getters:加工state成员给外界,在组件中使用 $sotre.getters.fun()
- mutations:修改状态,并且是同步的。在组件中使用$store.commit(’’,params)。这个和组件中的自定义事件类似。
- actions:异步操作。在组件中使用是$store.dispath(’’)
- modules:store的子模块,模块化状态管理
Vue组件如果调用某个VueX的方法过程中需要向后端请求时或者说出现异步操作时,需要dispatch VueX中actions的方法,以保证数据的同步。action的存在就是为了让mutations中的方法能在异步操作中起作用。
state
state 的创建
存储应用状态数据的对象,state 的值可以是一个对象,也可以是一个返回对象的函数,类似 vue 中组件的 data ,使用函数的方式返回对象可以避免对象引用导致的副作用问题
// let state = {
// a: 1
// }
let state = _=>({a:1})
const store = new Vuex.Store({
state
})
const store2 = new Vuex.Store({
state
})
console.log(store.state == store2.state)
store.state.a = 100;
console.log(store.state.a, store2.state.a);
- 通过 store.state 访问状态数据
- state 数据与组件 data 一样是被追踪的
在组件中使用 store
// stores/index.js
import Vue from 'vue'
import Vuex from 'vuex'
import state from './state'
Vue.use(Vuex)
const store = new Vuex.Store({
state
})
export default store;
// stores/state.js
export default () => ({
title: '哈哈哈哈哈',
content: '啦啦啦啦啦啦啦啦'
})
<template>
<div class="home">
<h2>{{title}}</h2>
<div>{{content}}</div>
</div>
</template>
<script>
import store from '@/stores'
export default {
name: 'home',
data() {
return {
title: store.state.title,
content: store.state.content
}
}
}
</script>
Mutations
更改 Vuex 的 store 中的状态的唯一方法是提交 mutation,mutations是操作state数据的方法的集合,比如对该数据的修改、增加、删除等等。每个 mutation 都有一个字符串的 事件类型 (type) 和 一个 回调函数 (handler)
mutation 中的函数不要直接调用
提交
store.commit(type, payload)
// or
store.commit({
type: ...,
payload: ...
})
type
要提交的 mutation 回调函数名称,type 为固定的 key
payload
载荷:提交的额外数据,任意格式
Mutations使用方法
mutations方法都有默认的形参:([state] [,payload])
state是当前VueX对象中的state
payload是该方法在被调用时传递参数使用的
实例:
index.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
const store = new Vuex.store({
state:{
name:'helloVueX'
},
mutations:{
//es6语法,等同edit:funcion(){...}
edit(state){
state.name = 'jack'
}
}
})
export default store
而在组件中,我们需要这样去调用这个mutation——例如在App.vue的某个method中:
this.$store.commit('edit')
mutation 函数必须是同步的
commit 方法没有返回值
Mutation传值
单个值提交时:
this.$store.commit('edit',15)
当需要多参提交时,推荐把他们放在一个对象中来提交:
this.$store.commit('edit',{age:15,sex:'男'})
接收挂载的参数:
edit(state,payload){
state.name = 'jack'
console.log(payload) // 15或{age:15,sex:'男'}
}
Getters
可以对state中的成员加工后传递给外界,类似组件的 data 与 computed,store 也提供了一个 getters 对象来处理派生数据
Getters中的方法有两个默认参数
state 当前VueX对象中的状态对象
getters 当前getters对象,用于将getters下的其他getter拿来用
通过属性访问
与组件计算属性一样,默认是通过属性的方式去访问 getters 中的数据的,这种方式与组件的计算属性一样,也是会缓存结果的
通过方法访问
还可以通过闭包函数的形式返回一个函数,来实现给 getters 函数传参,需要注意的是这种方式不支持结果缓存
实例:
getters:{
nameInfo(state){
return "姓名:"+state.name
},
fullInfo(state,getters){
return getters.nameInfo+'年龄:'+state.age
}
}
在组件中调用:
this.$store.getters.fullInfo
Actions
由于直接在mutation方法中进行异步操作,将会引起数据失效。所以提供了Actions来专门进行异步操作,最终提交mutation方法。
Actions中的方法有两个默认参数
context 上下文(相当于箭头函数中的this)对象
payload 挂载参数
由于setTimeout是异步操作,所以需要使用actions
实例:
actions:{
aEdit(context,payload){
setTimeout(()=>{
context.commit('edit',payload)
},2000)
}
}
在组件中调用:
this.$store.dispatch('aEdit',{age:15})
(改进)
由于是异步操作,所以我们可以为我们的异步操作封装为一个Promise对象
aEdit(context,payload){
return new Promise((resolve,reject)=>{
setTimeout(()=>{
context.commit('edit',payload)
resolve()
},2000)
})
}
Models
Vuex 允许我们将 store 分割成模块(module)。每个模块拥有自己的 state、mutation、action、getter、甚至是嵌套子模块——从上至下进行同样方式的分割。
实例:
models:{
a:{
state:{},
getters:{},
....
}
}
组件内调用模块a的状态:
this.$store.state.a
而提交或者dispatch某个方法和以前一样,会自动执行所有模块内的对应type的方法:
this.$store.commit('editKey')
this.$store.dispatch('aEditKey')