Vue基础——状态管理(vuex)

本文详细介绍了Vuex在Vue.js中的应用,包括状态、getter、mutation和action的概念,以及如何组织Module来管理复杂状态。Vuex适用于管理共享状态,但在小型应用中可能显得繁琐。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

状态管理(vuex)

一、什么是Vuex

Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式 + 库;Vuex可以帮助我们管理共享状态

状态自管理应用包含:

  • 状态,驱动应用的数据源;
  • 视图,以声明方式将状态映射到视图;
  • 操作,响应在视图上的用户输入导致的状态变化。
img

二、Vuex的作用

Vuex有五个核心概念:State、Getter、Mutation、Action、Module

state

  • 用于存放组件间通信的属性值
  • state中的属性不能直接修改,需要在mutations中修改
//格式
// state.js
export default{
	state:{
        name:"张三"
    }
}

// ./store/index.js
import state from './state'
export default new Vuex.Store({
	state
})
//取值(在页面中)
<template>
	<div>
        {{$store.state.name}} <!-- 用法1 -->
        <he />
        {{name}} <!-- 用法三的使用 -->
    </div>
</template>
<script>
import { mapState } from "vuex"
export default{
    mounted(){
        console.log(this.$store.state.name) //用法二
    }
    computed:{
    	...mapState(['name']) //用法三(相当于把属性放在this上)
	}
}
</script>

getters

  • 是一些函数,类似于组件中的计算属性
  • 可以处理一些通用且复杂的逻辑,实际使用较少
//格式
// getters.js
export default{
	setName(state){
        return '我是' + state.name
    }
}

// ./store/index.js
import state from './state'
import getters from './getters'
export default new Vuex.Store({
	state,
    getters
})
//取值(在页面中)
<template>
	<div>
        {{setName}}
    </div>
</template>
<script>
import { mapGetters } from "vuex"
export default{
    computed:{
    	...mapGetters(['setName'])
	}
}
</script>

mutations

  • 存放函数,可用于修改state中的属性值
  • 只接受两个参数:state和options
  • 原则上mutations必须都是同步函数
  • 在组件中使用 this.$store.commit('xxx') 提交 mutation,或者使用 mapMutations 辅助函数将组件中的 methods 映射为 store.commit 调用
  • 使用常量替代 mutation 事件类型在各种 Flux 实现中是很常见的模式
//格式
// mutations.js
export default{
	btn(){
        alert(1)
    },
    setName(state,name){
        state.userName = name
    }
}
// state.js
export default{
	list:[
        {name:'张三'},
        {name:'李四'},
        {name:'王五'},
    ],
    userName:''
}

// ./store/index.js
import state from './state'
import getters from './getters'
import mutations from './mutations'
export default new Vuex.Store({
	state, //数据
    getters, //计算属性
    mutations //方法
})
//取值(在页面中)
<template>
	<div>
        <button @click="btn">按钮1</button> <!-- 用法1 -->
        <button @click="run">按钮2</button> <!-- 用法2 -->
        <ul>
        	<li v-for='(item,index) in list' :key='index' @click='showName(item.name)'>
    		</li>    <!-- 用法3 -->
    	</ul>
        <hr />
        <h1>{{userName}}</h1>
    </div>
</template>
<script>
import { mapMutations,mapState } from "vuex"
export default{
    computed:{
      ...mapState(['list''userName'])  
    },
    methods:{
        ...mapMutations(['btn','srtName']) //用法1
        run(){
    		this.btn() //用法2
		},
        showName(name){
            //this.userName = name ===>报错,不能直接修改state中的userName
            this.setName(name) //用法3  传值
            this.$store.commit("setName",name) //用commit提交mutation
        }
    }
}
</script>

如果想在每个页面都要使用到同一个函数可以执行commit提交mutation

//在main.js中
import store from './store'

store.commit("btn")
image-20231124113426335

使用常量替代 mutation 事件类型,这样可以对mutation的函数作用更加一目了然

// mutation-types.js
export const SOME_MUTATION = 'SOME_MUTATION'
// mutations.js
export default{
	[SOME_MUTATION](){
        alert('我被触发了');
    }
}
// 在页面中
<template>
	<div>
        <button @click="SOME_MUTATION">按钮</button>
    </div>
</template>
<script>
import { mapMutations } from "vuex"
export default{
    methods:{
        ...mapMutations(['SOME_MUTATION'])
    }
}
</script>

Action

  • 提交的是mutation,而不是直接变更状态
  • 可以包含任意异步操作
//mutations.js
import {ADD,RE,SUM} from './mutation-type' //在mutation-type中取函数类型
export default {
    [ADD](state,obj){ //obj为action使用commit传过来的值
        alert(obj)
        state.count++
        this.commit('SUM')
    },
    [RE](state){
        state.count--
        this.commit('SUM')
    },
    [SUM](state){
        state.sum = state.count*10
    }
}
//actions.js
export default{
    addFn({commit},obj){
        commit('ADD',obj) //使用mutation的ADD函数并传值obj
    }
}
<template>
  <div class="home">
    <h1>{{count}}</h1>
    <button @click="btn">按钮</button>
  </div>
</template>

<script>
import {mapState,mapActions} from 'vuex'
export default {
  name: 'Home',
  computed:{
    ...mapState(['count'])
  },
  methods:{
    ...mapActions(['addFn']), //action
    btn(){
      this.addFn(1) //使用action中的addFn函数并传值1
    }
  }
}
</script>

mutation是同步函数而action是异步

官网中这样说在这里插入图片描述

代码解释:

//页面
<template>
  <div class="home">
    <h1>{{count}}</h1>
    <button @click="run">mutations按钮(点击+10)</button>
  </div>
</template>

<script>
import {mapState,mapMutations} from 'vuex'
export default {
  name: 'Home',
  computed:{
    ...mapState(['count'])
  },
  methods:{
    ...mapMutations(['setCount']),
    run(){
      this.setCount({
        num:10
      })
    }
  }
}
</script>

同步情况下:

//mutation.js
export default {
    setCount(state,obj){
         state.count += obj.num
    }
}

结果如下:在这里插入图片描述

数据都是对的上的,没有问题!

异步情况下:

//mutation.js
export default {
    setCount(state,obj){
        setTimeout(() => {
            state.count += obj.num
        }, 1000);
    }
}

结果如下:
在这里插入图片描述

调式的数据对不上,出现异常了!

那么试试action中异步提交mutation:

//页面
<template>
  <div class="home">
    <h1>{{count}}</h1>
    <button @click="run">mutations按钮(点击+10)</button>
  </div>
</template>

<script>
import {mapState,mapActions} from 'vuex'
export default {
  name: 'Home',
  computed:{
    ...mapState(['count'])
  },
  methods:{
    ...mapActions(['setCountFn']),
    run(){
      this.setCountFn({
        num:10
      })
    }
  }
}
</script>
//mutation.js
export default {
    setCount(state,obj){
         state.count += obj.num
    }
}
//actions.js
export default{
    setCountFn({commit},obj){
        setTimeout(() => {
            commit("setCount",obj)
        }, 1000);
    }
}

结果如下:
在这里插入图片描述

数据对上了,正常!

这就是为什么mutation中混合异步调用会使你的程序很难调试,这就是mutation必须使用同步函数的原因!

Module

为了将模块更加细致分类,每个模块写一个仓库,都包含了state、mutation、getter、action

例如:

/* ./modules/list.js */
export default {
    state:{},
    getter:{},
    mutation:{},
    action:{}
}
/* ./store/index.js */
import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

import list from './modules/list.js'

export default new Vuex.Store({
	modules:{
		list,
		...
	}
})

// 页面中使用
computed:{
    ...mapState({
        属性名:state=>state.list.属性名
    })
}

总结:

Vuex是为了方便而使用的,当你觉得使用会让你方便的时候才使用。

Vuex 可以帮助我们管理共享状态,并附带了更多的概念和框架。这需要对短期和长期效益进行权衡。

如果您不打算开发大型单页应用,使用 Vuex 可能是繁琐冗余的。确实是如此——如果您的应用够简单,您最好不要使用 Vuex

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值