为v-dialog添加v-model后数组元素传递异常问题排查
问题描述
我有一个apps数组,每个app对象都包含link字段,同时自定义了Dialog组件。给v-dialog添加v-model="dialog"后出现异常:激活器模板里显示的当前app的link是正确的,但传递给Dialog组件的app始终是数组最后一个元素。
问题原因
所有对话框共用了同一个dialog状态变量。当点击任意激活器打开对话框时,所有对话框的v-model都会响应这个变量的变化而显示,但此时循环已经执行完毕,app变量指向数组最后一个元素,导致对话框内容全部渲染最后一个app的数据。
解决方案
给每个对话框分配独立的状态,而非共用一个变量。推荐直接给每个app对象添加isDialogOpen属性,用来控制对应对话框的显示/隐藏:
修改后的代码
父组件
<v-col v-for="app in apps" :key="app._id" :cols="setBreakpointCols"> <v-card class="pa-2" outlined height="230px"> <!-- 用当前app的isDialogOpen控制对话框状态 --> <v-dialog v-model="app.isDialogOpen"> <template v-slot:activator="{ on: dialog, attrs }"> <v-tooltip right color="#363636" max-width="250px"> <template v-slot:activator="{ on: tooltip }"> <v-img :src="getImgUrl(app.src)" class="white--text align-end" gradient="to bottom, rgba(0,0,0,.5), rgba(0,0,0,.5)" height="85%" v-bind="attrs" v-on="{ ...tooltip, ...dialog }"> <v-card-title v-text="app.title"></v-card-title> </v-img> </template> <span v-if="app.vpnRequired">VPN needed to run!</span> <v-divider class="my-1" v-if="app.vpnRequired" dark></v-divider> <span>{{ app.description }}</span> </v-tooltip> <h1>{{app.link}}</h1> </template> <h1>{{app.link}}</h1> <!-- 关闭时触发修改当前app的isDialogOpen状态 --> <Dialog @closeDialog="app.isDialogOpen = false" :app="app" /> </v-dialog> <v-card-actions mb-2> <v-spacer></v-spacer> <v-tooltip top color="#363636"> <template v-slot:activator="{ on, attrs }" v-if="app.quickActions"> <v-btn @click="DeleteAppFromQuickActions(app)" icon> <v-icon v-bind="attrs" v-on="on"> mdi-minus-box-outline </v-icon> </v-btn> </template> <template v-slot:activator="{ on, attrs }" v-else> <v-btn @click="AddAppToQuickActions(app)" icon> <v-icon v-bind="attrs" v-on="on"> mdi-plus-box-outline </v-icon> </v-btn> </template> <span v-if="app.quickActions">Delete from QuickActions</span> <span v-else>Add to QuickActions</span> </v-tooltip> <v-spacer></v-spacer> </v-card-actions> </v-card> </v-col>
子组件(无需修改)
<template> <v-container fluid> <v-row> <v-col fixed style="background:#363636;" class="d-flex justify-end" cols="12"> <v-btn plain color="grey" :href="app.link" target="_blank"> <v-icon>mdi-open-in-new</v-icon> </v-btn> <v-btn @click="closeDialog" plain color="grey"> <v-icon>mdi-close-box-outline</v-icon> </v-btn> </v-col> <v-col cols="12"> <iframe :src="app.link" width="100%" height="800px" frameborder="0"> </iframe> </v-col> </v-row> </v-container> </template> <script> export default { name: "Dialog", props: ['app'], methods: { closeDialog() { this.$emit('closeDialog') } } } </script>
内容的提问来源于stack exchange,提问作者senadk
相关产品推荐
相关产品推荐

