小白带你学习Vuex

flow2

概述

在做一些Vue项目时,如果遇到嵌套多层的组件间的数据同步和通信将会非常麻烦,另外如果一些数据交互是分散在各个组件的,很可能会重复获取数据,或者接口数据的返回有更改时,不能及时的定位,所以如果能在全局对数据进行统一的状态管理将会非常方便。 Vuex是Vue官方推荐的状态管理利器。

基础知识

Vuex的官方文档(https://vuex.vuejs.org/zh/)中有相应的阐述,以下是我的理解和整理。

  • state“状态”,整个应用只有一个state,为了确保对全局状态的管理,可以想象成一个大的“json对象”,也可以分为各个模块。
  • getter获取状态,进行数据请求
  • mutation修改状态的操作,同步
  • action提交mutation,异步简单来说,如果我们的state对象中有一个变量a的值为0;我们希望把a改为1,则需要进行的操作是先定义一个mutation将a置为1,然后用action去提交这个mutation,从而去修改state中的a。

开始实践

1.安装

npm i -g vue-cli    // 安装vue-cli
vue init webpack 项目名  // 初始化一个集成webpack的vue项目
npm i vuex    // 项目根目录下安装vuex

2.引入并使用Vuex,以及创建存储对象

import Vuex from 'vuex'
Vue.use(Vuex)

创建全局唯一的存储对象,命名随意,一般使用store,声明state对象,设置count为0;在mutations中使用add方法和minus方法更改count的值,mutation的参数一般是state对象和传入的参数;在actions中也有add和minus方法(actions中的函数的命名可以跟mutations中的一样)用于mutation的提交,参数一般是store对象和传入的参数。

const store = new Vuex.Store({
strict: true, // 严格模式——只能由mutation修改状态
state: {
  count: 0
},
mutations: {
  add (state, arg) {
   arg = arg || 1
   state.count += arg
},
  minus (state, arg) {
   arg = arg || 1
   state.count -= arg
}
},
actions: {
add ({commit}, arg) {
  commit('add', arg)
},
minus ({commit}, arg) {
  commit('minus', arg)
}
},
getters: {
}
})

最后需要把store对象挂载到Vue对象上。

new Vue({
el: '#app',
router,
store,
components: { App },
template: '<App/>'
})

3.在组件中使用store对象

前面我们已经准备好store对象,现在在组件中开始使用。我们写一个简单的父组件来显示count的值。

<template lang="html">
<span>{{state.count}}</span>
</template>

<script>
export default {
data () {
return {
  state: this.$store.state
}
}
}
</script>

然后我们在下面的子组件中改变count的值,Add方法中调用前面store中的action中的方法,用于提交更改,这样我们就简单实现了在一个组件中更改数据,在另一个组件中显示数据,其中的传参是为了在没有传值的时候加1和减1,在有参数的时候根据传参进行加减,这样就简单的使用了Vuex。

<template lang="html">
<li>
<input type="button" value="加1" @click="Add">
<input type="button" value="减1" @click="Minus">
</li>
</template>

<script>
export default {
data () {
return {
}
},
methods: {
Add () {
  this.$store.dispatch('add',3)
},
Minus () {
  this.$store.dispatch('minus',3)
}
}
}
</script>

那怎么把数据交互和Vuex配合起来呢? 我们来写一个demo实现从接口返回数据并显示在页面上。 写一个node server来模拟返回数据

const koa1=require('koa');
const router1=require('koa-router');

let server=new koa();
server.listen(8084);

server.use(async (ctx, next)=>{
ctx.set('Access-Control-Allow-Origin', '*');

await next();
});

let r1=router();

r1.get('/a', async ctx=>{
 ctx.body=[1,2,3,4,5,6];
});
server.use(r.routes());

在state中声明一个数组

state: {
    arr: []
}

在mutations中声明一个setArr方法用于更改arr的值

mutations: {
    setArr(state,arg){
        state.arr = arg;
    }
}

在actions中访问接口获取值

actions: {
    async getArr({commit},arg){
    let arr = await (await fetch('http://localhost:8084/server')).json();
    commit('setArr',arr);
    }
}

在getters中触发action(如果state中的arr不为空,则不会去请求数据)

getters: {
    arr(state){
    if(state.arr.length == 0){
    store.dispatch('getArr');
    }
    return state.arr;
    }
}

在组件中显示接口返回的值

<template>
<ul><li v-for="i in arr">{{i}}</li></ul>
</template>

<script>
export default {
data () {
return {
}
},
computed: {
arr () {
  return this.$store.getters.arr
}
},
}
</script>

这样就实现了vuex和数据交互的简单配合,可以在这个demo的基础上加以更改也可以跟上面的加以结合,实现前端触发更改传给后端的过程。

总结,Vuex的核心是store对象,我们在使用的时候需要先创建一个store对象(它是Vuex.Store对象的一个实例),然后在注册到Vue身上,就可以在组件里面使用了,在组件中的使用过程是,执行this.$store.dispatch方法,这个方法的作用是,找到对应的action,store对象中对应的action中会有一个commit方法去触发对应的mutation,只有mutation可以更改state对象的值,getters对象和actions对象配合使用可以进行数据交互。

发表评论