Vue 组件中获取 Vuex state 数据的三种核心方式

这段代码展示了 Vue 组件中获取 Vuex state 数据的三种核心方式,核心差异在于「响应式表现」「数据更新机制」「适用场景」,

下面逐一拆解每种方式的原理、特点和为什么会有这些区别:

html 复制代码
<template>
  <div class="about">
    <h2>直接取的</h2>
    <!--方式1: 直接取-->
    <p>取出Vuex的数据,user: {{this.$store.state.user}}</p>
    <p>取出Vuex的数据,token: {{this.$store.state.token}}</p>
    <hr>
    <h2>data中获取的</h2>
    <!--方式2: 在data中获取-->
    <p>取出Vuex的数据,user: {{user}}</p>
    <p>取出Vuex的数据,token: {{token}}</p>
    <hr>
    <h2>调用mutations中的方法修改token</h2>
    <input type="text" v-model="newToken">
    <button @click="changeToken">修改token</button>
    <h2>计算属性中获取的</h2>
    <p>取出Vuex的数据,token: {{token2}}</p>
  </div>
</template>
<script>
export default {
  name: 'AboutView',
  data() {
    return {
      // 可以在data中直接获取Vuex中的数据
      user: this.$store.state.user,
      // token: this.$store.state.token,
      newToken:''
    }
  },
  // 建议使用计算属性取出Vuex的数据,而不是data
  computed:{
    token2(){
      return this.$store.state.token
    }
  }
  ,
  methods: {
    changeToken(){
      // 调用mutations中的方法,修改token
      // this.$store.commit("mutations中定义的方法名", "调用时传递的参数")
      this.$store.commit("setToken", this.newToken)
    }
  }
}
</script>

一、方式 1:模板中直接取 this.$store.state.xxx

写法 html

javascript 复制代码
<p>取出Vuex的数据,user: {{this.$store.state.user}}</p>
核心原理

模板渲染时实时访问 Vuex 的 state 对象属性 ------Vuex 的 state 本身是响应式的,模板每次渲染 / 更新都会重新读取 $store.state.xxx 的最新值。

关键特点
  1. 完全响应式 :当 state 中的 user/token 被修改(比如通过 mutation),模板会立刻同步更新;
  2. 无缓存 :每次模板重渲染都会重新读取 state(性能影响可忽略,除非高频渲染);
  3. 语法简单但冗余 :直接写 this.$store.state.xxx 直观,但多次使用会导致模板代码臃肿,维护性差。
适用场景
  • 临时调试、快速验证数据;
  • 只在模板中少量使用 state 数据的简单场景。
为什么能实时更新?

Vuex 的 state 是基于 Vue 的响应式对象实现的,模板中访问 $store.state.xxx 会触发 Vue 的「依赖收集」,当 state 数据变化时,Vue 会通知模板重新渲染。

二、方式 2:在 data 中获取 this.$store.state.xxx

写法 js

javascript 复制代码
data() {
  return {
    user: this.$store.state.user, // 初始化时赋值
    newToken:''
  }
}
核心原理

data 中的属性在组件实例化时(beforeCreate/created 阶段)只赋值一次 ------ 把当时 $store.state.user 的「初始值」拷贝给 data.user,后续 state 变化不会同步到 data.user

关键特点
  1. 非响应式 :这是最核心的问题!比如通过 changeToken 修改了 state.token,但 data 中如果定义了 token: this.$store.state.token,模板里的 {``{token}} 永远是初始化的旧值,不会更新;
  2. 数据是 "拷贝"data.user 只是拿到了 state.user 初始化时的取值(如果是基本类型,是值拷贝;如果是引用类型,是地址拷贝,但 state 本身的响应式不会传递给 data 的属性);
  3. 模板写法简洁 :模板中只需写 {``{user}},无需写冗长的 $store.state
为什么不推荐?

data 的设计初衷是存储「组件自身的局部状态」,其初始化逻辑只执行一次,无法感知 Vuex state 的后续变化 ------ 这会导致 "数据不一致" 的 bug(比如 state 改了,但组件显示的还是旧值)。

适用场景

几乎不推荐使用 ,除非能 100% 确定 state 中的该数据在组件生命周期内永远不会变化(比如静态常量)。

三、方式 3:在 computed(计算属性)中获取 this.$store.state.xxx

重要用法: 一般从state中取出的数据要放在computed中而不是data中!

写法 js

javascript 复制代码
computed:{
  token2(){
    return this.$store.state.token
  }
}
核心原理

计算属性会「依赖收集」------ 它会监听 this.$store.state.token 的变化,当 state.token 被修改时,计算属性会自动重新计算返回最新值,并触发模板更新。同时,计算属性有「缓存特性」:只要依赖的 state.token 不变,多次访问 token2 只会执行一次计算。

关键特点
  1. 完全响应式state.token 变化,token2 会同步更新,模板也会跟着更;
  2. 有缓存 :提升性能(比如多次在模板中用 {``{token2}},不会重复读取 state);
  3. 模板简洁 + 可维护 :模板写 {``{token2}} 即可,且计算属性可以集中管理 state 数据的读取逻辑(比如后续需要对 token 做格式化,只需改计算属性,无需改所有模板);
  4. 支持扩展 :可以在计算属性中对 state 数据做派生 / 格式化(比如 return this.$store.state.token || '默认值')。
为什么是最佳实践?

计算属性完美结合了「响应式」和「简洁性」,既解决了直接取值的模板冗余问题,又避免了 data 取值的非响应式坑,同时还能通过缓存优化性能。

三种方式核心对比表

方式 响应式 缓存 模板简洁度 维护性 推荐度
模板直接取 $store.state ✅ 是 ❌ 无 ❌ 冗余 ⭐⭐
data 中赋值 ❌ 否 ❌ 无 ✅ 简洁 极差
computed 中取值 ✅ 是 ✅ 有 ✅ 简洁 ⭐⭐⭐

补充:修改 state 的逻辑(changeToken 方法)

代码中 changeToken 调用 this.$store.commit("setToken", this.newToken) 是 Vuex 规定的唯一合法修改 state 的方式(通过 mutation),这和 "取值方式" 的呼应:

  • 不管用哪种方式取值,只要通过 mutation 修改了 state.token
    • 方式 1、方式 3 会实时更新;
    • 方式 2 永远不会更新(因为是初始化一次的拷贝)。

总结

  • 临时调试用「模板直接取」;
  • 绝对不要用「data 中取值」(除非数据永不改);
  • 正式开发优先用「计算属性取值」(响应式、高性能、易维护);
  • 进阶优化:还可以用 Vuex 提供的 mapState 辅助函数简化计算属性写法(比如 ...mapState(['user', 'token'])),进一步减少代码冗余。
相关推荐
Hashan37 分钟前
基于Vue3完成动态组件库建设
前端
想要成为糕糕手37 分钟前
JavaScript 面向对象编程:从构造函数到原型继承的完整指南
javascript
北辰alk37 分钟前
Vue动态组件:让组件“活”起来的终极指南
vue.js
李慕婉学姐37 分钟前
【开题答辩过程】以《基于Springboot和Vue的生活垃圾识别与处理系统》为例,不知道这个选题怎么做的,不知道这个选题怎么开题答辩的可以进来看看
vue.js·springboot
爱吃香菜i39 分钟前
基于Vant的移动端公共选人/选部门组件设计文档
前端
Jingyou42 分钟前
JavaScript 封装无感 token 刷新
前端·javascript
想要成为糕糕手43 分钟前
从零实现一个健壮可复用的“就地编辑”组件:深入剖析 OOP、DOM 与事件机制
javascript
quan26311 小时前
20251204,vue列表实现自定义筛选和列
前端·vue.js·elementui
蜗牛攻城狮1 小时前
JavaScript `Array.prototype.reduce()` 的妙用:不只是求和!
前端·javascript·数组