什么是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>