新奇玩法!在Vue3中使用class component、注解和TSX!
问题引入
可能你看到标题会很奇怪,Vue3 不是已经不推荐在 Vue 中使用类组件了吗?因为类组件其实和 export default
选项式的对象写法本质差不多,但是这样不利于复用。在 Vue3 中主张的一个思想就是组合函数复用,只要有 setup
的地方就可以使用组合函数。
第二个问题,为什么要使用注解?
哦哦,可能是 Java 里面叫习惯了,JavaScript 中对应的是叫“装饰器”。使用类组件的时候,需要搭配注解来实现 Vue 对象的属性的声明以及注入,因为你用类声明了一个组件就没法像对象写法那样使用 Vue 的 API,所以得用注解。
第三个问题,为什么要用 TSX?
TSX 其实是 TypeScript + JSX 的组合。这没有为什么,因为是团队要求的。老项目就是使用 TSX,目前的工作量不足以支撑使用组合式 API 重构,仅仅是拿过来做 Vue3 的升级。
让我们开始
快速初始化一个脚手架项目
安装一下依赖,试试能不能跑起来。
安装vue-facing-decorators
要使用注解开发 Vue 项目,那么必须得装一下 vue-facing-decorator 这个库,它是 vue-property-decorator 的 Vue3 版本平替库。基本上都能支持原有的一些类和注解。
pnpm install vue-facing-decorator
来试着编写一个HelloWorld
在项目根目录创建一个 App.tsx 文件,编写如下代码:
import { Component, Vue } from 'vue-facing-decorator'
import type { VNode } from 'vue'
@Component({ name: 'App' })
export class App extends Vue {
render(): VNode {
return (
<>
HelloWorld
</>
)
}
}
咦?怎么有点 Spring 的味道了?哈哈哈哈。
在 main.ts 文件中导入 App 类,代码修改如下:
import './assets/main.css'
import { createApp } from 'vue'
import { createPinia } from 'pinia'
import { App } from './App'
import router from './router'
const app = createApp(App)
app.use(createPinia())
app.use(router)
app.mount('#app')
App.vue 去掉后缀 .vue
即可。
最后回到浏览器看一下效果:
可恶,竟然报错了。从报错的原因上看,好像是不支持注解,缺少 babel 的插件支持。
解决问题
在 Google 上搜了一圈,最后在 StackOverflow 上面找到了一个好的解决方案。想使用装饰器需要安装一个库,命令如下:
pnpm install --save-dev @babel/plugin-proposal-decorators
修改一下 vite.config.ts,在 vueJsx 插件函数的括号里面加上如下配置项,表示支持注解,legacy 是遗产的意思,笔者揣测是老版本的意思:
import { fileURLToPath, URL } from 'node:url'
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import vueJsx from '@vitejs/plugin-vue-jsx'
import VueDevTools from 'vite-plugin-vue-devtools'
export default defineConfig({
plugins: [
vue(),
vueJsx({
babelPlugins: [[
'@babel/plugin-proposal-decorators',
{ legacy: true },
]]
}),
VueDevTools()
],
resolve: {
alias: {
'@': fileURLToPath(new URL('./src', import.meta.url))
}
}
})
再回到浏览器,奇迹出现啦:
假如你不使用JSX
可能你会问,假如我不使用 JSX 呢?就用普通的类组件呢?
别急,一切问题都是有解决方案的。你需要安装一个第三方插件,国外开源社区大神的开发的 vite 插件,叫作 vite-plugin-babel:
pnpm install -D vite-plugin-babel
再修改一下 vite.config.ts 的配置:
import { defineConfig } from 'vite';
import babel from 'vite-plugin-babel';
export default defineConfig({
plugins: [
babel({
babelConfig: {
babelrc: false,
configFile: false,
plugins: [
[
"@babel/plugin-proposal-decorators",
{ loose: true, version: "2022-03" },
],
],
},
}),
],
resolve: {
alias: {
'@': fileURLToPath(new URL('./src', import.meta.url))
}
}
});
这里引入了一个 babel 插件函数,在内部进行配置。按照这个方法应该可以的。
总结
虽然 Vue 官方已经不推荐类组件的写法而且在 Vue 中写 JSX 也很不推荐,但是就当作是一次小小的尝试吧,学习的经历。因为在项目管理中,需要评估项目的各种的风险,在时间紧张的情况下,就必然使用非同寻常的策略,这也不失为一种好的解决方法。以后的优化放在以后做(工作量又来了,又有一段时间不用担心失业咯,哈哈哈。)。
怎么样,你学会了吗?
转载自:https://juejin.cn/post/7370708996419584054