You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Vue3组合式API:父组件设置子组件对象及弹窗问题求助

Vue3+Vuetify弹窗问题修复

问题概述

  1. 点击「Add User」链接无法打开弹窗
  2. 点击用户链接打开弹窗后,表单无法填充用户属性

修复步骤

1. 修复UserList.vue

问题点:

  • Add User链接的点击事件写错成@onclick,应为@click
  • 静态传递user="null"是字符串而非null值,且子组件props要求必填导致报错
  • 直接给ref实例赋值userform.user = user无效,props需通过响应式变量绑定

修改后代码:

<script setup>
import { ref } from 'vue'
import { store } from '../services/store.js'
import UserForm from './UserForm.vue'

const userform = ref(null)
const currentUser = ref(null) // 新增响应式变量存储当前操作的用户

const openDialog = (user) => {
  currentUser.value = user || {} // 新增用户时传空对象避免props报错
  userform.value.openDialog()
}
</script>

<template>
  <table>
    <thead>
    <tr>
      <th>Users</th>
    </tr>
    </thead>
    <tbody>
    <tr v-for="user in store.state.users" :key="user.id">
      <td><a href="javascript:;" @click="openDialog(user)">{{ user.firstName }} {{ user.lastName }}</a></td>
    </tr>
    </tbody>
    <tfoot>
    <tr>
      <td colspan="2" class="text-center" style="padding:20px 0">
        <a href="javascript:;" @click="openDialog(null)">Add User</a> <!-- 修正@onclick为@click -->
        <UserForm :user="currentUser" ref="userform"></UserForm> <!-- 绑定响应式变量currentUser -->
      </td>
    </tr>
    </tfoot>
  </table>
</template>

2. 修复UserForm.vue

问题点:

  • props中user设置为required: true,新增用户时传null会触发报错
  • props定义错误:openDialog被定义为Boolean类型,实际是要暴露的方法
  • 直接绑定props.user.firstName存在响应式问题,且当user为null时会报错

修改后代码:

<script setup>
import { ref, toRefs } from 'vue'

const dialog = ref(false)
const props = defineProps({
  user: {
    type: Object,
    required: false, // 改为非必填
    default: () => ({}) // 默认空对象,避免v-model报错
  }
})

// 解构props并保持响应式
const { user } = toRefs(props)

const save = () => {
  console.log('saving', user.value)
  dialog.value = false
}
const openDialog = () => {
  dialog.value = true
}

const emits = defineEmits(['save'])
defineExpose({
  openDialog
})
</script>

<template>
  <form>
    <v-row justify="center">
      <v-dialog v-model="dialog" persistent width="1024">
        <template v-slot:activator="{ props }"></template>
        <v-card>
          <v-card-title>
            <span class="text-h5">{{ user.id ? 'Edit User' : 'Add User' }}</span> <!-- 动态切换标题 -->
          </v-card-title>
          <v-card-text>
            <v-container>
              <v-row>
                <v-col cols="12" lg="4" sm="4" xs="12">
                  <v-text-field
                    label="First name*"
                    required
                    v-model="user.firstName"
                  ></v-text-field>
                </v-col>
                <v-col cols="12" lg="4" sm="4" xs="12">
                  <v-text-field
                    label="Middle name"
                    hint="example of helper text only on focus"
                  ></v-text-field>
                </v-col>
                <v-col cols="12" lg="4" sm="4" xs="12">
                  <v-text-field
                    label="Last name"
                    hint="example of helper text only on focus"
                    v-model="user.lastName"
                  ></v-text-field>
                </v-col>
              </v-row>
              <!-- 其他表单字段保留原结构 -->
            </v-container>
            <small>*indicates required field</small>
          </v-card-text>
          <v-card-actions>
            <v-spacer></v-spacer>
            <v-btn color="blue-darken-1" variant="text" @click="dialog = false">
              Close
            </v-btn>
            <v-btn class="ma-2" color="primary" @click="save">
              <v-icon start icon="mdi-checkbox-marked-circle"></v-icon>
              Save
            </v-btn>
          </v-card-actions>
        </v-card>
      </v-dialog>
    </v-row>
  </form>
</template>

3. 可选:完善store.js的用户操作逻辑

如果需要实现保存用户的功能,可在store中添加对应方法:

import { reactive } from 'vue'

class Store{
    constructor() {
        this.state = reactive({
            users: [
                { id: 1, firstName: "John", lastName: "Smithers" },
                { id: 2, firstName: "Mary", lastName: "Smithers"}
            ],
            currentUserId: null
        })
    }
    
    addUser(user){
        const newId = Math.max(...this.state.users.map(u => u.id)) + 1
        this.state.users.push({ id: newId, ...user })
    }
    
    updateUser(updatedUser){
        const index = this.state.users.findIndex(u => u.id === updatedUser.id)
        if(index !== -1){
            this.state.users[index] = updatedUser
        }
    }
}

export const store = new Store()

随后在UserForm的save方法中调用store方法:

const save = () => {
  if(user.value.id){
    store.updateUser(user.value)
  } else {
    store.addUser(user.value)
  }
  dialog.value = false
  emits('save')
}

内容的提问来源于stack exchange,提问作者geoff swartz

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 22:49:59