Vue.js子组件注入变量初始为undefined,跳转链接id获取失败
Vue组件传值与跳转链接问题排查与修复
问题场景
父组件内通过按钮点击修改selectedReceipt变量,并用provide传递给子组件。子组件通过inject获取变量后,初始值为undefined,但watch监听能正常拿到值;尝试通过链接'printDetails/' + selectedReceipt?.value?.id跳转时,id始终显示undefined。
父组件代码
<script setup> const selectedReceipt = ref([]); provide('selectedReceipt', selectedReceipt); function setSelectedReceipt(receipt){ selectedReceipt.value = receipt; } </script> <template> <tr v-for="(receipt,index) in receipts" :key="index"> <td class="align-middle">{{ index + receipts_Data.from }}</td> <td class="align-middle">{{ receipt.hospitals ? receipt.hospitals.en_name: 'N/A' }}</td> <td class="align-middle">{{ receipt.years ? receipt.years.en_name : 'N/A' }}</td> <td class="align-middle">{{ receipt.months ? receipt.months.month_name : 'N/A' }}</td> <td class="align-middle">{{ receipt.assessment_date }}</td> <td class="align-middle">{{ receipt.maktoob_no }}</td> <td class="align-middle">{{ receipt.maktoob_date }}</td> <td class="align-middle">{{ receipt.description }}</td> <td class="align-middle"> <div class="btn-list"> <AppButton @click="setSelectedReceipt(receipt)" type="outline-primary" btn-sm data-bs-toggle="modal" data-bs-target="#edit_receipts_modal"> <i class="fe fe-edit"></i> </AppButton> <BtnOptions @click="setSelectedReceipt(receipt)" type="outline-primary" btn-sm> <li><a @click="openDetailsModal">Details</a></li> <li><a @click="openStaffModal">Staff</a></li> </BtnOptions> </div> </td> </tr> </template>
子组件代码
<script setup> const selectedReceipt = inject('selectedReceipt'); watch( () => selectedReceipt, async() => { console.log(selectedReceipt.value); master_Filter.value.hospital_id = selectedReceipt.value.hospitals.en_name; master_Filter.value.assessment_date = selectedReceipt.value.assessment_date; master_Filter.value.maktoob_no = selectedReceipt.value.maktoob_no; master_Filter.value.maktoob_date = selectedReceipt.value.maktoob_date; await getDetails(); }, {deep: true }); </script> <template> <template #footer> <button type="reset" form="frm-store" class="btn btn-default btnCloseModal" data-bs-dismiss="modal">{{ Lang.get('Close') }}</button> <AppButton type="btn-primary"> <a :href="'printDetails/' + selectedReceipt?.value?.id">Print</a> </AppButton> </template> </template>
问题原因与修复方案
1. 初始值类型不匹配
父组件中selectedReceipt初始化为数组ref([]),但实际赋值的是单个receipt对象,类型不一致会导致模板中可选链判断失效。
修复:将初始值改为与赋值类型一致的null:
const selectedReceipt = ref(null); provide('selectedReceipt', selectedReceipt);
2. Watch监听逻辑错误
当前监听的是selectedReceipt这个ref对象本身,而非其value属性,虽开启deep: true能触发,但写法不规范且容易引发异常。
修复:直接监听ref对象,并新增空值判断:
watch(selectedReceipt, async (newReceipt) => { if (!newReceipt) return; // 避免初始undefined时执行后续逻辑 console.log(newReceipt); master_Filter.value.hospital_id = newReceipt.hospitals.en_name; master_Filter.value.assessment_date = newReceipt.assessment_date; master_Filter.value.maktoob_no = newReceipt.maktoob_no; master_Filter.value.maktoob_date = newReceipt.maktoob_date; await getDetails(); }, { deep: true });
3. 模板链接的空值安全处理
即使使用可选链,仍需确保selectedReceipt.value.id存在时才渲染按钮,避免生成无效链接。
修复:添加条件渲染:
<template #footer> <button type="reset" form="frm-store" class="btn btn-default btnCloseModal" data-bs-dismiss="modal">{{ Lang.get('Close') }}</button> <AppButton v-if="selectedReceipt?.value?.id" type="btn-primary"> <a :href="'printDetails/' + selectedReceipt.value.id">Print</a> </AppButton> </template>
4. 模态框与状态更新的同步问题
点击Details时,先设置selectedReceipt再打开模态框,若模态框基于DOM操作(如Bootstrap),可能存在子组件未及时更新状态的情况。
修复:使用nextTick等待状态更新后再打开模态框:
// 父组件中修改openDetailsModal方法 import { nextTick } from 'vue'; async function openDetailsModal() { await nextTick(); // 等待Vue完成状态更新和DOM渲染 const modal = new bootstrap.Modal(document.getElementById('你的详情模态框ID')); modal.show(); }
内容的提问来源于stack exchange,提问作者Newbie
相关产品推荐
相关产品推荐

