版本
"dependencies":{"pinia":"^3.0.4","vue":"^3.5.26"},"devDependencies":{"@vitejs/plugin-vue":"^6.0.3","vite":"^7.3.1","vite-plugin-vue-devtools":"^8.0.5"},"engines":{"node":"^20.19.0 || >=22.12.0"}代码
user.js
import{defineStore}from'pinia';exportconstuseUserStore=defineStore('userStore',{actions:{changeUsername(value){if(value&&value.length<10){this.username+=value}}},getters:{getUsername(){returnthis.username.toUpperCase()}},state:()=>({username:'abc'}),})App.vue
<script setup>import{useUserStore}from'@/store/user'import{storeToRefs}from'pinia';import{ref,toRef,toRefs}from'vue';constuser=useUserStore()// 错误constuserInfo=storeToRefs(user)console.log(userInfo.username)// 正确const{username}=storeToRefs(user)console.log(username)</script><template><!--错误--><div>{{userInfo.username}}</div><input type="text"v-model="userInfo.username"><!--正确--><div>{{username}}</div><input type="text"v-model="username"></template>现象
分析
原因
👉问题不是出在storeToRefs,而是出在你“把一个 ref 对象当成普通值来用”的心智模型上。[object Object]说明input 绑定到的不是字符串,而是一个对象。
关键点:storeToRefs返回的是什么?
constuserInfo=storeToRefs(user)此时:
userInfo={username:Ref<string>}也就是说:
userInfo.username→是一个 ref 对象userInfo.username.value→ 才是真正的字符串"abc"
那为什么模板里会出现[object Object]?
表面看很迷惑,因为你写的是:
<input v-model="userInfo.username">但v-model只能直接绑定:
- 普通变量
- 或单个
ref
❌ 它不擅长绑定「对象里的 ref」
在这种情况下,Vue 会把整个Ref当成值塞进 input,于是:
String(Ref) → [object Object]为什么很多教程让你这样写?
const{username}=storeToRefs(user)因为这样:
username===Ref<string>这是一个干净的 ref,非常适合v-model
✅ 正确、推荐写法(重点)
App.vue
<script setup> import { useUserStore } from '@/store/user' import { storeToRefs } from 'pinia' const user = useUserStore() const { username } = storeToRefs(user) </script> <template> <div>{{ username }}</div> <input type="text" v-model="username" /> </template>这和你原来的代码真正的区别
| 你的写法 | 推荐写法 |
|---|---|
userInfo.username | username |
| 对象里的 ref | 单独的 ref |
v-model易出坑 | v-model官方推荐 |
为什么{{ userInfo.username }}有时“看起来能用”?
因为:
- 插值表达式会自动解包 ref
- 但
v-model在对象嵌套 ref 的场景下不会稳定解包
所以你会看到一个很典型的新手陷阱:
显示正常,但 input 变成
[object Object]
总结一句好记的
storeToRefs之后,一定要解构再用v-model
❌v-model="obj.xxx"
✅const { xxx } = storeToRefs(store)
如果你愿意,我可以顺手帮你把
getteractionv-model + 业务校验
整理成一个标准 Pinia 表单写法模板👌