【vue】pinia中的值使用 v-model绑定出现[object Object]

版本

javascript 复制代码
  "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

javascript 复制代码
import { defineStore } from 'pinia';

export const useUserStore = defineStore('userStore', {
    actions: {
        changeUsername(value) {
            if(value && value.length<10) {
                this.username += value
            }
        }
    },
    getters: {
        getUsername() {
            return this.username.toUpperCase()
        }
    },
    state: () => ({
        username: 'abc'
    }),
})

App.vue

javascript 复制代码
<script setup>
import { useUserStore } from '@/store/user'
import { storeToRefs } from 'pinia';
import { ref, toRef, toRefs } from 'vue';

  const user = useUserStore()
  
  // 错误
  const userInfo = 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 返回的是什么?

js 复制代码
const userInfo = storeToRefs(user)

此时:

js 复制代码
userInfo = {
  username: Ref<string>
}

也就是说:

  • userInfo.username是一个 ref 对象
  • userInfo.username.value → 才是真正的字符串 "abc"

那为什么模板里会出现 [object Object]

表面看很迷惑,因为你写的是:

vue 复制代码
<input v-model="userInfo.username">

v-model 只能直接绑定:

  • 普通变量
  • 或单个 ref

❌ 它不擅长绑定「对象里的 ref」

在这种情况下,Vue 会把整个 Ref 当成值塞进 input,于是:

复制代码
String(Ref) → [object Object]

为什么很多教程让你这样写?

js 复制代码
const { username } = storeToRefs(user)

因为这样:

js 复制代码
username === Ref<string>

这是一个干净的 ref ,非常适合 v-model


✅ 正确、推荐写法(重点)

App.vue

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)

如果你愿意,我可以顺手帮你把

  • getter
  • action
  • v-model + 业务校验
    整理成一个标准 Pinia 表单写法模板 👌
相关推荐
之歆10 小时前
DAY_12JavaScript DOM 完全指南(二):实战与性能篇
开发语言·前端·javascript·ecmascript
Maimai1080810 小时前
React如何用 @microsoft/fetch-event-source 落地 SSE:比原生 EventSource 更灵活的实时推送方案
前端·javascript·react.js·microsoft·前端框架·reactjs·webassembly
candyTong10 小时前
Claude Code 的 Edit 工具是怎么工作的
javascript·后端·架构
卡卡军13 小时前
agmd 1.0 重磅升级——Rust 重写,性能起飞
javascript·rust
Larcher13 小时前
🔥 告别抓瞎:用 Claude Code (cc) 优雅接手与维护已有项目
javascript·机器学习·前端框架
JYeontu13 小时前
轮播图不够惊艳?试下这个立体卡片轮播图
前端·javascript·css
亲亲小宝宝鸭13 小时前
如何监听DOM尺寸的变化?element-resize-detector 和 resizeObserver
前端·javascript
代码煮茶13 小时前
Vite 5.0 新特性深度解析:更快、更干净、更未来的前端构建利器
vue.js
卷帘依旧16 小时前
Generator 全面解析 + async/await 深度对比
前端·javascript
weixin_4713830316 小时前
统一缩放单位基础(px、em、rem)
开发语言·javascript·ecmascript