初识Vuex

287 阅读3分钟

最近学习了一下Vuex,在这里简单的做一个笔记。由于本人技术欠缺,有问题的地方欢迎指正。

什么是Vuex?

引用官网的话:Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。
注:个人觉得比较适用于项目中数据有关联性并且运用相同组件的情况,例如,购物车,答题等等。本文使用的案例就是一个答题demo。

核心概念

  1. State: 数据源。
const store = new Vuex.Store({
  state: {
    count: 1
  },
  }
  1. Getter: store 的计算属性

  2. Mutation:Mutation里面装了更改state状态的事件。

  3. Action:操作mutation里面的事件。
    注:Mutation和Action的区别
    1.mutation是同步的,Action 可以包含任意异步操作
    2.Action 提交的是 mutation,而不是直接变更状态

  4. Module:模块,为了解决当应用变得非常复杂时,store 对象就有可能变得相当臃肿的情况。

const moduleA = {
  state: { ... },
  mutations: { ... },
  actions: { ... },
  getters: { ... }
}

const moduleB = {
  state: { ... },
  mutations: { ... },
  actions: { ... }
}

const store = new Vuex.Store({
  modules: {
    a: moduleA,
    b: moduleB
  }
})

store.state.a // -> moduleA 的状态
store.state.b // -> moduleB 的状态

demo

demo需求:一个答题小测验。最重要的一点就是记录每道题的选择答案,提交答卷的时候根据答案进行打分。
首先,新建一个store文件,并且新建一个store.js文件

import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
const store = new Vuex.Store({
 /**************************************************************************************
 
  state存放数据源
    
 **********************************************************************************/
    state:{
      itemNum:1,//第几题
      answerid: [], //答案id
      itemDetail: [{
		"topic_id": 20,
		"topic_name": "大熊猫是哪个国家的?"
		"topic_answer": [{
			"topic_answer_id": 1,
			"topic_id": 20,
			"answer_name": "中国",
			"is_standard_answer": 1
		},
		{
			"topic_answer_id": 2,
			"topic_id": 21,
			"answer_name": "加拿大",
			"is_standard_answer": 0
		},{
			"topic_answer_id": 3,
			"topic_id": 23,
			"answer_name": "哥伦比亚",
			"is_standard_answer": 0
		}]
	},
	  .........
	]
    },
     /*********************************************************************************/
     
     mutations存放数据逻辑
     
     *********************************************************************************/
    mutations:{
       //记录答案
        REMBER_ANSWER(state, id){
            state.answerid.push(id)
        },
        //进入下一题
        ADD_ITEMNUM(state,num){
           state.itemNum += num
        },
        //初始化数据
        INITIAL_DATA(state){
            state.itemNum = 1;
            state.allTime = 0;
            state.answerid = [];
        }
    },
     /********************************************************************************/
     
     actions 操作mutations
     
     ********************************************************************************/
    actions:{
        addNum({commit, state},id) {
            commit('REMBER_ANSWER',id)
            if(state.itemNum < state.itemDetail.length){
                commit('ADD_ITEMNUM',1)
            }
        },
        initialzeDate({commit}){
            commit('INITIAL_DATA')
            //这里提交的是mutations中定义的INITIAL_DATA
        } 
    }

})
export default store

然后,新建一个组件question.vue,答题页面

<template>
  <!--循环渲染问题答案-->
  <section>
	<header >{{itemDetail[itemNum-1].topic_name}}</header>
	<ul>
	  <li  v-for="(item, index) in itemDetail[itemNum-1].topic_answer" 
	       :key='index' @click="choosed(index, item.answer_id)">
	  	{{item.answer_name}}
	  </li>
	</ul>
	</div>
	<span  @click="nextItem" v-if="itemNum < itemDetail.length">下一题</span>
	<span  v-else @click="submitAnswer">提交</span>
  </section>
</template>
<script>
import { mapState, mapActions } from 'vuex'
export default {
   name:'pageItem',
   data(){
       return {
        itemId: null, //题目ID
        choosedNum: null, //选中答案索引
        choosedId:null //选中答案id  
       }
   },
   /********************************************************************************/
     首先,在组件中使用在store中定义的状态数据,需要在组件的computed属性里声明这些变量
     例如:
     computed:{
        itemNum(){
          return this.$store.state.itemNum 
        }
    }
    由于state有多个数据,一个一个写就很麻烦,因此mapState因运而生,它可以帮你简单的引用这些变量,如下所示
    /******************************************************************************/
   computed: mapState([
  	'itemNum', //第几题
  	'itemDetail', //题目详情
    ]),
    
    methods:{
    /********************************************************************************/
     在组件中,想要使用Action中定义的方法,也需要挂载,其辅助函数为mapActions。通过...对象扩展运算符,将返回值解析就成为methods的属性,如下所示,'addNum','initialzeDate'是store.js中actions定义的。通过mapActions,可以在组件中直接使用这些方法了
     
    /******************************************************************************/
      ...mapActions([
          'addNum','initialzeDate'
      ]),
      nextItem(){
          if(this.choosedNum != null){
             this.choosedNum = null;
             //保存答案,题目索引加一,进入下一题
             this.addNum(this.choosedId)
          }else {
              alert('您还没有选择答案哦')
          }
      },
      //提价答案
      submitAnswer(){
        if(this.choosedNum != null){
            this.addNum(this.choosedId);
        }
      },
      //选中问题
      choosed(index,id){
        this.choosedNum = index;
        this.choosedId = id;
      },
  }
}
</script>

结语,这是初次尝试Vuex,文中的代码是仿照别人写的,具体来源不太清楚(若有侵权,请联系)。