Vue3组合式API:父组件设置子组件对象及弹窗问题求助
Vue3+Vuetify弹窗问题修复
问题概述
- 点击「Add User」链接无法打开弹窗
- 点击用户链接打开弹窗后,表单无法填充用户属性
修复步骤
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
相关产品推荐
相关产品推荐

