21. Vuex
21.1 搭建Vuex环境
- 下载安装Vuex
npm i vuex
创建
src/store/index.js
该文件用于创建Vuex
中最为核心的store.js
文件//引入Vue import Vue from 'vue' //引入Vuex import Vuex from 'vuex' //应用Vuex Vue.use(Vuex) //准备actions对象--响应组件中用户的动作 const actions={ } //准备mutations对象--修改state中的数据 const mutations={ } //准备state对象--报错具体的数据 const state={ } //创建并暴露store export default new Vuex.Store({ actions, mutations, state })
在
src/main.js
中创建vm时传入store
配置项//引入Vue import Vue from 'vue' //引入插件 import vueResource from 'vue-resource' import store from './store' //使用插件 Vue.use(vueResource) //引入App组件 import App from './App' //关闭Vue的生产提示 Vue.config.productionTip = false new Vue({ el: "#app", store, render: h => h(App), beforeCreate() { Vue.prototype.$bus = this } })
21.2 基本使用
src/store/index.js
//引入Vue
import Vue from 'vue'
//引入Vuex
import Vuex from 'vuex'
//应用Vuex
Vue.use(Vuex)
//准备actions对象--响应组件中用户的动作
const actions={
add(context,value){
context.commit("ADD",value)
},
reduce(context,value){
context.commit("REDUCE",value)
},
addOdd(context,value){
if(context.state.sum%2){
context.commit("ADD",value)
}
},
addWait(context,value){
setTimeout(()=>{
context.commit("ADD",value)
},500)
}
}
//准备mutations对象--修改state中的数据
const mutations={
ADD(state,value){
state.sum+=value
},
REDUCE(state,value){
state.sum-=value
}
}
//准备state对象--报错具体的数据
const state={
sum:0
}
//创建并暴露store
export default new Vuex.Store({
actions,
mutations,
state
})
src/components/Count.vue
<template>
<div>
<h1>当前求和的值为: {{ $store.state.sum }}</h1>
<select v-model.number="n">
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
</select>
<button @click="add">+</button>
<button @click="reduce">-</button>
<button @click="addOdd">求和为奇数时再加</button>
<button @click="addWait">等一等再加</button>
</div>
</template>
<script>
export default {
name: "Count",
data() {
return {
n: 1,
}
},
mounted() {
}, methods: {
//加法
add() {
this.$store.commit('ADD',this.n)
},
//减法
reduce() {
this.$store.commit('REDUCE',this.n)
},
//奇数时加
addOdd() {
this.$store.dispatch('addOdd',this.n)
},
//等等再加
addWait() {
this.$store.dispatch('addWait',this.n)
},
}
}
</script>
<style scoped>
button {
margin-left: 5px;
}
</style>
21.3 getters的使用
- 概念: 当state中的数据需要经过加工后再使用时,可以使用getters加工
在
src/store/index.js
中追加getters
配置//准备getters对象,用于将state中的数据进行加工 const getters = { bigSum(state) { return state.sum * 10 } } //创建并暴露store export default new Vuex.Store({ ...... getters })
组件中读取数据:
$store.getters.bigSum
21.4 mapState和mapGetters
mapState用于帮助我们映射state
中的数据为计算属性
mapGetters用于帮助我们映射getters
中的数据为计算属性
src/components/Count.vue
<template>
<div>
<h1>当前求和的值为: {{ sum }}</h1>
<h3>当前求和的10倍为: {{ bigSum }}</h3>
<h2>我在{{ school }},学习{{ subject }}</h2>
<select v-model.number="n">
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
</select>
<button @click="add">+</button>
<button @click="reduce">-</button>
<button @click="addOdd">求和为奇数时再加</button>
<button @click="addWait">等一等再加</button>
</div>
</template>
<script>
import {mapState,mapGetters} from 'vuex'
export default {
name: "Count",
data() {
return {
n: 1,
}
},
computed:{
// he(){
// return this.$store.state.sum
// },
//借助mapState生成计算属性(对象写法)
// ...mapState({sum:"sum",school:"school",subject:"subject"}),
//借助mapState生成计算属性(数组写法)
...mapState(['sum','school','subject']),
//借助mapGetters生成计算属性(对象写法)
// ...mapGetters({bigSum:"bigSum"})
//借助mapGetters生成计算属性(数组写法)
...mapGetters(["bigSum"])
},
mounted() {
console.log("Count", this.$store)
},
methods: {
//加法
add() {
this.$store.commit('ADD', this.n)
},
//减法
reduce() {
this.$store.commit('REDUCE', this.n)
},
//奇数时加
addOdd() {
this.$store.dispatch('addOdd', this.n)
},
//等等再加
addWait() {
this.$store.dispatch('addWait', this.n)
},
}
}
</script>
<style scoped>
button {
margin-left: 5px;
}
</style>
21.5 mapMutations和mapActions
mapMutations方法用于帮助我们生成与mutations
对话的方法,即: 包含$store.commit(xxx)
的函数
mapActions方法用于帮助我们生成与actions
对话的方法,即: 包含$store.dispatch(xxx)
的函数
src/components/Count.vue
<template>
<div>
<h1>当前求和的值为: {{ sum }}</h1>
<h3>当前求和的10倍为: {{ bigSum }}</h3>
<h2>我在{{ school }},学习{{ subject }}</h2>
<select v-model.number="n">
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
</select>
<button @click="ADD(n)">+</button>
<button @click="REDUCE(n)">-</button>
<button @click="addOdd(n)">求和为奇数时再加</button>
<button @click="addWait(n)">等一等再加</button>
</div>
</template>
<script>
import {mapState,mapGetters,mapActions,mapMutations} from 'vuex'
export default {
name: "Count",
data() {
return {
n: 1,
}
},
computed:{
// he(){
// return this.$store.state.sum
// },
//借助mapState生成计算属性(对象写法)
// ...mapState({sum:"sum",school:"school",subject:"subject"}),
//借助mapState生成计算属性(数组写法)
...mapState(['sum','school','subject']),
//借助mapGetters生成计算属性(对象写法)
// ...mapGetters({bigSum:"bigSum"})
//借助mapGetters生成计算属性(数组写法)
...mapGetters(["bigSum"])
},
mounted() {
console.log("Count", this.$store)
},
methods: {
// //加法
// add() {
// this.$store.commit('ADD', this.n)
// },
// //减法
// reduce() {
// this.$store.commit('REDUCE', this.n)
// },
//借助mapMutations生成调用commit的方法(对象写法)
// ...mapMutations({add:"ADD",reduce:"REDUCE"}),
//借助mapMutations生成调用commit的方法(数组写法)
...mapMutations(["ADD","REDUCE"]),
//******************************************************//
//奇数时加
// addOdd() {
// this.$store.dispatch('addOdd', this.n)
// },
// //等等再加
// addWait() {
// this.$store.dispatch('addWait', this.n)
// },
//借助mapActions生成调用dispatch的方法(对象写法)
// ...mapActions({addOdd:"addOdd",addWait:"addWait"})
//借助mapActions生成调用dispatch的方法(数组写法)
...mapActions(['addOdd','addWait'])
}
}
</script>
<style scoped>
button {
margin-left: 5px;
}
</style>
21.6 模块化+命名空间
- 目的:让代码更好维护,让多种数据分类更加明确
修改
store.js
//引入Vue import Vue from 'vue' //引入Vuex import Vuex from 'vuex' //应用Vuex Vue.use(Vuex) import countAbout from './count' import personAbout from './person' //创建并暴露store export default new Vuex.Store({ modules:{ countAbout:countAbout, personAbout:personAbout } })
count.js
export default { //开启命名空间 namespaced:true, actions:{ add(context, value) { context.commit("ADD", value) }, reduce(context, value) { context.commit("REDUCE", value) }, addOdd(context, value) { if (context.state.sum % 2) { context.commit("ADD", value) } }, addWait(context, value) { setTimeout(() => { context.commit("ADD", value) }, 500) } }, mutations:{ ADD(state, value) { state.sum += value }, REDUCE(state, value) { state.sum -= value }, }, state:{ sum: 0, school:"南方IT", subject:"软件工程", }, getters:{ bigSum(state) { return state.sum * 10 } }, }
person.js
import {nanoid} from "nanoid"; import axios from "axios"; export default { //开启命名空间 namespaced:true, actions:{ //添加一个姓王的人 addPersonWang(context,value){ if(value.name.indexOf("王")===0){ context.commit("ADD_PERSON",value) }else{ alert("添加人员的姓必须为王") } }, addPersonServer(context){ axios.get("https://api.uixsj.cn/hitokoto/get?type=zha").then( response=>{ context.commit("ADD_PERSON",{id:nanoid(),name:response.data}) }, error=>{ alert(error.message) } ) } }, mutations:{ ADD_PERSON(state, value){ state.personList.unshift(value) } }, state:{ personList:[ {id:nanoid(),name:"张三"} ] }, getters:{ //获取人员列表里的第一个人的名称 FirstPersonName(state){ return state.personList[0].name } }, }
开启命名空间后,组件中读取state数据
//方式一: 自己直接读取 this.$store.state.personAbout.personLit //方式二: 借助mapState读取 ...mapState('countAbout',['sum','school','subject'])
开启命名空间后,组件中读取getters数据
//方式一: 自己直接读取 this.$store.getters["personAbout/FirstPersonName"] //方式二: 借助mapGetters读取 ...mapGetters('countAbout',["bigSum"])
开启命名空间后,组件中调用dispatch
//方式一: 自己直接dispatch this.$store.dispatch("personAbout/addPersonWang",personObj) //方式二: 借助mapActions: ...mapActions('countAbout',['addOdd','addWait'])
开启命名空间后,组件中调用commit
//方式一: 自己直接commit his.$store.commit("personAbout/ADD_PERSON",personObj) //方式二: 借助mapMutations: ...mapMutations('countAbout',["ADD","REDUCE"])