Vuex几个核心概念
- State (单一状态树)
- Getters (和计算属性差不多)
- Mutations (同步方法)
- Actions (异步方法)
- Modules (模块)
state
修改state里面的属性的话必须要通过mutations来修改
state≈data
用来存放数据的
mutations
官方解释:更改 Vuex 的 store 中的状态的唯一方法是提交 mutation。Vuex 中的 mutation 非常类似于事件:每个 mutation 都有一个字符串的 事件类型 (type) 和 一个 回调函数 (handler)。这个回调函数就是我们实际进行状态更改的地方,并且它会接受 state 作为第一个参数:
// index.js
const store = new Vuex.Store({
state: {
counter: 100
},
mutations: {
increment(state) {
state.counter++
},
decrement(state) {
state.counter--
}
}
})
这样就能直接拿到increment属性并且执行它
// .vue
methods: {
jia() {
// 通过this.$store.commit()发送mutations里面的属性
this.$store.commit('increment')
},
jian() {
this.$store.commit('decrement')
}
}
-
将store对象放在new Vue对象中,用来保存多个组件共享的状态
-
在其他的组件中使用store对象中保存的状态
- 使用this.$store.state属性的方式来进行访问
- 使用this.$store.commit(‘mutations里面的方法’)来进行修改
-
这里通过的是提交mutations的方式,而不是直接改变store.state.count
-
使用$store.commit(’’)是因为Vuex可以追踪到stat状态的变化,所以最好不要直接就使用store.state.count来进行改变count的值,这种直接修改的值Vuex是追踪不到的
mutations传参用法(两种方法)
// index.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
const store = new Vuex.Store({
state: {
list: [
{
name: 'aaa',
age: 12,
sex: true
},
{
name: 'bbb',
age: 18,
sex: false
},
{
name: 'ccc',
age: 13,
sex: true
},
{
name: 'ddd',
age: 16,
sex: false
}
]
},
mutations: {
// 第一个参数state就是store里面的state
// 第二个参数all是用来接受this.$store.commit('addList', obj)发送过来的信息的
// 普通方式接受参数
// addList(state, all) {
// state.list.push(all)
// }
// 用payload接受传过来的对象
addList(state, payload) {
state.list.push(payload.obj)
}
}
})
export default store
<template>
<div>
<button @click="addL">点击添加信息</button>
<div> {{ $store.state.list }} </div>
<hr>
</div>
</template>
<script>
export default {
name: 'counter',
methods: {
addL() {
const obj = {id: 1, name: '测111', age: 999}
// this.$store.commit('addList', obj) 普通传参方式
// 把obj发送给index.js中mutations里面定义的addList方法
// 用对象方式传参
// 你可以向 store.commit 传入额外的参数,即 mutation 的 载荷(payload)
this.$store.commit({
type: 'addList',
obj: obj
})
}
}
}
</script>
<style>
</style>
当点击添加信息的时候就会添加一个对象到数组里面
getters
官方解释:Vuex 允许我们在 store 中定义“getter”(可以认为是 store 的计算属性)。就像计算属性一样,getter 的返回值会根据它的依赖被缓存起来,且只有当它的依赖值发生了改变才会被重新计算。
getters和computed计算属性差不多
// index.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
const store = new Vuex.Store({
state: {
list: [
{
name: 'aaa',
age: 12,
sex: true
},
{
name: 'bbb',
age: 18,
sex: false
},
{
name: 'ccc',
age: 13,
sex: true
},
{
name: 'ddd',
age: 16,
sex: false
}
]
},
getters: {
// 第一个参数state就是store 里面的state
abc(state) {
return state.list.filter(a => a.sex) // filter参数a就是list里面的对象,这里是只要sex是真就返回
},
// 第二个参数就是它本身
def(state, geeters) {
return geeters.abc.length
},
// 传参的方式
ret(state) {
return (userage) => {
return state.list.filter(a => a.age > userage)
}
}
}
})
export default store
Getter 会暴露为 store.getters 对象,你可以以属性的形式访问这些值:
<!--counter.vue-->
<template>
<div>
<h2>对象:-------{{ $store.getters.abc }}</h2>
<h2>长度:{{ $store.getters.def }}</h2>
<h2>传参:{{ $store.getters.ret(17) }}</h2>
</div>
</template>
<script>
export default {
name: 'counter'
}
</script>
<style>
</style>
actions
异步操作处理在action里面做,action类似于mutation,但action是来代替mutation进行异步操作的
官方解释: Action 函数接受一个与 store 实例具有相同方法和属性的 context 对象,因此你可以调用 context.commit 提交一个 mutation,或者通过 context.state 和 context.getters 来获取 state 和 getters。
actions里面定义方法的参数不是state,而是context(上下文)
可以把context理解成state
// index.js
state: {
info: {
name: 'qqq'
}
},
mutations: {
abc(state) {
state.info.name = 'ccc'
}
},
actions: {
aAbc(context, payload) {
return new Promise((resolve, reject) => {
setTimeout(() => {
context.commit('abc') // 把mutations里面的abc发射出去
console.log(payload) // 这里打印的是App.vue里面传过来的第二个参数
resolve('我已经完成了操作') // 完成之后调用resolve
}, 1000)
})
}
},
<!--App.vue-->
<template>
<div id="app">
<button @click="btnCli">dsad</button>
<h2>{{ $store.state.info }}</h2>
</div>
</template>
<script>
export default {
name: 'App',
methods: {
btnCli() {
// 通过同步修改修用commit
// this.$store.commit('abc')
// 通过异步修改用dispatch
this.$store
.dispatch('aAbc', '我是payload传参')
.then(res => {
console.log('我已经完成了提交')
console.log(res) // resolve()在这里打印
})
}
}
}
</script>
<style>
</style>
return new Promise(){} 整体返回给aAbc,.dispatch(‘aAbc’, ‘我是payload传参’)调用了aAbc,那么他就是Promise,所以在这里就可以直接调用.then方法
modules
官方解释:由于使用单一状态树,应用的所有状态会集中到一个比较大的对象。当应用变得非常复杂时,store 对象就有可能变得相当臃肿。
为了解决以上问题,Vuex 允许我们将 store 分割成模块(module)。每个模块拥有自己的 state、mutation、action、getter、甚至是嵌套子模块——从上至下进行同样方式的分割:
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
const moduleA = {
state: {
demo: '测试1'
},
mutations: {},
getters: {},
actions: {}
}
const store = new Vuex.Store({
state: {},
mutations: {},
getters: {},
actions: {},
modules: {
a: moduleA
}
})
export default store
上面的moduleA对象 给了store里面modules里面的a,那么这个a就会到store里面的state里面,所以想要拿到moduleA 里面的demo属性,就直接
$store.state.a
在里面使用mutations也和之前一样
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
const moduleA = {
state: {
demo: '测试1'
},
mutations: {
edit(state, payload) {
state.demo = payload
}
}
}
const store = new Vuex.Store({
modules: {
a: moduleA
}
})
export default store
<template>
<div id="app">
<button @click="btnCli">点击修改</button>
<h2>{{ $store.state.a }}</h2>
</div>
</template>
<script>
export default {
name: 'App',
methods: {
btnCli() {
this.$store.commit('edit', '测试2')
}
}
}
</script>
<style>
</style>
modules里面的getters有第三个参数,第三个参数可以获取到(rootState)根
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
const moduleA = {
state: {
demo: '测试1'
},
getters: {
name1(state) {
return state.demo + '111'
},
name2(state, getters) {
return getters.name1 + '222'
},
// 第三个参数就是最下面的state
name3(state, getters, rootState) {
return getters.name2 + rootState.count
}
}
}
const store = new Vuex.Store({
state: {
count: 666
},
modules: {
a: moduleA
}
})
export default store
<h2>{{ $store.getters.name1 }}</h2> <!--测试1111-->
<h2>{{ $store.getters.name2 }}</h2> <!--测试1111222-->
<h2>{{ $store.getters.name3 }}</h2> <!--测试1111222666-->