问题描述:
在弹窗中使用虚拟化选择器渲染表格,打包之后线上浏览该页面卡住,无法加载
TradeProcess.vue:269 [Vue warn]: Maximum recursive updates exceeded in component . This means you have a reactive effect that is mutating its own dependencies and thus recursively triggering itself. Possible sources include component template, render function, updated hook or watcher source function.
描述:
超过了最大递归更新数。这意味着你有一种反应性的效果,它会改变自己的依赖关系,从而递归地触发自己。可能的源包括组件模板、呈现函数、更新的钩子或观察者源函数。
造成这个问题可能的原因:
1.可能是打包之后的样式和开发环境下不一致,导致虚拟化表格计算高度的时候陷入死循环卡住了 。
2.排查页面上的递归函数,死循环,导致页面崩了
解决方法:
一、计算高度时陷入死循环:
刚开始没有手动设置虚拟化表格的width
和height
,而是使用了AutoResizer组件
包裹(该组件会自动更新表格的宽度和高度,默认高度是100%)
子组件是由一个弹窗渲染的且弹窗未给高度,由于虚拟化表格的高度依赖于父组件的高度,而弹窗的高度也是根据它内容的高度来确定的,此时会陷入死循环,导入页面崩溃。
解决思路: 给弹窗设置高度且确保虚拟化表格在渲染前可以计算出高度。
父组件:
1.class="auto-dialog"
给弹窗设置高度
2.@opened="dialogOpened"
在弹窗动画加载后再去加载虚拟化表格
const dialogOpened = () => {
// 用来标记此时弹窗已加载完
state.detailDialogVisible = true;
};
3.style="height: 600px"
给子组件也设置高度
子组件:
1.v-if="state.tableVisible"
监听父组件传递的detailDialogVisible
, 为true
表示弹窗已加载完毕再去渲染虚拟化列表,此时可以确保能获取到弹窗高度。
watch(
() => props.detailDialogVisible,
() => {
if (props.detailDialogVisible) {
state.tableVisible = props.detailDialogVisible;
}
},
{ immediate: true },
);
二、排查页面上的递归函数
按照上面的方式改完发现问题并没有解决,可能存在第二个问题,这个需要根据自己的代码来进行排查。
在此记录一下造成页面崩溃的真正原因!!
为了方便用户,给该虚拟化列表设置了手动滚动的方式,输入数字可以直接滚动到相应行数。
问题:
设置了输入框的最小值为1;最大值取的是接口返回的列表数据的总条数,但是忽略了一个问题,总条数可能为0!所以就有可能情况就是: 最小值为1,最大值为 0
解决方式:
1.设置当总条数大于15条时再添加此效果,可以确保最大值不会比最小值小
2.直接设置最小值为0