vuex基础到模块化

507 阅读1分钟

什么是Vuex

在Vue中,多组件的开发给我们带来了很多的方便,但同时当项目规模变大的时候,多个组件间的数据通信和状态管理就显得难以维护。而Vuex即将状态管理,可以简单理解为全局变量。Vuex采用和Redux类似的单向数据流的方式来管理数据。用户界面负责触发动作(Action)进而改变对应状态(State),从而反映到视图(View)上。


数据流转图


基本使用

vuex简单计数器示例:

<div id="app">
  <p>{{ count }}</p>
  <p>
    <button @click="increment">+</button>  //触发methods中的increment方法
    <button @click="decrement">-</button>
  </p>
</div>

const store = new Vuex.Store({
  state: {
    count: 0
  },
  mutations: {
  	increment: state => state.count++,  //此处使用箭头函数
    decrement: state => state.count--
  }
})

new Vue({
  el: '#app',
  computed: {
    count () {
	    return store.state.count
    }
  },
  methods: {
    increment () {
      store.commit('increment')    //触发mutations中的increment状态变更
    },
    decrement () {
    	store.commit('decrement')
    }
  }
})

触发流程:

前端调用方法 --> methods中的对应方法 --> store.commit触发 mutations中的相应方法 --> state中的状态属性被改变

效果:



模块化使用


main.js

import Vue from 'vue'
import VueRouter from 'vue-router'
import ElementUI from 'element-ui'
import 'element-ui/lib/theme-default/index.css'
import App from './App'
import axios from './http.js'
import echarts from 'echarts'
//导入store入口文件
import store from './store/index'

Vue.use(VueRouter)
Vue.use(ElementUI)

/*vue全局引入外部插件的方法,通过this.$axios*/
Vue.prototype.$axios = axios;
Vue.prototype.$echarts = echarts;

Vue.config.productionTip = false

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

store/index.js

import Vue from 'vue'
import Vuex from 'vuex'
//导入vuex的store模块
import moduleOne from './modules/storeModuleOne'   
// 引入 axios
import axios from '../http'
Vue.use(Vuex)

// 从环境变量判断当前运行模式
// const debug = process.env.NODE_ENV !== 'production'


const store =  new Vuex.Store({
	// strict:debug,                         //设置运行模式
	// plugin:debug ? [createLogger()] : []  //调试模式则加入日志插件
    modules:{
        moduleOne
    },
    //state相当于data
    state: {
        //作者名称
        author: 'FANE',
        address:'江苏南京',
        school:['北大','清华'],
        version:'版本一',
        loginInfo:{
            name:'Zhang',
            age:'24'
        },
        count: 1,
        data:['www']
    },
    //getters相当于computed
    getters:{
        author:state => state.author,
        loginInfo:state => state.loginInfo,
        // address:state => state.address,
        // version:state => state.version,
        // school:state => state.school,
        count:state => state.count,
        data:state => state.data,
    },
    
    mutations: {
        increment:state => state.count++,
        decrement:state => state.count--,

        dataReceive(state,res){
            state.data = res
        }

    },
    //actions相当于methods(或者MVC中的Controller),用于操作mutations实现对state中状态的读取,但是actions不会直接对状态做修改
    actions:{
        decrement (context) {
            context.commit('decrement')
        },
        getBarData(context){
            //原来使用axios时是通过全局定义Vue.prototype.$axios = axios;用this.$axios.get()方法调用;
            //但是在store中的this并不是一个Vue实例,此处直接导入axios调用即可
            axios.get('/api/getBarData').then(res => {
                context.commit('dataReceive',res.data.data.title)
            })
                .catch(e => {
                    console.warn('error','getBarData查询异常')
                    console.log(e)   //打印错误状态
                })
        }
    }
})

// 导出store实例对象
export default store

store的子文件moduleOne.js

import Vue from 'vue'

const state = {
    liu:'jingna',
    wei:['yu','ning']
}
const mutations = {
    changeName(state,res){
        state.liu = res
    }
}

const actions = {
    changeNameA(context){
        context.commit('changeName','南京')
    }
}

export default {
    state,mutations,actions
}

axios的http.js导入处理——作用为axios的请求拦截和处理
vuex与axios结合的方案来源于,WiseWrong的博客 www.cnblogs.com/wisewrong/p…

import axios from 'axios'


// 添加请求拦截器
axios.interceptors.request.use(function (config) {
    // 在发送请求之前做些什么
    console.log("axios请求拦截")
    console.log(config)
    return config;
  }, function (error) {
    // 对请求错误做些什么
    return Promise.reject(error);
  });

// 添加响应拦截器
axios.interceptors.response.use(function (response) {
    // 对响应数据做点什么
    console.log("axios响应拦截")
    return response;
  }, function (error) {
    // 对响应错误做点什么
    return Promise.reject(error);
  });

export default axios;

vue页面

<template>
	<div id="mochild2" style="border:solid 2px grey;padding:10px;">
		This is mochild2!
		  <div>
		  	<h1>{{this.author}}</h1>
            <h1>{{this.address}}</h1>
            <h1>{{this.loginInfo}}</h1>
            <h1>{{this.version}}</h1>
            <h1>{{this.school}}</h1>
            <h1>{{this.data}}</h1>
            <h1>{{this.count}}</h1>

            <h2>{{this.liu}}</h2>
            <el-button size="small" @click="add()">数字加</el-button>
            <el-button size="small" @click="small()">数字减</el-button>
            <el-button size="small" @click="changeNameA()">改名字</el-button>
		  </div>
	</div>
</template>
<script type="text/javascript">
import {mapGetters,mapActions,mapState} from 'vuex'
export default{
	 data() {
      return {

      }
    },
    computed:{
	     //此处loginInfo是一个对象,默认执行get方法放回当前参数
        loginInfo:{
            get(){
                return this.$store.state.loginInfo.name  //state直接获取
            },
            set(newValue){
                this.$store.state.loginInfo.name = newValue
            }
        },
        version(){
            return this.$store.state.version    //方法一:state直接获取
        },
        author(){
            return this.$store.getters.author   //方法一:getters方法获取
        },

        ...mapState([                           //方法二:mapState获取
            'address',
            'school',
        ]),
        ...mapGetters([                         //方法二:mapGetters获取
            'count',
            'data'
        ]),
        /*moduleOne中的文件*/
        liu(){
            return this.$store.state.moduleOne.liu
        },
    },
    mounted(){
        this.getBarData();
    },
     methods: {
	     add(){
             this.$store.commit('increment')  //.commit()方法可以直接调用mutations的increment方法
         },
         small(){
             this.$store.dispatch('decrement')   //方法一:.dispatch()方法调用actions中的方法decrement,间接调用mutations中的decrement
         },
         ...mapActions([                         // 方法二:通过mapActions将actions映射到methods中
             'getBarData',
             'changeNameA'    //changeNameA是来自moduleOne的actions
         ])
     }
}
</script>