Vue3引入子组件后beforeMount无限执行问题求助
Vue3 组件引入后无限执行及报错问题排查
问题现象
- 未引入子组件时,
beforeMount钩子仅执行一次,页面正常显示 - 引入子组件后,代码开始无限循环执行,Node控制台重复打印SQL查询日志
- 移除子组件中的动态变量(如
{{ clientArray.clientPhone }})后恢复正常 - Chrome控制台报错:
Uncaught (in promise) TypeError: Cannot read properties of undefined (reading 'length'),对应代码行184:
<tbody v-if="vehicleData && vehicleData.vehicleTask.length"> <tr v-for="Task, index in vehicleData.vehicleTask" :key="Task.id"> <th scope="row" colspan="2">{{ index }}</th> <td colspan="2">{{ Task.title }}</td> </tr> </tbody>
涉及代码
父组件
<div class="modal fade" id="exampleModal" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true"> <div class="modal-dialog modal-xl modal-dialog-centered modal-dialog-scrollable"> <div class="modal-content"> <div class="modal-header"> <h1 class="modal-title fs-5" id="exampleModalLabel">预查看工单</h1> <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="关闭"></button> </div> <div class="modal-body"> <DevizView :clientArray="clientData" :vehicleArray="vehicleData"/><!-- 子组件 --> </div> <div class="modal-footer"> <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">关闭</button> <button type="button" class="btn btn-primary">保存更改</button> </div> </div> </div> </div> <script> import axios from "@/axios"; import DevizView from "@/views/Test.vue"; export default { props: { id: { type: Number, required: true, }, }, data() { return { vehicleData: [], clientData: [] } }, components: { DevizView }, methods: { async GetVehicleDetails() { await axios.post('http://localhost:3000/vehicle/GetVehicleDetails', {id:this.id}) .then((res)=>{ this.vehicleData = res.data; // 将字符串化的JSON解析为真实对象 try { this.vehicleData.vehicleTask = JSON.parse(this.vehicleData.vehicleTask); } catch (error) { console.error('解析vehicleTask JSON失败:', error); } }).catch(err=>console.log(err)) return this.vehicleData }, async GetCustomerDetails() { await axios.post('http://localhost:3000/customer/GetCustomerDetails', {id:this.vehicleData.clientId}) .then((res)=>{ this.clientData = res.data; }).catch(err=>console.log(err)) return this.clientData }, }, beforeMount(){ this.GetVehicleDetails().then(() => { this.GetCustomerDetails(); }); } }; </script>
子组件
<div class="table-responsive"> <table class="table table-sm caption-top"> <caption><strong>客户/车辆信息</strong></caption> <tbody> <tr> <th class="table-secondary">姓名</th> <td colspan="3">{{ clientArray.clientName }}</td> </tr> <tr> <th class="table-secondary">电话</th> <td>{{ clientArray.clientPhone }}</td> <th class="table-secondary">邮箱</th> <td>{{ clientArray.clientEmail }}</td> </tr> <tr> <th class="table-secondary">入库日期:</th> <td>{{ vehicleArray.vehicleEnterDate }}</td> <th class="table-secondary">出库日期:</th> <td></td> </tr> </tbody> </table> </div>
问题原因及解决方案
1. 初始值类型不匹配
父组件中vehicleData和clientData初始值设为数组[],但接口返回的是对象。子组件渲染时访问对象属性,初始数组无对应属性会触发警告,引发不必要的重渲染。
- 修复:将初始值改为空对象
{}:
data() { return { vehicleData: {}, clientData: {} } }
2. 异步加载期间的空值访问
接口返回前子组件已开始渲染,vehicleData.vehicleTask可能为undefined,读取length时报错。报错触发组件重渲染,进而重复调用接口,形成无限循环。
- 修复:
- 使用可选链操作符优化模板判断:
v-if="vehicleData?.vehicleTask?.length" - 解析JSON时设置默认值,避免
vehicleTask为undefined:try { this.vehicleData.vehicleTask = JSON.parse(this.vehicleData.vehicleTask) || []; } catch (error) { console.error('解析vehicleTask JSON失败:', error); this.vehicleData.vehicleTask = []; // 解析失败时设为空数组 }
- 使用可选链操作符优化模板判断:
3. 子组件未声明Props
子组件直接使用clientArray和vehicleArray但未声明Props,Vue会将其视为隐式属性,导致重渲染逻辑异常。
- 修复:子组件添加Props声明:
<script> export default { props: { clientArray: { type: Object, default: () => ({}) }, vehicleArray: { type: Object, default: () => ({}) } } } </script>
4. 异步流程简化
将beforeMount中的嵌套异步调用改为async/await写法,提升可读性:
async beforeMount() { await this.GetVehicleDetails(); await this.GetCustomerDetails(); }
内容的提问来源于stack exchange,提问作者Mina Dominic
相关产品推荐
相关产品推荐

