写在前面
1、Vuex官方说法:一个专为 Vue.js 应用程序开发的状态管理模式。采用集中式存储管理应用的所有组件的状态。说白点就是在一个地方管理所有组件的数据。
2、Vue的思路:当改变数据时,页面会跟着变化,但是用户操作页面时,不会自动改变数据。所以Vuex是Vue用来单向绑定数据的。
3、为什么又要单向绑定数据:为了「控制欲」,双向绑定意味着你不知道 data 什么时候就变了(when),也不知道是谁变的(who),变成了什么也不通知你(what)。当然你可以加一个 watch 来监听 data 的变化。但这就显得很复杂了。单向绑定牺牲一部分的便捷性,换来更大的「控制力」。
1、安装
安装Vuex1
npm install vuex --save
2、创建index.js
1 | //src/store/index.js |
3、将index引入到App.vue中
1 | //App.vue |
4、子组件拿到数据
虽然子组件可以用this.$store.state.count拿到数据,但是太麻烦了,所以可以放到子组件的计算属性里去1
2
3
4
5
6computed: {
count () {
return this.$store.state.count
}
},
//引用的时候就可以直接{{count}}
5、子组件如何修改this.$store.state的数据
更改 Vuex 的 store 中的状态的唯一方法是提交 mutation,通过计算属性的set来提交mutation1
2
3
4
5
6
7
8
9
10
11computed: {
count () {
get(){
return this.$store.state.count
},
set(value){
return this.$store.commit('increment', value)
//第一个参数为mutation里的属性,value为传入额外的参数,即载荷
}
}
},
6、Vuex为单向绑定,所以要解决用户操作修改数据
通过给元素添加事件监听,触发计算属性中的set来提交mutation1
<input type="text" :value="value" @input="count = $event.target.value">
7、Vuex其他核心概念(上面说了2个:State,Mutation)
1、Getter
有时候需要从 store 中的 state 中派生出一些状态,比如对state里的数据再进行一次筛选,就会用到Getter,它可以认为是 store 的计算属性,写在index.js里面1
2
3
4
5
6
7
8
9
10
11
12
13
14
15//src/store/index.js
export default new Vuex.Store({
state: {
todos: [
{ id: 1, text: '...', done: true },
{ id: 2, text: '...', done: false }
]
},
getters: {
doneTodos: (state,value)=> { //可接受2个参数
return state.todos.filter(todo => todo.done)
},
}
})
//子组件调用store.getters.doneTodos -> [{ id: 1, text: '...', done: true }]
2、Action
Action 类似于 mutation,Action 提交的是 mutation,而不是直接变更状态。而且可以包含任意异步操作。乍一眼看上去感觉多此一举,我们直接分发 mutation 岂不更方便。其实mutation必须同步执行,所以需要Action的存在1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17//src/store/index.js
export default new Vuex.Store({
state: {
count: 0
},
mutations: {
increment (state) {
state.count++
}
},
actions: {
increment (context) {
context.commit('increment')
}
}
})
//Action 函数接受一个与 store 实例具有相同方法和属性的 context 对象,因此你可以调用 context.commit 提交一个 mutation,或者通过 context.state 和 context.getters 来获取 state 和 getters。
3、Module
将store的所有东西放在一个花括号,为了防止太累赘了,Vuex 允许我们将 store 分割成模块(没用过,改天试试)1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20const moduleA = {
state: { ... },
mutations: { ... },
actions: { ... },
getters: { ... }
}
const moduleB = {
state: { ... },
mutations: { ... },
actions: { ... }
}
export default new Vuex.Store({
modules: {
a: moduleA,
b: moduleB
}
})
//store.state.a // -> moduleA 的状态
//store.state.b // -> moduleB 的状态