今天记录一个前端异常:Cannot read properties of null (reading 'insertBefore')
网上说导致这个问题的原因很多,实际上就是因为渲染子节点时父节点已经被移除导致的异常。
我遇到的是项目中使用 vue antd 和 element plus ,配置了全局配置组件导致的错误。
这个问题在开发环境下一切正常,但是一旦打包上生产环境,则出现报错。
报错写法如下:
vue
<div class="application" style="attr">
<div class="app-main">
<a-config-provider :locale="locale"
:theme="{
token: theme,
}">
<el-config-provider :locale="i18n.global.locale === 'zh-cn' ? zhCnElement : enusElement">
<a-watermark v-bind="themeStore.watermark">
<router-view></router-view>
</a-watermark>
</el-config-provider>
</a-config-provider>
</div>
</div>
组件 a-config-provider 和 el-config-provider 不能直接嵌套 router-view 或者组件,需要包裹一个 div
调整结构为如下后解决问题
vue
<template>
<a-config-provider :locale="locale"
:theme="{
token: theme,
}">
<el-config-provider :locale="i18n.global.locale === 'zh-cn' ? zhCnElement : enusElement">
<div class="application" style="attr">
<div class="app-main">
<a-watermark v-bind="themeStore.watermark">
<router-view></router-view>
</a-watermark>
</div>
</div>
</el-config-provider>
</a-config-provider>
</template>
<router-view> 负责动态创建 / 销毁路由页面组件;
a-config-provider、el-config-provider 本身都会渲染额外外层 DOM 容器(生成包裹 div);
路由切换时:旧页面组件销毁 → 新页面创建;
ElementPlus / Antdv 的 ConfigProvider 在更新 locale、theme 响应式变量时,自身会触发内部 DOM 重排、节点移动操作。
冲突场景:
路由组件销毁流程还没走完,外层 ConfigProvider 同时执行 DOM insertBefore 移动节点;此时待操作 DOM 已经被路由卸载、脱离父节点,浏览器直接抛出异常。
简单理解:
一边路由要把页面 DOM 移除,一边组件库 ConfigProvider 试图移动这个 DOM(insertBefore),节点不在父元素内,报错。