出现原因
vuex出现之前,共享数据的难题:
1、书写特别繁琐
2、依赖极其混乱
3、无谓的重新渲染
vuex出现之后
专门解决共享数据问题,解决思路是把数据提升到最顶层,不过它使用了一些特殊的技巧,让组件的依赖更加清晰,当数据发生变化时,仅渲染依赖数据的组件
好处
- 集中管理(共享)数据,易于开发和维护
- 高效地实现组件之间的数据共享,提高开发效率
- 存储在vuex中的数据是响应式的,数据改变,使用到的地方会自动实时更新
基本使用
第一步:安装依赖包
npm i vuex --save
第二步:导入
import Vuex from 'vuex'
Vue.use(Vuex)
第三步:创建store对象
const store = new Vuex.store({
state: {count:0}
});
第四步:把store实例挂载到Vue根实例中,进行关联
new Vue({
el: "#app",
render: h => h(app),
store,
router
})
安装完成后,会在vue实例中添加一个共有属性:$store
原理就是通过 Vue.prototype.$store 添加
五大核心概念
State (状态仓库)
用于存储所有共享数据
组件使用时,要在 computed 声明
组件中访问state中共享数据的方式
1、第一种直接访问(不推荐)
// 非模块
this.$store.state.全局数据名称
// 模块
this.$store.state.模块名.全局数据名称
2、第二种使用辅助函数(推荐)
1、从 vuex 按需导入 mapState 辅助函数
import {mapState} from 'vuex'
2、将当前组件需要的全局数据,映射为当前组件的computed计算属性
// 非模块写法
computed: {
...mapState(['count'])
}
或者
computed: {
...mapState({
count: state => state.count, // 第一种
count: 'count' // 第二种
})
}
// 模块
computed: {
...mapState({
count: state => state.模块名.count
})
}
注意事项:
官方推荐我们将vuex的state属性绑定到computed,为何不可以绑定到data里面呢?
错觉:data中的内容只会在 created 钩子触发前初始化一次,之后需要通过js修改data里面的属性值,页面才响应式改变,那么把state里的数据绑定到data中,state中数据改变,data中对应的数据也会跟着改变不对吗?
回答:上面说法有一半对,一半错。到底错在哪呢?
错在:如果state里面的状态值类型是数值、布尔、字符串基础数据类型的话,那么赋值就是值传递,如下
let a = 12;
let b = a;
a = 20;
alert(a) //20
alert(b) //12
这样你明白了吧,如果把state中状态传递给data,那么当state中状态改变后,因为不是引用传递,data中对应属性值不会改变
总结:
data是在create钩子触发前初始化一次
data中由于没有依赖跟踪,所以必须引用传递才可以做到响应式
Getter (状态处理、包装)
用于对 state 中状态进行包装,不会对 state 中原数据有任何修改
类似于 computed 计算属性
state 中数据发生变化, getter 中数据也发生变化 响应式
组件使用时,要在 computed 声明
定义
// getter里面放的也是函数
state: {count:0},
getters: {
doneTodos: state => {
return '当前最新数量' + state.count + '个'
}
}
使用
// 第一种方式
this.$store.getters.名称
// 第二种方式
1、从 vuex 中按需导入 mapGetters 辅助函数
import {mapGetters} from vuex
2、将导入的 getter 函数,映射为当前组件的 computed 计算属性
computed: {
...mapGetters(['doneTodos'])
}
Mutation (修改状态)
vuex 不允许直接修改 state 中数据,必须使用 Mutation 来修改
Mutation 中定义的函数必须是同步函数,不能是异步的
定义函数
// 定义的函数接受2个参数:
1、state
2、传参
mutations: {
increment (state, params) {
// 变更状态
state.count++
}
}
组件中使用
// 第一种方式
this.$store.commit('increment', 12);
// 第二种方式 (当成方法使用,更加简单方便)
1、从 vuex 中按需导入 mapMutation 辅助函数
import {mapMutations} from vuex
2、将导入的 mutation 函数,映射为当前组件的methods函数
methods: {
...mapMutations(['increment'])
}
3、调用
this.increment(参数);
模块时,该如何使用呢?
// 第一种方式
this.$store.commit('base/increment', 12);
// 第二种方式
1、从 vuex 中按需导入 mapMutation 辅助函数
import {mapMutations} from vuex
2、将导入的 mutation 函数,映射为当前组件的methods函数
methods: {
...mapMutations(['base/increment']),
...mapMutations('base', ['increment'])
}
3、调用
this['base/increment'](4)
this.increment(13)
Action (异步操作)
与 Mutation 类似,唯一区别是:
mutation 是同步函数,唯一修改 state 状态值的方法
action 是异步函数,但不能修改 state 状态值
定义函数
// 定义的函数接受2个参数:
1、context
2、传参
actions: {
incrementAsync (context, params) {
setTimeout(() => {
context.commit('increment', params)
}, 1000)
}
}
组件中使用
// 第一种方式
this.$store.dispatch('incrementAsync', 12);
// 第二种方式 (当成方法使用,更加简单方便)
1、从 vuex 中按需导入 mapMutation 辅助函数
import { mapActions } from vuex
2、将导入的 action 函数,映射为当前组件的methods函数
methods: {
...mapActions(['incrementAsync'])
}
3、调用
this.incrementAsync(参数);
模块时,该如何使用呢?
// 第一种方式
this.$store.dispatch('base/incrementAsync', 12);
// 第二种方式
1、从 vuex 中按需导入 mapMutation 辅助函数
import {mapActions} from vuex
2、将导入的 action 函数,映射为当前组件的methods函数
methods: {
...mapActions(['base/incrementAsync']),
...mapActions('base', ['incrementAsync'])
}
3、调用
this['base/incrementAsync'](4)
this.incrementAsync(13)
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。