Vuex的设计初衷就是为了解决Vue中单项数据流的问题,什么是单项数据流,简单来说就是
父组件可以传值给子组件,你可以用props,还相对简单.
子组件可以传值给父组件,你可以用$emit,这个算相对难一丢丢.
1.Vuex 的状态存储是响应式的。当 Vue 组件从 store 中读取状态的时候,若 store 中的状态发生变化,那么相应的组件也会相应地得到高效更新。
2.你不能直接改变 store 中的状态。改变 store 中的状态的唯一途径就是显式地提交 (commit) mutation。这样使得我们可以方便地跟踪每一个状态的变化,从而让我们能够实现一些工具帮助我们更好地了解我们的应用。
1. state
定义:state(vuex) ≈ data (vue)
作用:vuex的state和vue的data有很多相似之处,都是用于存储一些数据,或者说状态值。这些值都将被挂载数据和dom的双向绑定事件,也就是当你改变值的时候可以触发dom的更新。
虽然state和data有很多相似之处,但state在使用的时候一般被挂载到子组件的computed计算属性上。
javascript
//state.js
let state = {
count: 1,
name: 'dkr',
sex: '男',
from: 'china'
}
export default state
2. mapState 与 ...mapState 辅助函数
作用:当一个组件需要获取多个状态时候,将这些状态都声明为计算属性会有些重复和冗余。为了解决这个问题,我们可以使用辅助函数帮助我们减少代码
写在computed里面
3. getters
作用:Vuex 允许我们在 store 中定义"getter"(可以认为是 store 的计算属性)。就像计算属性一样,getter 的返回值会根据它的依赖被缓存起来,且只有当它的依赖值发生了改变才会被重新计算。
使用场景:getters可以让你从store的state中派生出一些新的状态,当然如果不是多个组件要用到这个状态,或者说每个子组件用到的派生属性不一样,那么你完全可以不用getters。
很多情况下你是用不到getters的,不要用getters去管理state的所有派生状态。如果有多个子组件或者说子页面要用到才考虑用getters。
javascript
// getters.js
// 第一个参数是state
let address = (state) => {
return '国籍:' + state.from
}
// 第二个参数可以访问getters
let addressMore = (state, getters) => {
return '其他描述' + getters.address
}
// return 一个function,这个function可以传参,当然这个function最后会返回一个具体的数值
//本例中这个方法用于查询state中的arr数组是否存在某个值
let findArr = (state) => (number) => {
let ifExit = state.arr.find((n) => n === number) // arr.find是ES6语法中数组的扩展
if (typeof (ifExit) === 'undefined') {
return false
} else {
return true
}
}
export {address, addressMore, findArr}
javascript
computed: {
from: function () {
return this.$store.getters.address
},
from2: function () {
return this.$store.getters.addressMore
}
},
created () {
console.log(this.$store.getters.findArr(2))
console.log(this.$store.getters.findArr(7))
}
4. mapGetters 与 ...mapGetters辅助函数
写在computed里面
javascript
computed: mapGetters({
'from': 'address',
'from2': 'addressMore',
'find': 'findArr'
}),
5. mutation
语法:this.$store.commit('xxxx')
作用:提供了mutation来追踪你对state的值的操作,更改 Vuex 的 store 中的状态的唯一方法是提交 mutation。类似于vue中的$emit事件
使用场景:用于管理同步事件,如果有异步操作请用action。
在mutation中的使用两个异步事件都改变了count的值,无法知道什么时候回调和哪个先回调。
javascript
//mutation.js
// 第一个参数默认接收state对象
const increment = (state) => {
state.count++
}
const decrement = (state) => {
state.count--
}
//第二个参数接收'载荷'
const add = (state, n) => {
state.count += n
}
const fn = (state, json) => {
state.name = json.first + json.second + state.name
}
export {increment, decrement, add, fn}
6. mapMutations 与 ...mapMutations辅助函数
写在methods里面
javascript
// 辅助函数写法
methods: {
...mapMutations({
decrement: 'decrement',
increment: 'increment', // 将 `this.increment()` 映射为 `this.$store.commit('increment')`
add: 'add',
changeName: 'fn' // 将 `this.changeName(json)` 映射为 `this.$store.commit('fn', json)`
})
}
7. action
语法:this.$store.dispatch('xxxx')
作用:Action 类似于 mutation,不同在于:
1.Action 提交的是 mutation,而不是直接变更状态。
2.Action 可以包含任意异步操作。
javascript
// Action 函数接受一个与 store 实例具有相同方法和属性的 context 对象
let incrementAsync = (content) => {
return new Promise((resolve, reject) => {
setTimeout(() => {
content.commit('increment')
resolve()
}, 1000)
})
}
let decrementAsync = (content) => {
return new Promise((resolve, reject) => {
setTimeout(() => {
content.commit('decrement')
resolve()
}, 1000)
})
}
export {incrementAsync, decrementAsync}
8. mapActions 与 ...mapActions辅助函数
写在methods里面
javascript
methods: {
...mapMutations(['increment', 'decrement']),
...mapActions(['incrementAsync', 'decrementAsync']),
add () {
this.incrementAsync().then(() => {
this.increment()
})
},
dec () {
this.decrementAsync().then(() => {
// do something
})
}
}