Vuex简介
- 是一个专为vue.js开发的状态管理模式
- 它采用集中式存储管理应用的所有组件的状态,并以对应的规则保证状态以一种可预测的方式发生变化
- Vuex也继承到Vue的官方调试工具devtools extension,提供了诸如零配置的time-travel调试,状态快照导入导出等高级调试功能
什么是状态管理?
- 你可以简单的将其看成需要多个组件共享的变量全部存储在一个对象里面
- 然后,将这个对象放在顶层的Vue实例中,让其他组件可以使用
- 那么,多个组件是不是就可以共享这个对象中的所有变量属性了呢?
为什么官方还要专门出一个Vuex插件呢,难道我们不能自己封装一个对象进行管理吗?
- 当然可以,只是我们要先想想VueJs带给我们的最大便利是什么?没错,就是响应式!
- 如果你自己封装实现一个对象能不能保证他里面所有的属性做到响应式呢?当然可以,自己封装的比较麻烦
- 不用怀疑,Vuex及时为了提供这样一个多个组件间共享状态的插件,用它就可以了
管理什么对象呢?
- 比如一些大型项目,涉及多个界面共享问题
- 用户的登录状态,用户名称,头像,地理位置信息等等
- 比如商品的收藏,购物车中的物品等等
- 这些状态信息,我们都可以放在统一的地方,对他进行保存和管理,而且是响应式的,类似于服务器后端
session
Vuex state
- state : 状态,姑且当做data中的属性
- view: 视图层,可以针对state的变化,显示不同的信息
- actions:主要是用户的各种操作:点击输入等,会导致状态的改变
1.安装vuex
cnpm install vuex --save
2.创建store文件夹下面的index.js文件
import Vuex from 'vuex'
import Vue from 'vue'
//1.安装插件, 执行vuex.install方法
Vue.use(Vuex) //Vuex not vuex
//2.创建vuex 对象(store)
const store = new Vuex.Store({
state:{
counter: 1000
},
mutations:{},
actions:{},
getters: {},
modules: {}
})
//3.导出store对象
export default store
3.挂在到vue组件上,main.js
import Vue from 'vue'
import App from './App'
import router from './router'
import store from "./store";
Vue.config.productionTip = false
/* eslint-disable no-new */
new Vue({
el: '#app',
router,
store, //Vue.prototype.$store = store 注册
render: h => h(App)
})
然后就可以使用了
<h2>{{$store.state.counter}}</h2>
$store
是挂载在 Vue 实例上的(即Vue.prototype),而组件也其实是一个Vue实例,在组件中可使用 this 访问原型上的属性,template 拥有组件实例的上下文,
可直接通过{{ $store.state.userName }}
访问,等价于 script 中的 this.$store.state.userName
vue component: --> 通过 actions --> mutation 修改state中的数据
devtools: 跟踪修改状态
mutations
然后这样调用
this.$store.commit('increment')
this.$store.commit('decrement')
Mutations 状态信息
- vuex的store状态的更新唯一方式: 提交Mutation
- Mutation主要包括两部分:
- 字符串的事件类型(type)
- 一个回调函数(handler), 该回调函数的第一个参数就是state
- Mutation的定义方式: 在store中的mutation定义函数即可
- 调用方式:
this.$store.commit('increment')
Mutations 携带参数
这个参数叫 payload
: 负载
如果参数过多playload可以传递一个 对象
组件内调用此方法即可
<button @click="incrementByCount(5)">+5</button>
incrementByCount(count){
this.$store.commit('incrementByCount',count)
}
Mutation提交风格
- 普通提交方式 commit
- vue还提供了另外一种风格,他是一个包含type属性的对象
Mutation 响应规则
- Vuex的store中的
state
是响应式
的,当state中的数据发生改变时,Vue组件会自动更新 - 这就要求我们必须遵守一些Vuex对应的规则:
- 提前在store中初始化好所需的属性,后加的属性不会添加至响应式系统中
- 当给state中的对象添加新属性时,使用下面的方式可以实现响应式
- 方式一:
使用Vue.set(obj,'newProp',123)
- 方式二: 用新对象给旧对象重新赋值
- 方式一:
这样做,虽然给info添加了属性,但是界面没刷新,不是响应式的
state.info['address'] = '洛杉矶'
可以这样做,成为响应式的
Vue.set(state.info,'address','洛杉矶']
还有另外一种方法
//该方式做不到响应式的
delete state.info.age
//这个样子才可以
Vue.delete(state.info,'age')
Mutation 的类型常量
在需要使用的地方引入
Vuex 核心概念
- state
- getters 类似于组件的计算属性
- mutations 修改state中的数据,类似于组件中的methods
- actions 专门用于异步操作,不在mutations中做
- modules 划分模块
State单一状态树(single source of truth)
- 我们很多信息需要被记录,不如个人档案,社保记录,公积金记录等
- 这些信息被分散到很多地方进行管理,有一天你需要办某个业务时,你会发现你需要到各个对应的工作地点去打印、盖章各种资料信息,最后到一个地方提交证明你的信息无误
- 这种保存信息的方案,不仅仅低效、而且不便于管理,以后的维护也是一个庞大的工作
这个和我们的开发类似:
- 如果你的状态信息是保存到多个store对象中的,那么之后的管理和维护等等都会变得非常困难
- 所以vuex也使用了单一状态树来管理应用层级的全部状态
- 单一状态树能够让我们最直接的方式找到某个状态的片段,而且在之后的维护和调试过程中,也可以非常方便的维护和管理。
Getters 类似于计算属性
什么时候使用计算属性?
当某个数据必须经过一系列变换之后再显示,而不是直接显示,这个时候需要使用计算属性。Getters也类似
getters: {
pow(state){
return state.counter*state.counter;
}
},
<h2>{{$store.getters.pow}}</h2>
获取年龄>20的学生对象
computed: {
more20stu(){
return this.$store.state.students.filter(s => s.age > 20)
}
},
如果多个地方使用到more20stu,可以将该方法定义到store中的Getters里面
getters: {
pow(state){
return state.counter*state.counter;
},
more20stu(state){
return state.students.filter(s=> s.age>20)
}
},
查询more20stu的个数,定义Getters
当然你可以这样写
more20stu(state){
return state.students.filter(s=> s.age>20)
},
more20stuLength(state){
return state.students.filter(s=> s.age>20).length
}
可以这样写
more20stu(state){
return state.students.filter(s=> s.age>20)
},
more20stuLength(state,getters){
return getters.more20stu.length
}
如果Getters想要传递参数,可以这样写:
Getters moreAgeStu返回一个函数,$store.getters.moreAgeStu
代表一个函数,不代表一个变量,
所以$store.getters.moreAgeStu
加上参数,返回值才代表一个变量
moreAgeStu(state){
return function (age) {
return state.students.filter(s=>s.age > age)
}
}
<p>{{$store.getters.moreAgeStu(1)}}</p>
简写方式
moreAgeStu(state){
return age => {return state.students.filter(s=> s.age > age)}
}