Vuex
- (五)Vuex
- 一、什么是Vuex
- 二、Vuex工作原理
- 三、搭建Vuex环境
- 四、求和案例分析
- 4.1 求和案例——vue实现
- 4.2 求和案例——vuex实现
(五)Vuex
一、什么是Vuex
1.概念
在Vue中实现集中式状态(数据)管理的一个Vue插件,对vue应用中多个组件的共享状态进行集中式的管理(读/写),也是一种组件间通信的方式,且适用于任意组件间通信。
在多组件中要共享数据 x,是由全局事件总线实现的,这样做会很麻烦,每个组件之间都要进行全局事件绑定,如下图所示:
但是如果使用Vuex实现,就需要把 x 提取到vuex中,所有组件就都可以使用,如下图所示:
Github 地址: https://github.com/vuejs/vuex
2.什么时候使用 Vuex
- 多个组件依赖于同一状态;
- 来自不同组件的行为需要变更同一状态。
二、Vuex工作原理
Vuex有三个重要的组成部分:
- actions(行为):发送ajax请求
- mutations(加工)
- state(状态):数据所在处
将数据写入state中后,由vc实例对象调用dispatch()方法,然后就会引起actions中对应函数的调用,之后再其中调用commit()方法,然后就会引起mutations中对应函数的调用,这个函数中就有state和所传参数,然后自动就会继续mutate,改变state中的数据,最后就会重新解析渲染。
如果出现需要其他服务器传入参数,就需要在actions中进行,发送Ajax请求,但是如果对于参数已知,可以直接跳过actions,通过直接调用commit()方法到mutations。
Vuex中三个重要的组成部分的类型都是对象,它们都是在store下面进行管理的,也就是说dispatch()方法、commit()方法都是store提供的。
(1)state
-
vuex 管理的状态对象;
-
它应该是唯一的;
-
示例代码:
(2)actions
-
值为一个对象,包含多个响应用户动作的回调函数;
-
通过 commit( )来触发 mutation 中函数的调用, 间接更新 state;
-
如何触发 actions 中的回调?
在组件中使用:
$store.dispatch('对应的 action 回调名')
触发 -
可以包含异步代码(定时器, ajax 等等);
-
示例代码:
(3)mutations
-
值是一个对象,包含多个直接更新 state 的方法
-
谁能调用 mutations 中的方法?如何调用?
在 action 中使用:
commit('对应的 mutations 方法名')
触发; -
mutations 中方法的特点:不能写异步代码、只能单纯的操作 state;
-
示例代码:
三、搭建Vuex环境
1.安装vuex
由于在2022年2月7日,vue3称为了默认版本,如果执行npm i vue
,就会直接安装为vue3的了,vue3的默认版本是vuex4,vue2的默认版本是vuex3,如果在vue2项目中安装vuex4版本就会报错:
所以vue2中,要用vuex的3版本,vue3中,要用vuex的4版本。
指定版本安装: npm i vuex@3
2.使用步骤:
(1)创建文件:src/store/index.js,该文件用于创建Vuex中最为核心的store;
//引入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
)}
(2)在main.js
中创建vm时传入store
配置项。
......
//引入store
import store from ' ./store "
......
//创建vm
new Vue({
el:'#app',
render: h =》h(App),
store
})
注意:vue脚手架在执行的时候,会扫描整个文件,然后将所有的import语句先执行,所以就需要在src/store/index.js文件中引用并使用Vuex。
搭建完毕后,在vc中就会出现store:
四、求和案例分析
4.1 求和案例——vue实现
Count.vue文件:
这里注意在绑定数据的适合,为了传入的数据是数字number,不是字符串String,这里可以使用 v-model.number绑定,或者在value前面加冒号:
,:value="1"
;
<template>
<div>
<h1>当前求和为:{{sum}}</h1>
<select v-model="n">
<!-- v-model.number="n" -->
<option :value="1">1</option>
<option :value="2">2</option>
<option :value="3">3</option>
</select>
<button @click="increment">+</button>
<button @click="decrement">-</button>
<button @click="incrementOdd">当前求和为奇数再加</button>
<button @click="incrementWait">等一等再加</button>
</div>
</template>
<script>
export default {
name:'Count',
data() {
return {
n:1, //用户选择的数字
sum:0 //当前的和
}
},
methods:{
increment(){
this.sum += this.n
},
decrement(){
this.sum -= this.n
},
incrementOdd(){
if(this.sum % 2){
this.sum += this.n
}
},
incrementWait(){
setTimeout(()=>{
//函数体
this.sum += this.n
},500)
},
}
}
</script>
<style>
button{
margin-left: 5px;
}
</style>
App.vue文件中:
<template>
<div>
<Count/>
</div>
</template>
<script>
//引入组件
import Count from './components/Count.vue'
export default {
name:'App',
components:{Count},
}
</script>
页面显示结果:
4.2 求和案例——vuex实现
Count.vue文件:
<template>
<div>
<h1>当前求和为:{{$store.state.sum}}</h1>
<select v-model="n">
<!-- v-model.number="n" -->
<option :value="1">1</option>
<option :value="2">2</option>
<option :value="3">3</option>
</select>
<button @click="increment">+</button>
<button @click="decrement">-</button>
<button @click="incrementOdd">当前求和为奇数再加</button>
<button @click="incrementWait">等一等再加</button>
</div>
</template>
<script>
export default {
name:'Count',
data() {
return {
n:1, //用户选择的数字
}
},
methods:{
//前面两个函数中什么添加也没有,所以可以直接通过commit写在mutations中
increment(){
this.$store.commit('JIA',this.n)
},
decrement(){
this.$store.commit('JIAN',this.n)
},
incrementOdd(){
this.$store.dispatch('jiaOdd',this.n)
},
incrementWait(){
this.$store.dispatch('jiaWait',this.n)
},
}
}
</script>
<style>
button{
margin-left: 5px;
}
</style>
App.vue文件中:
<template>
<div>
<Count/>
</div>
</template>
<script>
//引入组件
import Count from './components/Count.vue'
export default {
name:'App',
components:{Count},
}
</script>
main.js文件中:
//引入Vue
import Vue from 'vue'
//引入App
import App from './App.vue'
//引入插件
import VueResource from 'vue-resource'
//引入store
import store from './store'
//关闭Vue的生产提示
Vue.config.productionTip = false
//使用插件
Vue.use(VueResource)
//创建vm
new Vue({
el:'#app',
render: h => h(App),
store,
beforeCreate() {
Vue.prototype.$bus = this
},
})
src/store/index.js文件中:
//该文件用于创建Vuex中最为核心的store
//引入Vue核心库
import Vue from 'vue'
//引入Vuex
import Vuex from 'vuex'
//应用Vuex插件
Vue.use(Vuex)
//准备actions对象一响应组件中用户的动作
const actions = {
// //前面两个函数中什么添加也没有,所以可以直接通过commit写在mutations中
// jia(context, value) {
// console.log('actions中的jia被调用了')
// context.commit('JIA',value)
// },
// jian(context, value) {
// console.log('actions中的jian被调用了')
// context.commit('JIAN',value)
// },
//后面两个函数中都添加了条件
jiaOdd(context, value) {
console.log('actions中的jiaOdd被调用了')
if(context.state.sum % 2){
context.commit('JIA',value)
}
},
jiaWait(context, value) {
console.log('actions中的jiaWait被调用了')
setTimeout(()=>{
context.commit('JIA',value)
},500)
},
}
//准备mutations对象一修改state中的数据
const mutations = {
JIA(state,value){
console.log('mutations中的JIA被调用了')
state.sum += value
},
JIAN(state,value){
console.log('mutations中的JIAN被调用了')
state.sum -= value
}
}
//准备state对象一保存具体的数据
const state = {
sum:0 //当前的和
}
//创建并暴露store
export default new Vuex.Store({
actions,
mutations,
state
})
页面显示结果: