likes
comments
collection
share

新奇玩法!在Vue3中使用class component、注解和TSX!

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

问题引入

可能你看到标题会很奇怪,Vue3 不是已经不推荐在 Vue 中使用类组件了吗?因为类组件其实和 export default 选项式的对象写法本质差不多,但是这样不利于复用。在 Vue3 中主张的一个思想就是组合函数复用,只要有 setup 的地方就可以使用组合函数。

第二个问题,为什么要使用注解?

哦哦,可能是 Java 里面叫习惯了,JavaScript 中对应的是叫“装饰器”。使用类组件的时候,需要搭配注解来实现 Vue 对象的属性的声明以及注入,因为你用类声明了一个组件就没法像对象写法那样使用 Vue 的 API,所以得用注解。

第三个问题,为什么要用 TSX?

TSX 其实是 TypeScript + JSX 的组合。这没有为什么,因为是团队要求的。老项目就是使用 TSX,目前的工作量不足以支撑使用组合式 API 重构,仅仅是拿过来做 Vue3 的升级。

让我们开始

快速初始化一个脚手架项目

新奇玩法!在Vue3中使用class component、注解和TSX!

安装一下依赖,试试能不能跑起来。

新奇玩法!在Vue3中使用class component、注解和TSX!

安装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 即可。

最后回到浏览器看一下效果:

新奇玩法!在Vue3中使用class component、注解和TSX!

可恶,竟然报错了。从报错的原因上看,好像是不支持注解,缺少 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))
    }
  }
})

再回到浏览器,奇迹出现啦:

新奇玩法!在Vue3中使用class component、注解和TSX!

假如你不使用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
评论
请登录