如何使用 Vuex 设计你的数据流

1.前端数据管理

首先,我们需要掌握前端的数据怎么管理,现代 Web 应用都是由三大件构成,分别是:组件、数据和路由。
数据组件之间需要共享的时候,应该如何实现?

解决这个问题的最常见的一种思路就是:专门定义一个全局变量,任何组件需要数据的时候都去这个全局变量中获取。一些通用的数据,比如用户登录信息,以及一个跨层级的组件通信都可以通过这个全局变量很好地实现。在下面的代码中我们使用 _store 这个全局变量存储数据。

window._store = {}

数据存储的结构图大致如下,任何组件内部都可以通过 window._store 获取数据并且修改。
在这里插入图片描述
但这样就会产生一个问题,window._store 并不是响应式的,如果在 Vue 项目中直接使用,那么就无法自动更新页面。所以我们需要用 ref 和 reactive 去把数据包裹成响应式数据,并且提供统一的操作方法,这其实就是数据管理框架 Vuex 的雏形了。

2.vuex 是什么

Vuex 又是做什么的?其实,Vuex 存在的意义,就是管理我们项目的数据。

我们是使用组件化机制来搭建整个项目,每个组件内部有自己的数据和模板。但是总有些数据是需要共享的,比如当前登录的用户名、权限等数据,如果都在组件内部传递,会变得非常混乱。

如果把开发的项目比作公司的话,我们项目中的各种数据就非常像办公用品。很多小公司在初创时期不需要管理太多,大家随便拿办公用品就行。但是公司大了之后,就需要一个专门的办公用品申报的流程,对数据做统一地申请和发放,这样才能方便做资产管理。Vuex 就相当于我们项目中的大管家,集中式存储管理应用的所有组件的状态。

下面,我们先来上手使用一下 Vuex。我们项目结构中的 src/store 目录,就是专门留给 Vuex 的,在项目的目录下,我们执行下面这个命令,进行 Vuex 的安装工作。

npm install vuex@next

安装完成后,我们在 src/store 中先新建 index.js,在下面的代码中,我们使用 createStore 来创建一个数据存储,我们称之为 store。
store 内部除了数据,还需要一个 mutation 配置去修改数据,你可以把这个 mutation 理解为数据更新的申请单,mutation 内部的函数会把 state 作为参数,我们直接操作 state.count 就可以完成数据的修改。

import { createStore } from 'vuex'
const store = createStore({
  state () {
    return {
      count: 666
    }
  },
  mutations: {
    add (state) {
      state.count++
    }
  }
})

现在你会发现,我们的代码里,在 Vue 的组件系统之外,多了一个数据源,里面只有一个变量 count,并且有一个方法可以累加这个 count。然后,我们在 Vue 中注册这个数据源,在项目入口文件 src/main.js 中,使用 app.use(store) 进行注册,这样 Vue 和 Vuex 就连接上了。
然后,我们使用 .use 就可以对路由进行注册,使用 .mount 就可以把 Vue 这个应用挂载到页面上,代码如下。

const app = createApp(App)
app.use(store)
    .use(router)
    .mount('#app')

之后,我们在 src/components 文件夹下新建一个 Count.vue 组件,在下面的代码中,template 中的代码我们很熟悉了,就是一个 div 渲染了 count 变量,并且点击的时候触发 add 方法。在 script 中,我们使用 useStore 去获取数据源,初始化值和修改的函数有两个变化:

  • count 不是使用 ref 直接定义,而是使用计算属性返回了 store.state.count,也就是刚才在 src/store/index.js 中定义的 count。
  • add 函数是用来修改数据,这里我们不能直接去操作 store.state.count +=1,因为这个数据属于 Vuex 统一管理,所以我们要使用 store.commit(‘add’) 去触发 Vuex 中的 mutation 去修改数据。
<template>
<div @click="add">
    {{count}}
</div>
</template>
<script setup>
import { computed } from 'vue'
import {useStore} from 'vuex'
let store = useStore()
let count = computed(()=>store.state.count)
function add(){
    store.commit('add')
}
</script>

在浏览器中打开项目页面,我们就会有一个累加器的效果。相比起来之前用 ref 的方式,真的很简单,这时候小圣就问了我一个问题:什么时候的数据用 Vuex 管理,什么时候数据要放在组件内部使用 ref 管理呢?

答案就是,对于一个数据,如果只是组件内部使用就是用 ref 管理;如果我们需要跨组件,跨页面共享的时候,我们就需要把数据从 Vue 的组件内部抽离出来,放在 Vuex 中去管理。

我再结合例子具体说说:比如项目中的登录用户名,页面的右上角需要显示,有些信息弹窗也需要显示。这样的数据就需要放在 Vuex 中统一管理,每当需要抽离这样的数据的时候,我们都需要思考这个数据的初始化和更新逻辑。

就像下图中,项目初始化的时候没有登录状态,我们是在用户登录成功之后,才能获取用户名这个信息,去修改 Vuex 的数据,再通过 Vuex 派发到所有的组件中。

在这里插入图片描述

3.vuex 实战

Vuex 就是一个公用版本的 ref,提供响应式数据给整个项目使用。现在的功能还比较简单,项目大部分情况都是像之前的清单应用一样,除了简单的数据修改,还会有一些异步任务的触发,这些场景 Vuex 都有专门的处理方式。

在 Vuex 中,你可以使用 getters 配置,来实现 computed 的功能,比如我们想显示累加器数字乘以 2 之后的值,那么我们就需要引入 getters 配置。

下面的代码中,我们实现了计算累加器数字乘以 2 以后的值。我们在 Vuex 中新增了 getters 配置,其实 getters 配置和 Vue 中的 computed 是一样的写法和功能。我们配置了 doubule 函数,用于显示 count 乘以 2 的计算结果。

import { createStore } from 'vuex'
const store = createStore({
  state () {
    return {
      count: 666
    }
  },
  getters:{
    double(state){
          return state.count*2
      }
  },
  mutations: {
    add (state) {
      state.count++
    }
  }
})
export default store

然后,我们可以很方便地在组件中使用 getters,把 double 处理和计算的逻辑交给 Vuex。

let double = computed(()=>store.getters.double)

实际项目开发中,有很多数据我们都是从网络请求中获取到的。在 Vuex 中,mutation 的设计就是用来实现同步地修改数据。如果数据是异步修改的,我们需要一个新的配置 action。现在我们模拟一个异步的场景,就是点击按钮之后的 1 秒,再去做数据的修改。

面对这种异步的修改需求,在 Vuex 中你需要新增 action 的配置,在 action 中你可以做任意的异步处理。这里我们使用 setTimeout 来模拟延时,然后在 action 内部调用 mutation 就可以了。

首先,我们在 createStore 的配置中,新增了 actions 配置,这个配置中所有的函数,可以通过解构获得 commit 函数。内部的异步任务完成后,就随时可以调用 commit 来执行 mutations 去更新数据。

const store = createStore({
  state () {
    return {
      count: 666
    }
  },
  ...
  actions:{
      asyncAdd({commit}){
          setTimeout(()=>{
            commit('add')
          },1000)
      }
  }
})

action 并不是直接修改数据,而是通过 mutations 去修改,这是我提醒你需要注意的。actions 的调用方式是使用 store.dispatch,在下面的代码中你可以看到这样的变化效果:页面中新增了一个 asyncAdd 的按钮,点击后会延迟一秒做累加。

function asyncAdd(){
    store.dispatch('asyncAdd')
}

代码执行的效果如下:
在这里插入图片描述
Vuex 在整体上的逻辑如下图所示,从宏观来说,Vue 的组件负责渲染页面,组件中用到跨页面的数据,就是用 state 来存储,但是 Vue 不能直接修改 state,而是要通过 actions/mutations 去做数据的修改
在这里插入图片描述
下面这个图也是 Vuex 官方的结构图,很好地拆解了 Vuex 在 Vue 全家桶中的定位,我们项目中也会用 Vuex 来管理所有的跨组件的数据,并且我们也会在 Vuex 内部根据功能模块去做拆分,会把用户、权限等不同模块的组件分开去管理。

在这里插入图片描述
由于 Vuex 所有的数据修改都是通过 mutations 来完成的,因而我们可以很方便地监控到数据的动态变化,后面我们可以借助官方的调试工具,非常方便地去调试项目中的数据变化。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

半夏_2021

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值