目录
1. vue组件间通讯
1.1 父子组件
1.2 消息总线
1.3 vuex
2. vuex使用
2.1 简介
2.2 安装
2.3 创建store模块
2.4 创建vuex的store实例并注册上面引入的各大模块
2.5 在main.js中导入vuex
3. 将折叠和展开效果使用vuex实现
3.1 在state.js中声明全局参数
3.2 设置全局参数
3.3 Main.vue组件
3.3.1 直接通过state获取状态值
3.3.2 getter方式获取store中的值
3.4 LeftAside.vue组件
4. 异步处理
4.1 异步修改参数
5. 异步调用后台方法
5.1 准备后台方法
5.2 配置api/actions.js
5.3 store/actions.js
5.4 Home.vue
6. Vuex的常用辅助函数
7. vuex的模块化
8. vuex状态持久化
这种方式需要另外创建一个vue实例,用来当做消息总线。见vuepro02-bus示例。
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。可以想象为一个“前端数据库”(数据仓库), 让其在各个页面上实现数据的共享包括状态,并且可操作。
Vuex分成五个部分:
1.State:单一状态树
2.Getters:状态获取
3.Mutations:触发同步事件
4.Actions:提交mutation,可以包含异步操作
5.Module:将vuex进行分模块
Vuex是专门为vue应用程序开发的状态管理模式,将组件的共享状态抽取出来,以一个全局单例模式进行管理,组件树构成一个巨大的视图,不管组件在树的何种位置,任何组件都能获取到状态和触发行为。可以将其想象为一个“前端数据库”(数据仓库),让其在各个页面上实现数据的共享包括状态,并且可操作。(核心就是 解决组件间的通讯问题)
Vuex分成五个部分:
1.State:单一状态树
2.Getters:状态获取
3.Mutations:触发同步事件
4.Actions:提交mutation,可以包含异步操作
5.Module:将vuex进行分模块
npm install vuex -S
main.js是vue应用程序的入口,在这个文件中导入vuex组件。
通过在根实例中注册store选项,该store实例会注入到根组件下的所有子组件中,且子组件可以通过this.$store访问到。
state.js的作用可以看作是存放全局参数的容器,组件可以通过state.js获取全局参数。
//存放全局参数的容器,组件可以通过state.js获取全局参数
const state = {
LeftAsideState: 'open'
}
export default state
当在TopNav.vue中点击展开或折叠时,需要将当前的状态设置到全局参数中,以便于其他组件可以获取到状态。
mutations:相当于setter方法,处理数据的唯一途径,state的改变或赋值只能在这里。
1) mutations.js
//Mutation 必须是同步函数。原因:异步方法,我们不知道什么时候状态会发生改变,所以也就无法追踪了
//如果我们需要异步操作,Mutations就不能满足我们需求了,这时候我们就需要Actions了
const mutations = {
//state,即state.js中定义的state,借此可以访问state中定义的全局变量
//payload: 载荷,保存传递参数的容器
setLeftAsideState: (state, payload) => {
//通过载荷为全局参数赋值,相当于setter
state.LeftAsideState = payload.LeftAsideState;
}
}
export default mutations
2)如何调用mutations.js中定义的setLeftAsideState为全局参数赋值? 见一下示例:
当点击TopNav.vue组件中的折叠或展开按键时,需要将当前的状态设置到全局参数中,以便于其他组件可以获取到状态。
TopNav.vue
//转换折叠图标的状态
doToggle: function() {
//如果原来为打开状态则点击后转换为折叠
//如果原来为折叠状态则点击后转换为打开
this.opened = !this.opened;
//通过自定义事件将状态值传递个父组件,及Main.vue
//相应的Main.vue组件中需要设置‘left-open-collapsed’
//使用vuex方式后,将原来的实现方式注释
//this.$emit("left-open-collapsed",this.opened);
/*
* 通过vuex进行组件间的通讯,当点击折叠或展开时设置全局参数,以便于
* 其他组件获取状态。
*
* 第一种提交方式:
* this.$store.commit(type, payload);
* 参数type: 与mutations.js定义的方法名一致
* 参数payload:载荷,是个json对象,其中的参数与state.js中定义的全局参数名一致
* 该方法的作用是为全局参数LeftAsideState赋值。
*
* 第二种提交方式:
* this.$store.commit({type: 'setLeftAsideState', LeftAsideState: 'open'});
* 即:将type参数与要设置的全局参数放在一个json对象中。
*/
this.$store.commit("setLeftAsideState", {
LeftAsideState : this.opened ? 'open' : 'collapsed'
});
}
Main.vue组件获取设置的全局变量(LeftAsideState)的值,并需要根据变量的值来改变自身的状态。
state中存放的状态值是响应式的,从store实例中读取状态最简单的方式是在计算属性中返回某个状态。
/*
* 通过计算属性读取store中的值,并根据获取到的值返回展开或折叠样式。
* 定义好计算属性后,通过绑定的方式使用
*
*/
computed: {
leftAsideClass: function() {
//可以通过以下的方式进行获取,但是不推荐。
let tmp = this.$store.state.LeftAsideState;
return tmp == 'open' ? "main-aside" : "main-aside-collapsed";
}
}
//getters将state中定义的值暴露在this.$store.getters对象中
//可以通过如下代码访问:this.$store.getters.getLeftAsideState
const getters = {
//参数state即为stroe中存放的state,在state.js定义
getLeftAsideState: function(state) {
return state.LeftAsideState;
}
}
export default getters
/*
* 通过计算属性读取store中的值,并根据获取到的值返回展开或折叠样式。
*/
computed: {
leftAsideClass: function() {
//可以通过以下的方式进行获取,但是不推荐。
//let tmp = this.$store.state.LeftAsideState;
//getters方式获取状态值
let tmp = this.$store.getters.getLeftAsideState;
return tmp == 'open' ? "main-aside" : "main-aside-collapsed";
}
}
computed: {
//通过计算属性获取定义在store中的状态值,并根据状态值来设定返回值,用于标记左侧栏展开或折叠的状态
//因为命名冲突,可将上面再data中定义的同名属性删除.
isCollapse: function() {
return this.$store.getters.getLeftAsideState == 'open' ? false : true;
}
}
同步
同步模式,即上述所说的单线程模式,一次只能执行一个任务,函数调用后需等到函数执行结束,返回执行的结果,才能进行下一个任务。如果这个任务执行的时间较长,就会导致「线程阻塞」
var x = true;
while(x);
console.log("don't carry out"); //不会执行
setTimeout(function(){
console.log("async task .... ");
}, 3000);
现做一个异步修改参数值的简单示例:
1) 在store中声明一个参数
//存放全局参数的容器,组件可以通过state.js获取全局参数
const state = {
LeftAsideState: 'open',
//声明一个存放人员名称的参数,设置默认值,用于演示异步修改参数
PersonName:'张飞'
}
export default state
2) 在mutations.js中定义修改参数的方法:
//Mutation 必须是同步函数。为什么呢?异步方法,我们不知道什么时候状态会发生改变,所以也就无法追踪了
//如果我们需要异步操作,Mutations就不能满足我们需求了,这时候我们就需要Actions了
const mutations = {
//state,即state.js中定义的state,借此可以访问state中定义的全局变量
//payload: 载荷,保存传递参数的容器
setLeftAsideState: (state, payload) => {
//通过载荷为全局参数赋值,相当于setter
state.LeftAsideState = payload.LeftAsideState;
},
//设置人员名称,用于演示异步
setPersonName: (state, payload) => {
state.PersonName = payload.PersonName;
}
}
export default mutations
//getters将state中定义的值暴露在this.$store.getters对象中
//可以通过如下代码访问:this.$store.getters.getLeftAsideState
const getters = {
//参数state即为stroe中存放的state,在state.js定义
getLeftAsideState: function(state) {
return state.LeftAsideState;
},
//定义获取人员名称的方法
getPersonName: function(state) {
return state.PersonName;
}
}
export default getters
/*
* Action与mutation定义语法类型,不同点:
* 1) Action提交的是mutation,而不是直接变更状态,mutation直接变更状态
* 2) Action可以包含任意异步操作
* 3) Action的回调函数接收一个 context 上下文参数
* 详见方法内的注释
*/
const actions = {
/*
* context为上下文参数,与 store 实例有着相同的方法和属性
* context参数包含:state、rootState、getters、mutations、actions 五个属性
* payload为负载,是一个存放需要传递的参数的容器,和mutations的含义一致
*/
setPersonNameAsyn: function(context, payload) {
//异步操作,第一个参数为一个匿名函数,第二参数为延迟的时间,单位为毫秒。
//作用:在3秒或调用第一个参数定义的匿名函数。
setTimeout(function() {
//action提交的是mutation,而不能直接变更状态
//第一个参数setPersonName即为mutation中定义的方法名
//payload即为参数容器。
//通过context的commit方法提交一个mutation,由mutation负责
//修改参数,action负责提供异步功能,(mutation必须是同步的)
context.commit('setPersonName', payload);
}, 3000);
}
}
export default actions
首页
{{personName}}
//VUEX 异步请求后台数据
'VUE_ASYN_REQ':'/userMsg/vueAsynAction!asynAction.action',
const actions = {
......
/*
* 在actions.js中无法直接获取vue实例的this对象,但需要该对象来获取axios
* 对象,以便于发送ajax请求,可以通过payload参数由调用者传入vue实例的this
* 对象。
*/
getDataFromApiAsyn: function(context, payload) {
let _this = payload._this;
let url = _this.axios.urls.VUE_ASYN_REQ;
_this.axios.post(url, {
param: payload.PersonName
}).then(resp => {
//通过resp响应对象获取返回的数据,并赋予payload
payload.PersonName = resp.data.data;
//提交一个mutation,用于设置state中的参数。
context.commit('setPersonName', payload);
}).catch(error => {
})
}
......
}
首页
{{personName}}
还可以使用如下方式获取模块中的值:this.$store.state.userMsg.userName; 但不建议使用。
Vuex 解决了多视图之间的数据共享问题。但是运用过程中又带来了一个新的问题是,Vuex 的状态存储并不能持久化。也就是说当你存储在 Vuex 中的 store 里的数据,只要一刷新页面,数据就丢失了。
引入vuex-persist 插件,它就是为 Vuex 持久化存储而生的一个插件。不需要你手动存取 storage ,而是直接将状态保存至 cookie 或者 localStorage 中。
npm install vuex-persist -S