vuex 是什么
vuex 是vue集成的一个状态管理器,当多个组件都用到了同一个状态变量时,我们可以把那个状态变量交给vuex,这样,所有组件都可以直接从vuex 中获取对应的数据,免去了各个组件相互传参的繁琐过程,而且,vuex是响应式的,当里面的数据发生变化时,所有用到了这个数据的组件都会进行对应的更新
在父子组件中,状态传递通过父子组件传值即可,vuex主要用于各个兄弟组件或毫无关系的组件之间的状态管理。
安装与基本使用
使用 npm install vuex --save
安装
创建 store 文件夹,并建立index.js 文件 用于编写 vuex相关配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| import Vue from 'vue' import Vuex from 'vuex'
Vue.use(Vuex)
const store = new Vuex.Store({ state:{ isLogin:false }, mutations:{
}, actions:{
}, getters:{
}, modules:{
} })
export default store
|
- 在main.js 中导入,并挂载
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| import Vue from 'vue' import App from './App' import router from './router' import store from './store/index.js'
Vue.config.productionTip = false
new Vue({ el: '#app', router, store, components: { App }, template: '<App/>' })
|
- 在组件中使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| <template> <div id="wapper"> <h2>当前的登录状态是 {{$store.state.isLogin}}</h2> </div> </template>
<script> export default { data() { return { }; }, }; </script>
<style scoped > </style>
|
修改 vuex 中的状态
在配置文件中 配置 mutations 定义两个修改状态的方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| import Vue from 'vue' import Vuex from 'vuex'
Vue.use(Vuex)
const store = new Vuex.Store({ state:{ isLogin:false }, mutations:{ clearLoginState(state){ state.isLogin = false }, loginSuccess(state){ state.isLogin = true } }, actions:{
}, getters:{
}, modules:{
} })
export default store
|
在组件中 调用mutations 即可
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| <template> <div id="wapper"> <button @click="Sublogin">登录</button> <button @click="Cenllogin">取消</button> </div> </template>
<script> export default { data() { return { }; }, methods:{ Sublogin(){ //传入 mutations 中定义的方法 this.$store.commit('loginSuccess') }, Cenllogin(){ this.$store.commit('clearLoginState ') } } }; </script>
<style scoped > </style>
|
在实际开发中,有可能有很多个组件都会修改 vuex中的状态,这时我们就需要一个工具来追踪每一次的修改,以便修改 vuex后出现bug时,快速定位
- 下载安装 vue devtools 插件,注意把插件中的 允许访问文件网址 选项打开
在 vue程序界面 打开控制台 可以使用该插件进行调试
可以追踪每一次状态的修改
vuex 五个核心配置
state
state 就是vuex 存放状态的地方,是vuex的核心
getters
getters 类似于 计算属性,用于对state中的数据进行一些计算
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| import Vue from 'vue' import Vuex from 'vuex'
Vue.use(Vuex)
const store = new Vuex.Store({ state: { isLogin: false, time: new Date().getMonth(), }, mutations: { clearLoginState(state) { state.isLogin = false }, loginSuccess(state) { state.isLogin = true } }, actions: {
}, getters: { timeNow(state) { if(state.time+1<10) return '0' + (new Date().getMonth() + 1) else return state.time } }, modules: {
} })
export default store
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| <template> <div id="wapper"> <button @click="Sub">获取时间</button> </div> </template>
<script> export default { data() { return { }; }, methods:{ Sub(){ console.log(`现在是${this.$store.getters.timeNow}月`) } } }; </script>
<style scoped > </style>
|
此外,各个getters 还可以作为参数相互传参
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
| import Vue from 'vue' import Vuex from 'vuex'
Vue.use(Vuex)
const store = new Vuex.Store({ state: { isLogin: false, time: new Date().getMonth(), }, mutations: { clearLoginState(state) { state.isLogin = false }, loginSuccess(state) { state.isLogin = true } }, actions: {
}, getters: { timeMon(state) { if(state.time+1<10) return '0' + (new Date().getMonth() + 1)+'月' else return state.time+'月' }, timeYear(state,getters){ let year = new Date().getFullYear()+'年' return year+getters.timeMon } }, modules: {
} })
export default store
|
同时,getters 里面还可以封装一个函数,供组件使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| import Vue from 'vue' import Vuex from 'vuex'
Vue.use(Vuex)
const store = new Vuex.Store({ state: { year:new Date().getFullYear() }, mutations: { }, actions: {
}, getters: { timeSeconds(state){ return Syear => {
if (Syear == state.year) return `匹配成功`
return '当前年份不等于vuex中存储的年份' } } }, modules: {
} })
export default store
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| <template> <div id="wapper"> <input v-model="type"></input> <button @click="Sub">提交</button> <p>{{message}}</p> </div> </template>
<script> export default { data() { return { type:'', message:'' }; }, methods:{ Sub(){ this.message = this.$store.getters.timeSeconds(this.type) } } }; </script>
<style scoped > </style>
|
mutations
vuex状态更新的唯一方式:提交mutations
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| import Vue from 'vue' import Vuex from 'vuex'
Vue.use(Vuex)
const store = new Vuex.Store({ state: { date:'', msg:'', }, mutations: { updateYear(state,payload){ state.year = payload.year state.msg = payload.msg } }, actions: { }, getters: { }, modules: { } })
export default store
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| <template> <div id="wapper"> <input v-model="year"></input> <button @click="Sub">提交</button> </div> </template>
<script> export default { data() { return { year:'', message:'hello' }; }, methods:{ Sub(){ //第一种提交风格 //第一个参数是mutations中定义的方法名 第二个参数,就是所传的指,又被称为 Payload //this.$store.commit('updateYear',this.year) this.$store.commit({ type:'updateYear',//在mutations 一个方法可以分为两个部分,一个是事件类型(方法名),一个是载荷(参数) year:this.year, msg:this.message }) } } }; </script>
<style scoped > </style>
|
actions
mutations 中的操作只能是同步操作,如需要进行异步操作则需要用到actions
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| import Vue from 'vue' import Vuex from 'vuex'
Vue.use(Vuex)
const store = new Vuex.Store({ state: { msg:'hello ', }, mutations: { changeMsg(state,Cmsg){ state.msg = Cmsg } }, actions: { changeMsgActions(context, payload) { setTimeout(() => { context.commit('changeMsg',payload.msgg) }, 1000) } }, getters: { }, modules: { } })
export default store
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| <template> <div id="wapper"> <input v-model="year"></input> <button @click="Sub">提交</button> </div> </template>
<script> export default { data() { return { year:'', message:'hello' }; }, methods:{ Sub(){ this.$store.dispatch({ type:'changeMsgActions', msgg:'hello world' }) } } }; </script>
<style scoped > </style>
|
modules
当程序规模较大的时候,store对象可能变得非常臃肿,此时就可以使用modules对stroe进行划分成模块(modules),再对某个模块就行操作
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56
| import Vue from 'vue' import Vuex from 'vuex'
Vue.use(Vuex)
const moduleA = { state:{ name:'fish' }, mutations:{ updateName(state,payload){ state.name = payload } }, actions:{ updateName(context){ setTimeOut(()=>{ context.commit('updateName','awsl') },1000) } }, getters:{ fullName(state){ return state.name + 'haha' }, fullName2(state,getters){ return getters.fullName+'ababa' }, fullName3(state,getters,rootState){ return getters.fullName+rootState.year } } }
const store = new Vuex.Store({ state: { isLogin: false, year: '2021' }, mutations: { }, actions: {
}, getters: { }, modules: { a:moduleA } })
export default store
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| <template> <div id="wapper"> <h2>i am {{name}}</h2> <input v-model="cName" type="text"></input> <button @click="Sub">getName</button> </div> </template>
<script> export default { data() { return { name:'', cName:'' }; }, methods:{ Sub(){ this.$stroe.commit('updateName','zhangsan') // 普通提交 //提交以后,首先会去stroe对象中寻找对应方法,如果没有,则去模块中找,各个mutations 中的方法不能重名 }, created(){ this.name = this.$store.state.a.name // 定义的模块最终会被放到 store 对象中的 state中去 // 通过 this.$store.state.a 即可拿到上面我们定义的模块,使用其中的属性,则直接点出属性名即可 // this.name = this.$store.getters.fullname // this.name = this.$store.getters.fullname2 // 使用 getters 也是通过普通方式调用即可 } } }; </script>
<style scoped > </style>
|
vuex 目录结构
随着项目越来越大,如果把vuex的代码全部写在index.js一个文件当中,就很难就行管理,因此,我们可以对里面的内容拆分成多个文件
将五个核心配置,单独封装成五个模块
在index.js 中导入模块即可
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| import Vue from 'vue' import Vuex from 'vuex'
Vue.use(Vuex)
import mutations from './mutations.js' import actions from './actions.js' import getters from './getters.js' import state from './state.js'
import moduleA from './modules/moduleA.js'
const store = new Vuex.Store({ state, mutations, actions, getters, modules: { a: moduleA } })
export default store
|
使用exprot default 来导出对象
1 2 3 4 5 6 7 8 9 10 11 12 13
| export default {
clearLoginState(state) { state.isLogin = false }, loginSuccess(state) { state.isLogin = true }, changeMsg(state, Cmsg) { state.msg = Cmsg } }
|