这段代码展示了 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的最新值。关键特点
- 完全响应式 :当
state中的user/token被修改(比如通过 mutation),模板会立刻同步更新;- 无缓存 :每次模板重渲染都会重新读取
state(性能影响可忽略,除非高频渲染);- 语法简单但冗余 :直接写
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。关键特点
- 非响应式 :这是最核心的问题!比如通过
changeToken修改了state.token,但data中如果定义了token: this.$store.state.token,模板里的{``{token}}永远是初始化的旧值,不会更新;- 数据是 "拷贝" :
data.user只是拿到了state.user初始化时的取值(如果是基本类型,是值拷贝;如果是引用类型,是地址拷贝,但state本身的响应式不会传递给data的属性);- 模板写法简洁 :模板中只需写
{``{user}},无需写冗长的$store.state。为什么不推荐?
data的设计初衷是存储「组件自身的局部状态」,其初始化逻辑只执行一次,无法感知 Vuexstate的后续变化 ------ 这会导致 "数据不一致" 的 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只会执行一次计算。关键特点
- 完全响应式 :
state.token变化,token2会同步更新,模板也会跟着更;- 有缓存 :提升性能(比如多次在模板中用
{``{token2}},不会重复读取state);- 模板简洁 + 可维护 :模板写
{``{token2}}即可,且计算属性可以集中管理state数据的读取逻辑(比如后续需要对token做格式化,只需改计算属性,无需改所有模板);- 支持扩展 :可以在计算属性中对
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'])),进一步减少代码冗余。