vuex
概念:
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。简单来说,对vue应用中,多个组件的共享状态在组件外部进行集中式的管理
一般存在多个组件共享状态的情况为:多个组件依赖于同一个状态或者来自于不同组件的行为需要变更同一个状态
遇到这种情况,以前的解决方法:
(1)将数据以及操作数据的行为定义在父组件
(2)将数据以及操作数据的行为传递给需要的各个子组件(有可能需要多级传递)
对于简单的应用,这种方法可以实现,但是,如果需要构建一个中大型单页应用,在组件外部集中管理状态,会是更好的选择,Vuex 就是这样的一个存在。
使用:
安装Vuex:
npm install vuex --save
基本概念:
(1)定义store对象 :new Vuex.Store({//配置项})
new Vuex.Store({
state,
mutations,
actions,
getters
})
store对象有四个常用的配置项,state、mutations、actions、getters
①State:
vuex管理的状态对象;
应该是唯一的
const state = {
xxx:initValue
}
②mutations:
包含多个直接更新state的方法(回调函数)的对象;
可以在action中由 commit('mutation名称');//yyy来触发;也可以在页面中
只能包含同步的代码,不能写异步代码
const mutations = { yyy(state,data){ //更新state的某个属性 }, ... }
③actions:
包含多个事件回调函数的对象;
通过执行 commit()方法来触发mutation的回调,间接更新state;
由组件中 $store.dispatch('action名称');//zzz来触发
通常把异步代码(定时器,ajax)放在里边
const actions = { zzz ({commit,state},data1){ commit('yyy',data2) }, ... }
④getters:
和 vue 中的 computed
类似 ,用来计算 state 然后生成新的数据 ( 状态 ) 的
const getters = { kkk(state){ //根据state.xxx来得到ccc
return ccc; } }
当在组件中使用时,
computed:{ evenOrOdd(){ return this.$store.getters.kkk; } }
(2)组件中常用的store对象的属性和方法
在入口文件main.js中引入并映射store后,所有用vuex管理的组件中都多了一个属性$store ,它就是一个store对象
//映射store import store from './store' new Vue({ store })
组件中$store对象常用的属性有:
- state:注册的state对象
- getters:注册的getters对象
常用的方法:
- dispatch(actionName,data):触发store中的action,data是传递的参数,如果需要的话
示例:
(1)在src下新建store.js,作为vuex的核心模块:
store.js
/* vuex 的核心管理对象模块 */ import Vue from 'vue' import Vuex from 'vuex' //声明使用vuex Vue.use(Vuex) //状态对象 const state = { //初始化状态 count:0 } //包含多个更新state函数的对象 const mutations = { //一个函数相当于一个mutation //增加的mutation Increment(state){ state.count++ }, //减少的mutation Decrement(state){ state.count--; } } //包含多个对应事件回调函数的对象 const actions = { //一个回调函数就相当于一个action,action通过commit来触发mutation increment({commit}){ //提交给mutations,致使相应的mutation调用 commit('Increment'); }, decrement({commit}){ commit('Decrement'); }, //带条件的action incrementIfOdd({commit,state}){ if(state.count%2===1){ commit('Increment'); } }, //异步的action incrementAsync({commit}){ //在action中可以直接执行异步代码 setTimeout(()=>{ commit('Increment'); },1000) } } //包含多个getter计算属性函数的对象 const getters = { evenOrOdd(state){ return state.count%2===0? 'even':'odd'; } } //向外暴露store对象 export default new Vuex.Store({ //四个常用的配置 state,//状态对象 mutations,//包含多个更新state函数的对象 actions,//包含多个对应事件回调函数的对象 getters//包含多个getter计算属性函数的对象 })
(2)在入口文件main.js中引入store并映射到vue示例中
main.js
import Vue from 'vue' import App from './App' import store from './store' new Vue({//配置对象的属性名都是一些默认的属性名,不能随便修改 el:'#app', components:{ App }, template:'<App/>', store //这样配置之后 ,所有的组件对象都多了一个$store对象 })
(3)所有的组件中都多了一个$store属性,该属性的值是一个store对象
App.vue
<template> <div> <p>click {{$store.state.count}} times,count is {{evenOrOdd}}</p> <button @click="increment">+</button> <button @click="decrement">-</button> <button @click="incrementIfOdd">increment if odd</button> <button @click="incrementAsync">increment async</button> </div> </template> <script> export default{ computed:{ evenOrOdd(){ return this.$store.getters.evenOrOdd; } }, methods:{ increment(){ //通知vuex去增加 this代表的是组件对象,在template中不需要写this,在js中需要写上 this.$store.dispatch('increment') //触发store中对应的action }, decrement(){ this.$store.dispatch('decrement') }, incrementIfOdd(){ this.$store.dispatch('incrementIfOdd') }, incrementAsync(){ this.$store.dispatch('incrementAsync') } } } </script> <style> </style>
效果图:
总结,vuex的结构图:
组件对状态的操作,分为三种形式,
(1)直接读取(直接获取状态中的值展示出来,黑线部分);
(2)计算属性(通过状态来计算出所需属性值,绿线部分);
(3)更新状态(需要对状态进行变更,红线部分);