Skip to content

标题备选

  1. Vue 实战基础:Vuex,关键知识点一次梳理
  2. 手把手梳理 Vuex:从概念到项目使用
  3. Vuex 学不顺?先把这些基础点打通

摘要

这篇文章适合 Vue 技术栈学习者,围绕「Vuex」整理关键概念、使用步骤和项目实践要点,方便复习和实战对照。

正文

哈喽大家好👋 我是程序🦍kk。把复杂知识掰成大白话讲明白,是我一直以来的小追求✨;打好基础才能稳步进阶,是我始终秉持的学习理念~

📢 我搭建了5000人程序猿专属学习交流群 群内会同步前端开发/全栈开发/Web3开发/远程工作等干货资源 关注我并回复 加群 ,就能加入交流圈啦🚀

前言

Vue 技术栈看起来上手快,但真正写项目时,基础概念一定要稳。

组件通信、状态管理、工程配置这些知识点,单独看都不复杂,串到项目里就很容易混。

这篇围绕「Vuex」做一次结构化整理,适合大家复习时对照查看。

知识点整理

下面进入正文。建议大家边看边对照自己的项目结构,很多知识点放到组件里会更好理解。

如果你现在维护的是 Vue 项目,可以对照看一下组件通信和状态管理是否已经形成固定写法。

vuex是什么?

vuex是一种项目中数据共享的方式。

vuex

其具有以下优势:

  • 能够在vuex中集中管理共享的数据,便于开发和后期进行维护
  • 能够高效的实现组件之间的数据共享,提高开发效率(代码量
  • 存储在vuex中的数据是响应式的,当数据发生改变时,页面中的数据也会同步更新

什么样的数据适合存储在Vuex中?

一般情况下,只有组件之间共享的数据才有必要存储到vuex中,对于组件中私有的数据依旧存储在组件自身的data中即可。

vuex的安装及配置

vuex不是脚手架在安装项目的时候自带的,是一个选配的功能,默认是不被安装的(需要自己根据需要选择)。因此其安装和配置存在两种情况:

情况1:在通过vue脚手架vue create xxxx的命令的时候,手动选择安装vuex【极力推荐】。好处在于不需要自己手动创建store目录及目录下的index.js文件。

情况2:在通过vue脚手架vue create xxxx的命令的时候,可能没有选择安装vuex,则这个时候我们有两种选择:

  • 删了重来,再建立项目的时候选择安装vuex
  • 当然也可以通过命令来补救安装,但是通过命令后续安装的vuex,需要自己创建store目录和其下的index.js文件
    • npm i -S vuex

vuex核心

state:提供唯一公共数据源,所有的共享数据都要统一放到state中进行存储

javascript
// 在组件中访问state数据的第一种方式(单个)
this.$store.state.全局数据名称
javascript
// 在组件中访问state数据的第二种方式(批量)
// 按需导入mapState函数
import {mapState} from 'vuex'
// 将全局函数映射为当前组件的计算属性
computed: {
    ...mapState(['count'])
}

第二种方式映射过来的情况,其数据的使用方式如同在当前组件中使用自身的data数据一样(下同)

  • 在视图中,就直接插值表达式
  • 在js中就this.xxxx

mutation(s):用于变更store中的数据(修改)

  • 在Vuex中只能通过mutation变更store中的数据,不可以直接操作store中的数据
  • 通过这种方式操作起来稍微繁琐一些,但是可以集中监控所有数据的变化
javascript
// 定义mutations
const store = new Vuex.Store({
    state: {
        count: 0
    },
    mutations: {
        add(state[,arg]){
            // 变更状态
            state.count++
        }
    }
})
javascript
// 组件中触发mutation的第一种方式
methods:{
    handle(){
        this.$store.commit('add'[,arg])
    }
}
javascript
// 组件中触发mutation的第二种方式
import {mapMutations} from 'vuex'
methods:{
    ...mapMutations(['add','reduce']),
    handle1(){
        this.add()
    },
    handle2(){
        this.reduce([arg])
    }
}

==不要在mutation中写异步的代码==

在mutation中混合异步调用会导致你的程序很难调试。每个mutation执行完成后都会对应到一个新的状态变更,这样devtools就可以打个快照存下来,然后就可以实现 time-travel 了。如果mutation支持异步操作,就没有办法知道状态是何时更新的,无法很好的进行状态的追踪,给调试带来困难

action(s):用于处理==异步==操作任务

javascript
// 声明action
const store = new Vuex.Store({
    // 省略其他代码
    mutations: {
        add(state){
            state.count++
        }
    },
    actions: {
        addAsync(context[,arg]){
            setTimeout(() => {
                context.commit('add'[,arg])
            },1000)
        }
    }
})
javascript
// 组件中触发action
methods: {
    handle(){
        this.$store.dispach('addAsync'[,arg])
    }
}

action也是支持如同state、mutation一样的按需导入mapActions方式进行触发。

getter(s):对store中已有的数据加工处理形成新的数据

  • 对已有的数据进行加工除了,类似于Vue的计算属性
  • store数据发生变化,则getter中的数据也会跟着变化
javascript
// 定义getter
....
getters: {
    showNum: state => {
        return '当前最新的数量是【' + state.count + '】'
    }
}
javascript
// 在组件中访问getters数据的第一种方式
this.$store.getters.全局数据名称
javascript
// 在组件中访问getters数据的第二种方式
// 按需导入mapGetters函数
import {mapGetters} from 'vuex'
// 将全局函数映射为当前组件的计算属性
computed: {
    ...mapGetters(['showNum'])
}

模块化

  • 为什么有状态的模块化?

    • 主要是因为项目是多人协作开发的,如果都去修改一个文件,则经常会出现代码冲突,而解决冲突比较费事费力。
  • 使用步骤

    • 建立src/store/modules文件夹(名称随意)
    • 在modules文件夹中建立需要的模块文件(命名以功能为导向,记得导出一下)
  • 注意点1(了解):

    • 在模块的时候,因为多人合作,不能的开发者之前并不清楚其他怎么给方法和数据源进行命名,这样的话就有一个问题:万一名称重名怎么办?如果冲突了,会执行以下合并策略:
      • state数据源肯定不会冲突,它以模块进行保存
      • mutations、actions的方法不会以模块为单位进行保存,如果出现同名则可能会冲突。vuex会先将这些同名的方法,整合到一起,都去执行。会先执行index.js中的,再去执行其他的。
      • getters如果出现冲突,不给解决,直接报错。
    • 因为多人合作可能出现命名的冲突,特别针对getters,vuex模块化的时候支持使用命名空间
      • 默认是没有给模块开启命名空间的
      • 如果需要请自己开启,通过模块对象的属性“namespaced”,将其值设置为true
      • 命名空间的名称,是模块的名字(模块里面属性的名字)
  • 注意点2:由于模块使用了命名空间,所以之前没有模块化的使用方式(this、map系列)在模块化之后都要发生对应的变化

    • state
      • this形式:this.$store.state.空间名.xxxx
      • map系列:...mapSate(空间名,[xxxx,yyyy,zzzz...])
    • mutations
      • this形式:this.$store.commit("空间名/方法名", "参数");
      • map系列:...mapMutations("空间名",["方法名",...]),
    • actions
      • this形式:this.$store.dispatch("空间名/方法名", "参数");
      • map系列:...mapActions("空间名",["方法名",...]),
    • getters
      • this形式:this.$store.getters["空间名/属性名"]
      • map形式:...mapActions("空间名", ["属性名",....]),

写在最后

好啦,今天的分享就到这里!

💬 互动时间:

你现在项目里更常用 Vue2 还是 Vue3?如果想看组件通信、Vuex/Pinia 或工程化配置的实战拆解,可以留言。

最后,感谢你看到这里👏

如果喜欢这篇内容,不妨顺手给小编安排一波👇 点赞👍|转发📲|推荐❤️|评论📣

要是想第一时间蹲到新内容推送,记得给我点个星标⭐️

更多干货内容正在持续填坑中,咱们下期见👋

标签建议

Vue、前端、前端基础