- State
- Getters
- Mutation
- Action
- Module
①State单一状态树(单一数据源)
(1)如果状态信息是保存到多个Store对象中,那么之后的管理和维护等等都会变得特别困难
(2)所以Vuex使用了单一状态树来管理应用层级的全部状态
(3)单一状态树能够以最直接的方式找到某个状态的片段,而且在之后的维护和调试过程中,也可以非常方便的管理和维护。
② Getters 基本使用(类似于组件中的计算属性)
store \index:
import Vue from 'vue'
import Vuex from 'vuex'
// 1. 安装插件
Vue.use(Vuex)
// 2. 创建对象
const store = new Vuex.Store({
state: {
counter: 1000,
students: [
{ id: 110, name: 'tom', age: 18 },
{ id: 111, name: 'bob', age: 23 },
{ id: 112, name: 'helon', age: 24 },
{ id: 113, name: 'jack', age: 15 }
]
},
mutations: {
// 方法
increment (state) {
state.counter++
},
decrement (state) {
state.counter--
}
},
actions: {
},
modules: {
},
getters: {
// 返回counter的平方 计算属性
powerCounter (state) {
return state.counter * state.counter
},
more20stu (state) {
// 获取年龄大于 20 岁的学生
return state.students.filter(s => s.age > 20)
},
// 第二个参数传入的就是一个getters
more20stuLen (state, getters) {
return getters.more20stu.length
},
moreAgeStu (state) {
// return function (age) {
// return state.students.filter(s => s.age > age)
// }
return age => state.students.filter(s => s.age > age)
}
}
})
// 3. 导出 store 对象
export default store
App.vue 组件:
<template>
<div id="app">
<h2>------------app 内容------------</h2>
<h2>{{message}}</h2>
<h2>{{$store.state.counter}}</h2>
<button @click="addition">+</button>
<button @click="subtraction">-</button>
<h2>---------App内容: getters相关信息---------</h2>
<h2>{{ $store.getters.powerCounter }}</h2>
<h2>{{$store.getters.more20stu}}</h2>
<h2>{{$store.getters.more20stuLen}}</h2>
<h2>{{$store.getters.moreAgeStu(8)}}</h2>
<h2>-----------hello vuex 内容------------</h2>
<hello-vuex></hello-vuex>
</div>
</template>
<script>
import HelloVuex from './components/HelloVuex.vue'
export default {
name: 'App',
components: {
HelloVuex
},
data () {
return {
message: 'app组件'
}
},
methods: {
addition () {
this.$store.commit('increment')
},
subtraction () {
this.$store.commit('decrement')
}
}
}
</script>
<style lang="less">
</style>
HelloVuex.vue:
<template>
<div>
<h2>{{$store.getters.powerCounter}}</h2>
<h2>{{$store.getters.more20stu}}</h2>
</div>
</template>
<script>
export default {
name: 'HelloVuex',
props: {
counter: Number
}
}
</script>
<style scoped>
</style>
③Mutations状态更新
●Vuex的store状态的更新唯一方式:提交Mutation
●Mutation主要包括两部分:
▲ 字符串的事件类型(type)
▲ 一个回调函数(handler),该回调函数的第一个参数就是state
● mutation的定义方式:
mutations: {
increment() {
state.count++
}
}
● 通过mutation更新
addition () {
this.$store.commit('increment')
}
vuex-mutations传参数
①vuex-mutations携带参数
App组件
<template>
<div id="app">
<h2>------------app 内容 mutations------------</h2>
<h2>{{message}}</h2>
<h2>{{$store.state.counter}}</h2>
<button @click="addition">+</button>
<button @click="subtraction">-</button>
<button @click="addCount(5)">+5</button>
<button @click="addCount(10)">+10</button>
<button @click="addStudent">添加学生</button>
<h2>---------App内容: getters相关信息---------</h2>
<h2>{{ $store.getters.powerCounter }}</h2>
<h2>{{$store.getters.more20stu}}</h2>
<h2>{{$store.getters.more20stuLen}}</h2>
<h2>{{$store.getters.moreAgeStu(8)}}</h2>
<h2>-----------hello vuex 内容------------</h2>
<hello-vuex></hello-vuex>
</div>
</template>
<script>
import HelloVuex from './components/HelloVuex.vue'
export default {
name: 'App',
components: {
HelloVuex
},
data () {
return {
message: 'app组件'
}
},
methods: {
addition () {
this.$store.commit('increment')
},
subtraction () {
this.$store.commit('decrement')
},
addCount (count) {
// 参数被称为是mutation的 载荷payload: 负载
this.$store.commit('incrementCount', count)
},
addStudent () {
const stu = { id: 114, name: 'baicai', age: 18 }
return this.$store.commit('addStudent', stu)
}
}
}
</script>
<style lang="less">
</style>
import Vue from 'vue'
import Vuex from 'vuex'
// 1. 安装插件
Vue.use(Vuex)
// 2. 创建对象
const store = new Vuex.Store({
state: {
counter: 1000,
students: [
{ id: 110, name: 'tom', age: 18 },
{ id: 111, name: 'bob', age: 23 },
{ id: 112, name: 'helon', age: 24 },
{ id: 113, name: 'jack', age: 15 }
]
},
mutations: {
// 方法
increment (state) {
state.counter++
},
decrement (state) {
state.counter--
},
incrementCount (state, count) {
state.counter += count
},
addStudent (state, stu) {
state.students.push(stu)
}
},
actions: {
},
modules: {
},
getters: {
powerCounter (state) {
return state.counter * state.counter
},
more20stu (state) {
return state.students.filter(s => s.age >= 20)
},
more20stuLen (state, getters) {
return getters.more20stu.length
},
moreAgeStu (state) {
// return function (age) {
// return state.students.filter(s => s.age > age)
// }
return age => state.students.filter(s => s.age > age)
}
}
})
// 3. 导出 store 对象
export default store
mutations的提交风格
除了普通的提交方式Vue还提供了另外一种风格,它是一个包含type属性的对象
this.$store.commit({
type: 'changeCount',
count: 100
})
Mutation中的处理方式是将整个commit的对象作为payload使用,所以代码没有改变
changeCount(state, payload) {
state.count = payload.count
}
Mutation响应规则
Vuex的store中的state是响应式的,当state中的数据发生改变时,Vue组件会自动更新
当给state中的对象添加新属性时,使用下面的方式:
方式一: 使用Vue.set(obj, ‘newProp’, 123)
方式二: 用新对象给就对象重新赋值
响应式方法: 可以做到响应式
import Vue from 'vue'
import Vuex from 'vuex'
// 1. 安装插件
Vue.use(Vuex)
// 2. 创建对象
const store = new Vuex.Store({
state: {
counter: 1000,
students: [
{ id: 110, name: 'tom', age: 18 },
{ id: 111, name: 'bob', age: 23 },
{ id: 112, name: 'helon', age: 24 },
{ id: 113, name: 'jack', age: 15 }
],
info: {
name: 'kobe',
age: 40,
height: 1.98
}
},
mutations: {
// 方法
increment (state) {
state.counter++
},
decrement (state) {
state.counter--
},
incrementCount (state, payload) {
console.log(payload)
state.counter += payload.count
},
addStudent (state, stu) {
state.students.push(stu)
},
changeName (state) {
// state.info.name = 'xiongmao'
// state.info.address = 'ooo' 这种方法并没有将address添加到响应式系统里面
// 该方法是将address 添加到响应式系统里面
// Vue.set(state.info, 'address', 'ooo')
// 该方式做不到响应式
// delete state.info.age
// 该方法可以做到响应式
Vue.delete(state.info, 'age')
}
},
actions: {
},
modules: {
},
getters: {
powerCounter (state) {
return state.counter * state.counter
},
more20stu (state) {
return state.students.filter(s => s.age >= 20)
},
more20stuLen (state, getters) {
return getters.more20stu.length
},
moreAgeStu (state) {
// return function (age) {
// return state.students.filter(s => s.age > age)
// }
return age => state.students.filter(s => s.age > age)
}
}
})
// 3. 导出 store 对象
export default store
Vuex-mutations类型常量
抽取常量
export const INCREMENT = 'increment'
引用常量
import { INCREMENT } from './mutations-type.js'
[INCREMENT] (state) {
state.info.name = 'coo'
}
commit() 函数 发送请求
import { INCREMENT } from './store/mutations-type.js'
increment() {
this.$store.commit(INCREMENT)
}
App.vue
<template>
<div id="app">
<h2>-------------App内容: info对象的内容是否是响应式的---------</h2>
<h2>{{ $store.state.info }}</h2>
<button @click="updateInfo">点击改变name内容</button>
<h2>------------app 内容 mutations------------</h2>
<h2>{{ message }}</h2>
<h2>{{ $store.state.counter }}</h2>
<button @click="addition">+</button>
<button @click="subtraction">-</button>
<button @click="addCount(5)">+5</button>
<button @click="addCount(10)">+10</button>
<button @click="addStudent">添加学生</button>
<h2>---------App内容: getters相关信息---------</h2>
<h2>{{ $store.getters.powerCounter }}</h2>
<h2>{{ $store.getters.more20stu }}</h2>
<h2>{{ $store.getters.more20stuLen }}</h2>
<h2>{{ $store.getters.moreAgeStu(8) }}</h2>
<h2>-----------hello vuex 内容------------</h2>
<hello-vuex></hello-vuex>
</div>
</template>
<script>
import HelloVuex from './components/HelloVuex.vue'
import { INCREMENT } from './store/mutations-types'
export default {
name: 'App',
components: {
HelloVuex
},
data () {
return {
message: 'app组件'
}
},
methods: {
addition () {
this.$store.commit(INCREMENT)
},
subtraction () {
this.$store.commit('decrement')
},
addCount (count) {
// 1.普通的提交封装
// this.$store.commit('incrementCount', count)
// 2. 特殊的提交封装
this.$store.commit({
// 事件类型
type: 'incrementCount',
count
})
},
addStudent () {
const stu = { id: 114, name: 'baicai', age: 18 }
return this.$store.commit('addStudent', stu)
},
updateInfo () {
return this.$store.commit('changeName')
}
}
}
</script>
<style lang="less">
</style>
mutations-type.js
export const INCREMENT = 'increment'
/store/index.js
import Vue from 'vue'
import Vuex from 'vuex'
import { INCREMENT } from './mutations-types.js'
// 1. 安装插件
Vue.use(Vuex)
// 2. 创建对象
const store = new Vuex.Store({
state: {
counter: 1000,
students: [
{ id: 110, name: 'tom', age: 18 },
{ id: 111, name: 'bob', age: 23 },
{ id: 112, name: 'helon', age: 24 },
{ id: 113, name: 'jack', age: 15 }
],
info: {
name: 'kobe',
age: 40,
height: 1.98
}
},
mutations: {
// 方法
[INCREMENT] (state) {
state.counter++
},
decrement (state) {
state.counter--
},
incrementCount (state, payload) {
console.log(payload)
state.counter += payload.count
},
addStudent (state, stu) {
state.students.push(stu)
},
changeName (state) {
// state.info.name = 'xiongmao'
// state.info.address = 'ooo' 这种方法并没有将address添加到响应式系统里面
// 该方法是将address 添加到响应式系统里面
// Vue.set(state.info, 'address', 'ooo')
// 该方式做不到响应式
// delete state.info.age
// 该方法可以做到响应式
Vue.delete(state.info, 'age')
}
},
actions: {
},
modules: {
},
getters: {
powerCounter (state) {
return state.counter * state.counter
},
more20stu (state) {
return state.students.filter(s => s.age >= 20)
},
more20stuLen (state, getters) {
return getters.more20stu.length
},
moreAgeStu (state) {
// return function (age) {
// return state.students.filter(s => s.age > age)
// }
return age => state.students.filter(s => s.age > age)
}
}
})
// 3. 导出 store 对象
export default store
注意: 尽量不要在mutations里面进行异步操作
④vuex-actions的使用
1.如果在mutations里面直接写异步程序,
例如
changeName() {
setTimeout(() => {
state.info.name = 'oookkk'
}, 1000)
}
那么vue调试工具将跟踪不到数据的变化state中记录的信息将会变成错误的信息,没有实时更新
注意: 尽量不要在mutations里面进行异步操作
如果有异步操作,vue组件通过dispatch("") Action要执行的函数,
然后Action函数里面要commit 提交mutations通过mutations修改state
App组件
updateInfo () {
return this.$store.dispatch('aUpdateInfo')
}
/store/index.js
actions: {
// context 上下文
aUpdateInfo (context) {
setTimeout(() => {
context.commit('changeName')
}, 1000)
}
}
mutations
mutations: {
// 方法
[INCREMENT] (state) {
state.counter++
},
decrement (state) {
state.counter--
},
incrementCount (state, payload) {
console.log(payload)
state.counter += payload.count
},
addStudent (state, stu) {
state.students.push(stu)
},
changeName (state) {
state.info.name = 'xiongmao'
// state.info.address = 'ooo' 这种方法并没有将address添加到响应式系统里面
// 该方法是将address 添加到响应式系统里面
// Vue.set(state.info, 'address', 'ooo')
// 该方式做不到响应式
// delete state.info.age
// 该方法可以做到响应式
// Vue.delete(state.info, 'age')
// setTimeout(() => {
// state.info.name = 'oookkk'
// }, 1000)
}
},
dispatch 传参问题
方法一
App.vue:
updateInfo() {
this.$store.dispatch('aUpdateInfo', {
message: '携带的信息',
success: () => {
console.log('success')
}
}
}
action
actions: {
// context 上下文
aUpdateInfo (context, payload) {
setTimeout(() => {
context.commit('changeName')
// 回调函数
payload()
}, 1000)
}
}
方法二:优雅写法
App.vue
updateInfo() {
this.$store.dispatch('aUpdateInfo', '传递的信息').then(res => {
console.log('里面完成了提交')
console.log(res)
})
}
action
aUpdateInfo (context, payload) {
return new Promise((resolve, reject) => {
setTimeout(() => {
context.commit('changeName')
console.log(payload)
resolve('resolve')
}, 1000)
})
}