Vue + ts 开发遇到的奇怪问题:删了 A 页面的组件引用,B 页面样式表挂了
如题,就是我遇到的奇怪问题,费了我一天,终于搞清楚了原委,荒诞,可笑,气愤,不知道说什么好。
昨天晚上,突然发现我正在写的一个软件,一个目录树的样式崩坏了……
刚看到,我是震惊的,因为我已经很久没碰这个页面了,为啥就突然崩坏了呢?让我有种摸不着头脑的感觉。一度怀疑是我每天执行 npm upgrade,导入了什么莫名的东西,破坏了 CSS。
困扰一夜,到了第二天终究还是要解决的。这种完全摸不着头脑的 bug,我就问你怎么找??
在毫无思路的情况下,只能用最蠢的法子,二分查找法。先找一个完全不可能有问题的 commit,回滚代码,然后二分查找,直到找到引入问题的 commit。逐行比对定位。我先找了个 11月8日的一个 commit,然后是 11月12日,然后是 11月9日,最后发现是 11月9日引入的问题。(我有个很好的习惯,每天会把自己全天的所有commit,压缩在一个里面进行push,导致我的 history 里每天只有一个 commit,比较好找。)
虽然找到了那次 commit,但是里面涉及到 5 个文件我还是毫无头绪,只能再逐个文件回滚到上一个,来试是哪个文件引入的。git checkout <11月8日> -- /path/to/file.vue
,用类似这样的命令,日期换成 commit hash,逐个文件回滚,测试,终于给我找到了引入问题的文件。
然后,荒诞的事情来了。
大概简述一下就是 A 页面引入了一个 el-tree 组件,B 页面也引入了一个 el-tree 组件。然后我把 B 页面的 el-tree 删掉了,换成了 el-table,结果 A 页面的 el-tree 的样式崩裂了!荒谬!死也想不到是这样搞坏掉的。
开始还在 el-table 上动脑子,但是理智告诉我不可能。
其实到这里,已经范围已经很小了,就算一行行傻试,也能试出来是怎么回事。我就不描述了,就专注讲讲,到底怎么回事。
在这个 A 页面里,我写了类似这样的代码:
<script lang="ts" setup>
import { ElTree } from 'element-ui'
const treeRef = ref<InstanceType<typeof ElTree>>()
</script>
<template>
<el-tree
ref="treeRef"
:data="treeData"
:props="defaultProps"
node-key="id"
show-checkbox
:checkStrictly="true"
:defaultCheckedKeys="defaultChecked"
@nodeClick="onNodeClick"
@checkChange="onCheckChange"
@check="onCheck"
/>
</template>
在 B 页面里,因为已经删掉了 el-tree,你可以认为 B 页面是空的。
那么 B 页面怎么影响的 A 页面样式呢?
这就要说明一下项目的一个设定,就是 AutoImport,
export default defineConfig({
base: path.resolve(__dirname, './dist/'),
plugins: [
vue(),
AutoImport({
resolvers: [ElementPlusResolver()]
}),
Components({
resolvers: [ElementPlusResolver()]
}),
ViteYaml(),
],
resolve: {
alias: {
'@': fileURLToPath(new URL('./src', import.meta.url))
}
}
})
这是一个 vite.config.ts 的节选,可以看到引入了一个 AutoImport 的组件。
因为,此前在 B 页面引用 el-tree 的时候,只是一个简单的原型,所以就是光秃秃放了一个 el-tree 在上面。所以,B 页面激活了 AutoImport 的特性,所以 el-tree 是自动导入到项目的。
而在 A 页面,因为已经写好了很多的逻辑,必须用到 el-tree 的引用,就要定义一个叫 treeRef 的引用变量,又因为好死不死的用了 typescript,所以,定义 treeRef 必须清晰指定类型,才能在后期顺利调用引用上的方法。
而定义类型的时候,AutoImport 特性并没有生效,于是我手动写了一句至关重要的 bug。
improt { ElTree } from 'element-ui'
这句话放在页面上,是有副作用的,只导入了 el-tree 的组件而没有导入对应的样式。
在 B 页面引用 el-tree 的时候,会自动在全局导入样式,所以 A 页面看起来正常的,而我删掉 B页面对 el-tree 的引用后,样式也自动去掉了,而 A 页面又没有正确导入 el-tree 的样式,于是,就崩坏了。
等我好不容易知道后,修复起来也简单无比:
import type { ElTree } from 'element-ui'
改成这样,就完事了,只有四个按键 type
就修复了。
教训
要说有啥教训,就是我对 vite 一知半解,对 autoimport 一知半解,对 typescript 也一知半解,然后我竟然做项目的时候选了 typescript,当然,其实对前端也一知半解。最后给自己徒增烦恼而已。
记录下来,供大家找乐子!
转载自:https://juejin.cn/post/7301135811193569343