学习笔记之Vuex(五)

(五)Vuex

一、什么是Vuex

1.概念

在Vue中实现集中式状态(数据)管理的一个Vue插件,对vue应用中多个组件的共享状态进行集中式的管理(读/写),也是一种组件间通信的方式,且适用于任意组件间通信。

在多组件中要共享数据 x,是由全局事件总线实现的,这样做会很麻烦,每个组件之间都要进行全局事件绑定,如下图所示:

image-20230225012815359

但是如果使用Vuex实现,就需要把 x 提取到vuex中,所有组件就都可以使用,如下图所示:

image-20230225013034369

Github 地址: https://github.com/vuejs/vuex

2.什么时候使用 Vuex

  • 多个组件依赖于同一状态;
  • 来自不同组件的行为需要变更同一状态。

二、Vuex工作原理

image-20230225013149912

Vuex有三个重要的组成部分:

  • actions(行为):发送ajax请求
  • mutations(加工)
  • state(状态):数据所在处

将数据写入state中后,由vc实例对象调用dispatch()方法,然后就会引起actions中对应函数的调用,之后再其中调用commit()方法,然后就会引起mutations中对应函数的调用,这个函数中就有state和所传参数,然后自动就会继续mutate,改变state中的数据,最后就会重新解析渲染。

image-20230225115257087

如果出现需要其他服务器传入参数,就需要在actions中进行,发送Ajax请求,但是如果对于参数已知,可以直接跳过actions,通过直接调用commit()方法到mutations。

Vuex中三个重要的组成部分的类型都是对象,它们都是在store下面进行管理的,也就是说dispatch()方法、commit()方法都是store提供的。

(1)state

  • vuex 管理的状态对象;

  • 它应该是唯一的;

  • 示例代码:

    image-20230225123028173

(2)actions

  • 值为一个对象,包含多个响应用户动作的回调函数;

  • 通过 commit( )来触发 mutation 中函数的调用, 间接更新 state;

  • 如何触发 actions 中的回调?

    在组件中使用: $store.dispatch('对应的 action 回调名') 触发

  • 可以包含异步代码(定时器, ajax 等等);

  • 示例代码:

    image-20230225123021239

(3)mutations

  • 值是一个对象,包含多个直接更新 state 的方法

  • 谁能调用 mutations 中的方法?如何调用?

    在 action 中使用:commit('对应的 mutations 方法名')触发;

  • mutations 中方法的特点:不能写异步代码、只能单纯的操作 state;

  • 示例代码:

    image-20230225123247198

三、搭建Vuex环境

1.安装vuex

由于在2022年2月7日,vue3称为了默认版本,如果执行npm i vue,就会直接安装为vue3的了,vue3的默认版本是vuex4,vue2的默认版本是vuex3,如果在vue2项目中安装vuex4版本就会报错:

image-20230225120906392

所以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:

image-20230225122503901

四、求和案例分析

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>

页面显示结果:

image-20230225130106423

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
})

页面显示结果:

image-20230225130658697

五、基本使用

1.初始化数据,配置actions,配置mutations,操作文件store.js

//引入Vue核心库
import Vue from 'vue'
//引入Vuex
import Vuex from 'vuex'
//引用Vuex
Vue.use(Vuex)

const actions = {
	//响应组件中加的动作
	jia(context ,value){
		// console. log('actions中的jia被调用了',miniStore,value)
		context. commit('JIA' ,value)
	}, 
}

const mutations = {
	//执行加
	JIA(state,value){
		// console. 1og( ' mutations中的IA被调用了',state, value)
		state.sum += value
	}
}

//初始化数据
const state = {
	sum:0
}

//创建并暴露store
export default new Vuex. Store({
	actions,
	mutations,
	state,
})

2.组件中读取vuex中的数据: $store.state.sum

3.组件中修改vuex中的数据: $store.dispatch( ' action中的方法名',数据)$store. commit( ' mutations中的方法名',数据)

备注:若没有网络请求或其他业务逻辑,组件中也可以越过actions,即不写dispatch,直接编写commit。

2.vuex开发者工具

vue和vuex是一个团队做的,开发者工具是一个,点击切换就可以切换到vuex开发者工具:

image-20230303185708806

image-20230303185806716

在实现功能的时候,开发者工具会帮你捕获mutations中使用的方法,下图中JIA旁边的三个按钮代表的意思分别是:合并、删除、退回到此数据:

image-20230303190113963

为了使数据导入,在state工具栏中有两个按钮,分别是:导出和导入,点击导出直接就可以复制粘贴:

image-20230303190614155

六、getters的使用

1.概念:当state中的数据需要经过加工后再使用时,可以使用getters加工。

2.在store.js中追加getters配置。

......

const getters = {
	bigSum(state){
		return state.sum * 10
	}
}

//创建并暴露store
export default new Vuex.Store({
    ......
	getters
})

3.组件中读取数据:$store.getters.bigSum

image-20230303192342570

image-20230303192325285

image-20230303192241037

七、四个map方法的使用

1.mapState方法:用于帮助我们映射state中的数据为计算属性。

computed: {
	//借助mapState生成计算属性: sum、 school、 subject (对象写法)
	...mapState({sum: 'sum' ,school: ' school , subject: ' subject'),

	//借助mapState生成计算属性: sum、 school、 subject (数组写法)
	...mapState(['sum' , school', ' subject']),
}

2.mapGetters方法:用于帮助我们映射getters中的数据为计算属性。

computed: {
	//借助mapGetters生成计算属性: bigSum (对象写法)
	...mapGetters({bigSum: 'bigSum'}),
        
	//借助mapGetters生成计算属性。bigSum (数组写法)
	...mapGetters(['bigSum'])
},

3.mapActions方法:用于帮助我们生成与actions对话的方法,即:包含$store.dispatch(xxx)的函数。

methods:{
	//靠mapActions生成: incrementodd、 incrementwait (对象形式)
	...mapActions({incrementodd: ' jiaOdd,incrementWait: 'jiaWait'})
                   
	//靠mapActions生成: incrementodd、 incrementWait (数组形式)
	...mapActions([ jiaOdd' , 'jiaWait'l)
}

4.mapMutations方法:用于帮助我们生成与mutations对话的方法,即:包含$store.commit(xxx)的函数。

methods:{
	//靠mapActions生成: increment、 decrement (对象形式)
	...mapMutations({increment:'JIA',decrement:'JIAN'}), 
    
	//靠mapMutations生成: JIA、 JIAN (对象形式) 
	...mapMutations(['JIA' ,'JIAN']),
}

备注:mapActionsmapMutations 使用时,若需要传递参数需要:在模板中绑定事件时传递好参数,否则参数是事件对象。

备注:首先需要引入:

import {mapState,mapGetters,mapActions,mapMutations} from 'vuex'

八、模块化+命名空间

1.目的:让代码更好维护,让多种数据分类更加明确。

2.修改store.js

const countAbout = {
	namespaced:true,//开启命名空间
	state:{x:1},
	mutations: { ... },
	actions: { ... },
	getters: {
		bigsum(state){
			return state.sum * 10
		}
	}
}

const personAbout = {
	namespaced:true, //开启命名空间
	state: { ... },
	mutations: { ... },
	actions: { ... }
}
               
const store = new Vuex.Store({
	modules: {
		countAbout,
		personAbout
	}
 })

3.开启命名空间后,组件中读取state数据:

//方式一:自己直接读取
this.$store.state.personAbout.list
//方式二:借助mapState读取,
...mapState('countAbout,['sum','school',' subject']),

4.开启命名空间后,组件中读取getters数据:

//方式一:自己直接读取
this.$store.getters['personAbout/firstPersoname']
//方式二:借助mapGetters读取:
...mapGetters('countAbout',['bigSun'])

5.开启命名空间后,组件中调用dispatch:

//方式一:自己直接dispatch
this.$store.dispatch( 'personAbout/addPersonMang',person)
//方式二:借助mapActions:
...mapActions('countAbout', {incrementodd: 'jiaOdd',incrementWait:'jialait'})

6.开启命名空间后,组件中调用commit

//方式一:自己直接commit
this.$store.commit('personAbout/ADD_PERSON',person)
//方式二:借助mapMutations:
...mapHutations('countAbout',{increment: 'JIA',decrement:'JIAN'}),
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值