likes
comments
collection
share

Vue + ts 开发遇到的奇怪问题:删了 A 页面的组件引用,B 页面样式表挂了

作者站长头像
站长
· 阅读数 50

如题,就是我遇到的奇怪问题,费了我一天,终于搞清楚了原委,荒诞,可笑,气愤,不知道说什么好。

昨天晚上,突然发现我正在写的一个软件,一个目录树的样式崩坏了……

刚看到,我是震惊的,因为我已经很久没碰这个页面了,为啥就突然崩坏了呢?让我有种摸不着头脑的感觉。一度怀疑是我每天执行 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
评论
请登录