场景:父页面写了一个用户信息的表格,表格中每一行用户数据对应一个重置密码按钮,点击按钮会弹出对话框。重置密码需要传递用户 id 。
代码如下:
javascript
<a-table>
<template #bodyCell="{ column, record }">
<template v-else-if="column.key === 'action'">
<div class="editable-row-operations">
<a-typography-link type="link" @click="handleResetPasswordModal()">
重置密码
</a-typography-link>
</div>
<ResetPasswordModal
ref="resetPasswordModalRef"
:id="record.id"
:onSuccess="
async () => {
await fetchData()
}"/>
</template>
</template>
</a-table>
坑
子组件定义了 ref ,并且全部都是 resetPasswordModalRef 的同一个组件实例,由于表格中的每一行数据都是循环出来的,在循环中渲染组件时,所有实例共享同一个 ref,导致总是操作最后一个实例。所以传递 id 的时候,总是会传递循环中的最后一个 id 过去,导致子组件总是接收不到对应的 id。
解决方案:
1. 动态设置 ref
- 使用 ref 数组,动态设置 ref,避免所有实例共享一个 ref
html
<template>
<a-table :data-source="data">
<a-column>
<template #default="text, record, index">
{{ record.id }}
<ResetPasswordModal
:ref="(el) => setModalRef(el, index)" <!-- 动态设置ref -->
:id="record.id"
:onSuccess="fetchData"
/>
<a-button @click="handleReset(record, index)">重置密码</a-button>
</template>
</a-column>
</a-table>
</template>
javascript
<script setup lang="ts">
import { ref } from 'vue'
const modalRefs = ref<any[]>([]) // 存储所有模态框的ref
const setModalRef = (el: any, index: number) => {
if (el) {
modalRefs.value[index] = el
}
}
const handleReset = (record: any, index: number) => {
console.log('操作记录:', record.id)
modalRefs.value[index]?.openModal()
}
</script>
2. 单个模态框 + 动态数据(最推荐)
- 父页面
javascript
<template>
<a-table :data-source="data">
<a-column>
<template #default="text, record">
{{ record.id }}
<a-button @click="handleReset(record)">重置密码</a-button>
</template>
</a-column>
</a-table>
<!-- 单个模态框在循环外部 -->
<ResetPasswordModal
ref="resetPasswordModalRef"
:id="currentRecordId"
:onSuccess="fetchData"
/>
</template>
<script setup lang="ts">
import { ref } from 'vue'
const resetPasswordModalRef = ref()
const currentRecordId = ref('')
const handleReset = (record: any) => {
console.log('设置当前记录ID:', record.id)
currentRecordId.value = record.id
resetPasswordModalRef.value?.openModal()
}
</script>
- 子组件
通过 props 接收,略
3. 使用方法传递参数
- 父页面
javascript
<template>
<a-table :data-source="data">
<a-column>
<template #default="text, record">
{{ record.id }}
<a-button @click="handleReset(record.id)">重置密码</a-button>
</template>
</a-column>
</a-table>
<!-- 不传id,完全通过方法参数 -->
<ResetPasswordModal
ref="resetPasswordModalRef"
:onSuccess="fetchData"
/>
</template>
<script setup lang="ts">
import { ref } from 'vue'
const resetPasswordModalRef = ref()
const handleReset = (id: string) => {
console.log('传递ID:', id)
resetPasswordModalRef.value?.openModal(id)
}
</script>
- 子组件
定义一个响应式数据接收 id,略