问题
保存时仍需报错 但是F5正常 打包也正常

ini
chunk-ZHNFVA5M.js?v=ac948eb1:11432 Uncaught (in promise) TypeError: Cannot read properties of null (reading 'nextSibling')
at nextSibling (chunk-ZHNFVA5M.js?v=ac948eb1:11432:35)
at removeFragment (chunk-ZHNFVA5M.js?v=ac948eb1:6679:14)
at remove2 (chunk-ZHNFVA5M.js?v=ac948eb1:6650:9)
at unmount (chunk-ZHNFVA5M.js?v=ac948eb1:6628:9)
at Object.remove (chunk-ZHNFVA5M.js?v=ac948eb1:9303:13)
at unmount (chunk-ZHNFVA5M.js?v=ac948eb1:6603:20)
at unmountComponent (chunk-ZHNFVA5M.js?v=ac948eb1:6713:7)
at unmount (chunk-ZHNFVA5M.js?v=ac948eb1:6593:7)
at unmountComponent (chunk-ZHNFVA5M.js?v=ac948eb1:6713:7)
at unmount (chunk-ZHNFVA5M.js?v=ac948eb1:6593:7)
环境准备
官方原版前端环境(5.5.9版本) 未调整任何配置 具体为
- transition开
- keepAlive关
(后话) 跟上面的都没关系
在什么情况才会出现
之前在项目中测试 只要是xxx.ts(tsx)
保存 就会出现该问题 xxx.vue
则不会出现
测试非useVbenXXX的页面
先使用playground/src/views/demos/access/index.vue
来测试

新建data.ts
然后vue文件引用
data.ts
js
console.log('code code');
index.vue
arduino
import './data';
修改data.ts
里的代码(或者直接保存也会触发热更新) 页面正常热更新 没有出现问题
测试useVbenModal/Drawer
文件位置playground/src/views/examples/modal/index.vue

还是同样 引用data.ts
流程跟上面一样 也能正常热更新
测试useVxe
文件位置playground/src/views/examples/vxe-table/basic.vue
data.ts
js
console.log('code code');
export const column = [
{ title: '序号', type: 'seq', width: 50 },
{ field: 'name', title: 'Name' },
{ field: 'age', sortable: true, title: 'Age' },
{ field: 'nickname', title: 'Nickname' },
{ field: 'role', title: 'Role' },
{ field: 'address', showOverflow: true, title: 'Address' },
];
vue
js
onMounted(() => {
console.log('mounted');
});
onBeforeUnmount(() => {
console.log('unmount');
});
然后保存data.ts 也能正常更新 看看Log

卸载再挂载 看起来流程没有问题
换个符合业务带查询的表格试试呢 playground/src/views/examples/vxe-table/form.vue
保存也是正常的 (后话: 因为没有Modal/Drawer) 也没有公用data.ts
混合
使用这个页面测试

保存data.ts
后 一定会复现

先把drawer相关的代码移除 发现保存正常了(热更新)

那么确定是useForm
的问题?
然后试了 单独 drawer+form 的情况(不包含表格) 没问题?
这就奇了怪了 三个单独使用都没问题 混在一次就有问题了?
然后回到role
菜单来测试 保留drawer 但是去除useForm 这样热更新也没问题
只保留一个空drawer 难道是useForm
的问题 控制变量进一步探究
js
<script lang="ts" setup>
import type { SystemRoleApi } from '#/api/system/role';
import { computed, ref } from 'vue';
import { useVbenDrawer } from '@vben/common-ui';
import { $t } from '#/locales';
const formData = ref<SystemRoleApi.SystemRole>();
const [Drawer] = useVbenDrawer({});
</script>
<template>
<Drawer />
</template>
研究过程不赘述 发现将schema改为内部(不引用data.ts) 则不报错
js
原版 从外部data.ts导入 报错
const [Form, formApi] = useVbenForm({
schema: useFormSchema(),
showDefaultActions: false,
});
内部 不报错
const [Form, formApi] = useVbenForm({
schema: [],
showDefaultActions: false,
});
最终发现 只要把data.ts
中引用的schema移动到新的ts 或者 直接在modal.vue
都能正常运行(算一种解决方案)
js
const [BasicForm, formApi] = useVbenForm({
commonConfig: {
labelWidth: 80,
},
schema: [直接在这里写 不从data.ts导入],
showDefaultActions: false,
});
或者
js
// 跟data.ts文件分开
import { modalSchema } from './other';
const [BasicForm, formApi] = useVbenForm({
commonConfig: {
labelWidth: 80,
},
schema: modalSchema(),
showDefaultActions: false,
});
这是一种解决方案 但不是最终的解决方案
另外的解决方案
使用热更新api来操作 也能正常 不推荐
html
<script setup lang="ts">
const key = ref(0);
if (import.meta.hot) {
import.meta.hot.accept(() => {
key.value++;
});
}
</script>
<template>
<BasicModal :key="key" :title="title" class="w-[550px]">
<BasicForm />
</BasicModal>
</template>
继续分析
问题跟useForm也无关 去除form后保存data.ts 热更新还是报错 那么问题就是在modal(drawer)上
那么需要确定是modal
造成的还是useVbenModal
造成
使用控制变量的方法 直接不使用useVbenModal
方法 导入modal并且更改props来直接显示
bash
packages/@core/ui-kit/popup-ui/src/modal/modal.vue
发现保存 热更新也是在报错 那么确定就是组件的问题
通过一个个删除元素 最终确认!!!
问题出在这个组件 DialogContent!!!

内部是这个组件 radix-vue提供的DialogPortal
确认是这个组件产生的问题

只要这个删除(换成div) 热更新就不会报错(当然样式也会有异常)
到github查看源码

使用的是TeleportPrimitive
问题出在这里 查看源码

贴上关键代码
js
<script setup lang="ts">
import { useMounted } from '@vueuse/core'
withDefaults(defineProps<TeleportProps>(), {
to: 'body',
})
const isMounted = useMounted()
</script>
<template>
<Teleport
v-if="isMounted || forceMount"
:to="to"
:disabled="disabled"
:defer="defer"
>
<slot />
</Teleport>
</template>
本质就是对Teleport
的封装(且参数都和Vue的一致) 看起来也没啥问题 那直接把上面的组件换成vue的Teleport
试试 发现
热更新正常了 不会报错了!!!
而且外部只使用了to参数 切换到teleport也是无缝

after

经过测试 热更新不会出现问题
原因分析
将文件粘贴到本地来测试

DialogContent.vue
引用 DialogPortal.vue
引用 MyTeleport.vue
保存 果然出现了问题

然后直接引用MyTeleport.vue
来测试

也报错

当直接使用Teleport
是正常了 只要包装了一层 就会产生问题
目前看使用Teleport
替换也没有产生什么副作用 先这样吧 有空再分析补充
解决方案
packages/@core/ui-kit/shadcn-ui/src/ui/dialog/DialogContent.vue
将DialogPortal
替换为Teleport
Drawer也是一样的改法
packages/@core/ui-kit/shadcn-ui/src/ui/sheet/SheetContent.vue
将DialogPortal
替换为Teleport