用浅显易懂的语言讲解vuex

xiaoxiao2025-05-27  44

一.什么是vuex

官方说法:Vuex 是一个专为 Vue.js应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。

个人理解:Vuex提供了一个储存数据的地方,但它的核心作用在于封装操作数据的方法。

二.为什么要用Vuex?

我们知道组件之间是独立的,组件之间想要实现通信,除了vuex还有三种方法,父子组件之间通信使用$emit和props,非父子组件只能用eventbus(事件总线),但事件总线使用起来较为繁琐。试想一下,当做中大型项目时,面对一大堆组件之间的通信,还有一大堆的逻辑代码,会不会很抓狂??那为何不把组件之间共享的数据给“拎”出来,在一定的规则下管理这些数据呢? 这就是Vuex的基本思想了。

三.怎么使用Vuex?

从官方文档可以看到,vuex的核心就是store对象(数据库管理系统),store有五个核心概念,分别是state,getter,mutation,action,module。我们先来概述一下,然后再结合代码来具体讲解。

store对象中有四部分,state(相当于数据存储器),就是存储数据的地方。getter(数据处理方法),很多时候我们需要把数据处理之后再用,每次用的时候都处理很明显不方便,所以我们把数据处理方法集中放到getter中。mutation(同步改变数据方法),当我们要改变state中的数据时,不能直接改变state中的数据,只能通过mutation中的方法来改变,mutation中的方法必须是同步的。action(异步改变数据方法)。当我们要异步改变state中的数据时,就要通过action,但action改变数据也是依靠mutation。

借助官方的图可以更好地理解:

在组件中改变vuex中的数据时,首先使用dispatch(就是store自带的调用actions的方法)调用actions中的异步改变数据方法,然后由actions中的方法使用commit(store调用mutation的方法)调用mutations中的方法改变数据。当然,图中这是异步改变数据,当我们只是同步改变数据时,直接使用commit调用mutations中的方法就可以。通过mutations改变的state中的数据会响应式的显示在页面上。

module是一个store模块化的方案,当我们在store中的数据很多时,各种方法写在一起看起来会很臃肿,为了解决这个问题,Vuex 允许我们将 store 分割成模块。每个模块拥有自己的 state、mutation、action、getter、甚至是嵌套子模块——从上至下进行同样方式的分割。

结合代码来实战演练一下:

1.创建store实例

Vue.use(Vuex) const store = new Vuex.Store({ state: { count: 0 }, mutations: { increment (state) { state.count++ } } })

在上面的代码中,首先new了一个vuex实例,实例中有state和mutations。state对象就是我们的数据库, 其中保存了一个属性count值为0。mutations对象中保存的是我们操作state的方法。

然后我们将store挂载在vue实例上, store 实例会注入到根组件下的所有子组件中,且子组件能通过 this.$store 访问到。

new Vue({ el: '#app', router, store, components: { App }, template: '<App/>' })

 这时我们就可以在vue实例中使用vuex了,我们要把需要用到的store中的值写在计算属性中。

<template> <div id="app"> {{count}} </div> </template> <script> export default { name: 'App' }, computed: { count () { return this.$store.state.count } } </script>

 但当数据很多的时候,都这样声明在计算属性中就显得很麻烦,vuex提供了mapState 辅助函数,我们可以像下面这样改写一下

import {mapState} from 'vuex' export default { name: 'HomeHeader', computed: { mapState(['count']) } }

如果是多个数据的话我们还可以用对象展开运算符

computed: { ...mapState(['count','number']) }

这种写法对于某些童鞋来说可能会比较懵,我们来分析一下,

mapState是一个函数,返回一个对象,他的本质大概是这个样子滴:

function mapState(){return {count:1,number:2}} var data={ mapState() }  //这样肯定会报错的   var data = { ...mapState() } //这样就能正确展开 data = { count:1; number:2; }

2.mutation

想要改变count时,必须使用commit调用mutations中的方法

this.$store.commit('increment') //调用mountations中的方法 console.log(store.state.count) // -> 1

同样的mutations中也提供了辅助函数mapMutations:

...mapMutations(['increment']) this.increment()

方法中是可以传入参数的,mutatinos方法中默认传入的第一个参数为state,actions和getter的方法也是一样的:

mutations: { increment (state, n) { state.count += n } } this.$store.commit('increment', 10) //或者这样 ...mapMutations(['increment']) this.increment(10)

3.action

Action 提交的是 mutation,而不是直接变更状态。action不同于mutation,action 函数接受一个与 store 实例具有相同方法和属性的 context 对象而不是store本身。我们使用参数结构省略了context,写成了{commit}

const store = new Vuex.Store({ state: { count: 0 }, mutations: { increment (state) { state.count++ } }, actions: { incrementAsync ({ commit }) { setTimeout(() => { commit('increment') }, 1000) } })

调用actions中的方法使用dispatch

this.$store.dispatch('incrementAsync')

同样的actions也有辅助函数mapActions,在这里不再多说。

store.dispatch()方法返回的是一个promise对象,所以我们可以像使用promise时那样写

store.dispatch('actionA').then(() => { // ... })

 4.getter

很多时候我们直接从store中拿到的数据是不能使用的,需要经过处理,但每次使用的时候都写代码处理一次就比较麻烦,所以vuex为我们提供了getter,在getter中保存对数据处理的方法

Vue.use(Vuex) const store = new Vuex.Store({ state: { todos: [1,2,3] }, mutations: { increment (state) { state.count++ } } }) computed: { doneTodosCount () { return this.$store.state.todos.filter((n) => n<2).length } }

 对于上面的这种情况,我们可以将下面这段代码加到store实例中

getters: { doneTodos: state => { return state.todos.filter((n) => n<2) } }

 然后通过下面这样来调用

this.$store.getters.doneTodos

 

转载请注明原文地址: https://www.6miu.com/read-5030817.html

最新回复(0)