【D1n910】项目迁移 Vue3.0 + Vite + typescript 踩31坑记录
正常操作,正常分析,大家好,我是 D1n910(蛋糕)。
可恶的蛋糕,害苦了我的同事们,是蛋糕说的,新项目,可以用新技术跑一下,没想到这么多坑。好在现在暂时活了下来。
迁移之前,一定要看 Vue2.0 升级到 Vue3.0 相关的文档。
很多问题,顺手改了,也没记下来,想必也是简单问题。

0、项目迁移方案
用 vite 直接生成新的项目,然后再从旧项目逐步迁移代码到新项目,vue-router、vuex、element-plus 等全家桶内容升级到最新。
原来的 mixins 内容,如果较为复杂,暂时不处理。不复杂的转为 setup。
1、使用 less 报错
在项目启动,直接使用 less,报送以下错误。
[vite] Internal server error: Preprocessor dependency "less" not found. Did you install it?
原因是新初始化的项目没有 less。
用下面的指令安装 less 然后执行即可。
yarn add less less-loader
2、启动后,不能够用ip地址访问,只能用localhost
启动指令添加 '--host' 配置即可。
"dev": "vite --host"
3、安装 eslint 后报错,vite安装vue项目报错(Error: esbuild: Failed to install correctly),参考链接 https://blog.csdn.net/m0_37682004/article/details/115001613
手动运行
来解决esbuild安装问题
安装完成之后,再次运行 npm run dev 即可。
4、Vite,typescript 设置别名(类似webpack的resolve.alias)
参考自
https://blog.csdn.net/weixin_43980237/article/details/117929461
(1)修改 vite.config.ts 配置

(2)修改 tsconfig.json 配置,这样 ts 才能检测到

5、别名设置错误,重新设置
error when starting dev server:
Error: The following dependencies are imported but could not be resolved:
…… Are they installed?
这是因为第 4 步的时候设置别名搞错了,所以需要重新设置。
7、this.$route 拿不到
参考链接
https://www.jianshu.com/p/00c109c36e38
router.currentRoute 来获取
8、this.$router 拿不到
9、$on、$emit 原来 vue2.0 的事件API,vue3.0被废弃,改为用 mitt 来实现
10、Vite通过代理(proxy)解决本地开发接口调用及跨域问题
参考
https://www.cnblogs.com/hy999/p/vue-vite-proxy.html
在 vite.config 中这么写配置
vue3 在 vite.config 中无法使用import.meta.env.*的解决办法
参考链接
https://www.jianshu.com/p/4973bd983e96
附带环境变量配置
根目录下文件命名方式

文件内书写方式

11、添加 eslint(todo)
https://blog.csdn.net/qq_23398171/article/details/115010584
https://www.baidu.com/s?ie=utf-8&f=8&rsv_bp=1&rsv_idx=2&tn=baiduhome_pg&wd=vite%20%E5%AE%9E%E6%97%B6%E7%9B%91%E6%B5%8B%20eslint%20%E4%BB%A3%E7%A0%81&rsv_spt=1&oq=vite%2520%25E5%25AE%259E%25E6%2597%25B6%25E7%259B%2591%25E6%25B5%258B%25E4%25BB%25A3%25E7%25A0%2581&rsv_pq=b4a56256000d953f&rsv_t=571bQpjSAO7ykPfBBs55BXsoR07Y%2FO2S6hNEfT2qZ2QpXNXMievdQ427twcrDwPr9ZkI&rqlang=cn&rsv_enter=1&rsv_dl=tb&rsv_btype=t&inputT=3962&rsv_sug3=60&rsv_sug1=13&rsv_sug7=100&rsv_sug2=0&rsv_sug4=4770
这个比较复杂,然后对于 vite 使用 eslint 有一个问题,我还没搞清楚,就是如何能够在 vite 运行时,检测到 eslint 报错,打断运行,红色提示。vite 内部编译报错会这样,但是我还没找到 vite-eslint 的。
12、Vue 3.0 原型链拓展属性(vue3.0使用TypeScript 如何拓展一个方法并且this可以访问,不报错?)
参考链接
https://www.jianshu.com/p/12faae13496d
13、拓展方法,BUS的运用,个人对于 12 的理解使用

这个作用是,模仿全局对象上挂vue实例,这样就能够在没有vue实例的方法中调用 vue 实例上挂载的方法,比如 element 的 this.$message。

BUS 文件 —— any 我找个时间去一下……

14、模块引用方式,换为 ref,看 vue3 文档,模块引用篇
15、elForm 表单值不能填写
14的延伸问题,发现是因为 ref 对应的变量名 和 v-model 绑定的变量名一样了。
类似下面这样
ref="from"
v-model="form"
改为不一样就行了。
16、Vue3.0 typescript props 设置泛型 提示错误
参考
https://github.com/nuxt/typescript/issues/285
修改 eslint 配置
17、vue-router 的 addRoutes 修改为 addRoute
需要注意,addRoutes 可以传入数组。最新的 vue-router 已废弃 addRoutes。改为使用addRoute。
addRoute 变成单个对象了。
相当于得这样
咱也不知道为什么要废弃,咱也不敢问。
18、router 提示 Catch all routes ("*") must now be defined using a param with a custom regexp.
参考自
https://blog.csdn.net/c6c6c/article/details/110558290
原因是要改为正则匹配
19、语法提示,变量名称最好不要用 $ 或者 _ 下划线开头
20、Property "xxx" was accessed during render but is not defined on instance.
属性“xxx”在渲染期间被访问,但未在实例上定义。
就是属性没定义,定义一下。
21、Extraneous non-props attributes (class) were passed to component but could not be automatically inherited because component renders fragment or text root nodes.
无关的非props属性(类)已传递给组件,但无法自动继承,因为组件呈现片段或文本根节点。
https://blog.csdn.net/qq_38888512/article/details/117224108
[Vue warn]: Extraneous non-props attributes (border, style) were passed to component but could not be automatically inherited because component renders fragment or text root nodes.
at xxxx(发生问题的组件位置)
at ...
在自定义组件上添加了border、style属性,而自定义组件内部又未去接收,因此警告了。
所以,要么在组件内部加上属性接收。如果是在第三方库UI库的话,建议直接去掉这些属性。
发现就是 element-plus 的 dialog 不支持 class,参考 element-plus 文档换了能够改 class 的属性,这个具体是什么属性的问题,提示里其实也有给出。像下面说的“class”

22、Failed to resolve component: xxx
不能加载 xxx 组件。
引用的组件没有在 component 声明,或者原来全局/局部加载的组件没有全局加载。
参考
https://blog.csdn.net/qq_41983641/article/details/115361460
23、升级 v-contextmenu 到最新版本
参考
https://github.com/heynext/v-contextmenu
yarn add v-contextmenu@next
import contextmenu from "v-contextmenu";
import "v-contextmenu/dist/themes/default.css";
Vue.use(contextmenu);
24、vue问题--[Vue Router warn]: <router-view> can no longer be used directly inside <transition> or <keep-
vue-router 新版本的问题,需要改写 router-view 的包裹方式方式,参考链接
https://blog.csdn.net/tjj3027/article/details/109597720
25、build 构建,vue-tsc --noEmit指令,ts 监测了 node_modules 下的代码

在tsconfig.json文件中使用exclude:
"exclude": [
"node_modules"
]
在 tsconfig.json 配置里加入
"compilerOptions": {
"skipLibCheck": true
}
26(todo)、build 构建,vue-tsc --noEmit指令,ts 监测了 template 的内容,报送不能找到 name。

ts会检查 template 下的内容,写法不兼容,所以检测不到。未解决。
考虑
A、修改ts配置;
B、改写为tsx写法;
C、构建时暂时不用 vue-tsc 先监测;
D、其他。
目前为了赶项目上线面选用方法 C,以后会妥善解决的。
27、slot 方式改变,slot不用 v-slot,改成 #slotName
28、element-plus elTabs tab-click 绑定方法报错
原因是传值变成组件实例了,所以之前取值报送 undefined

改为用 props 去获得
比如原来的
@tab-click="doSomthing"
doSomthing(data) {
console.log(data.value)
}
改为
doSomthing(data) {
console.log(data.props.value)
}
29、vite 数据不实时视图更新
解决方法
(1)✅ 重启 vite
(2)✅ 查看变量名是否冲突有误,场景:
父组件属性名称 aaa,通过 props 传入子组件;
子组件内部data命名为 aaa,覆盖了 props 的 aaa,所以没变化。
(3)(未尝试)处理浏览器缓存
30、切换路由报送错误,自定义指令错误
切换路由报送 Uncaught (in promise) TypeError: Cannot read property 'parentNode' of null。
Uncaught (in promise) TypeError: Cannot read property 'created' of undefined。
我这边的原因是是自定义指令有问题,发现自定义指令没有注册成功。修复后无报错。
31、自定义指令不生效
发现是因为用了已废弃的生命周期。原来我用的 inserted 改成了 mounted。解决问题。
Vue3.0 的生命周期有修改,参考 https://v3.cn.vuejs.org/guide/custom-directive.html#%E7%AE%80%E4%BB%8B。

到了第31个问题以后,基本上项目基础架构迁移完毕了,剩下的就是继续业务开发了。
所谓看到新技术一时爽,一用火葬场。
用了一段时间,稍微说一下自己觉得用了这些新内容的好处。
Vue3.0确实感觉更加像 React 了,原来的一个 vue 文件走天下,现在似乎被打散了,带来的我感觉就是更加灵活,更加心无所“狗”;
typescript 让我更有规则地“狗”,帮忙发现代码中的问题;(在 ts 之下,any,永远的神!我看到很多原型的声明也用的any。不过用any也不是很好,后面会逐步把临时写的any)
vite用起来目前感觉就是快,好快,因为这是内部系统,所以兼容性问题不是考虑范围内,部署以后加载提效 42%。本地构建也起飞🛫️。尤大永远的神。
继续开发去了。
END