编码猿 78336de068 22
2025-12-08 16:18:25 +08:00
2025-12-08 13:55:37 +08:00
2025-12-08 13:55:37 +08:00
22
2025-12-08 16:18:25 +08:00
2024-09-27 00:48:07 +08:00
2024-09-27 00:48:07 +08:00
2024-09-27 00:48:07 +08:00
2024-09-27 00:48:07 +08:00
2024-09-27 00:48:07 +08:00
www
2025-08-29 22:06:14 +08:00
22
2025-12-08 16:18:25 +08:00
2024-09-27 00:48:07 +08:00
2024-09-27 00:48:07 +08:00
2024-09-27 00:48:07 +08:00
2024-09-27 00:48:07 +08:00
2025-12-08 13:54:20 +08:00
2024-09-27 00:48:07 +08:00

前言:

前端发展真的是一个轮回,越发展越偏向原生Vue3开发阶段就参与并使用了,但是Vue3真的垃圾,十分的不喜欢这种垃圾的语法,钟爱classts装饰器,所以有了本项目!!

本项目作为Vue脚手架而存在已在很多公司项目中落地并经过不断打磨同时为了更优雅的代码开发本人写了很多周边的辅助插件装饰器shell为你提供类似java开发中SpringBoot那般优雅的爽快感!

围绕项目开发的插件有:

1: vue-cli-plugin-tsx-autorouter tsx自动路由插件 受Nuxt.js的思想启发,针对本项目tsx开发,根据页面结构自动生成路由配置文件,借助babelast实现提取tsx中类的属性进而实现路由meta

2./bin/tinit 封装shell命令行工具实现通过命令行直接创建众多代码文件

3解耦前端 页面 & JSON数据实现JSON映射存储到类属性

4装饰器将封装成通用TS项目插件

  • 1: 让代码更加优雅简洁高效的请求中间层装饰器 @GET@POST@DELETE@PUT
       @GET()
       @Mapper(ResponseType)
       public async IndexTest (params: object): Promise<ResponseType[]> {
           // 留空,不要写请求代码 即可发送请求,除非 useHandle: true这时 方法入参  params 为 ajax 接口数据,直接处理 params
           // 即可,同时也不需要写请求代码!!
       }
    
  • 2: 依赖注入装饰器:@Autowired
  • 3: 其他装饰器:@GlobalMethod@Mapper@RegVuePlugs@RegServiceAndMethods@Start 等等..

5AutoServiceCodeGeneration实时监听configure.config.ts配置文件,然后根据ApiList中的对象key名称自动生成请求中间层的代码,降低手动复制的低效率! 介绍: 1: 文件监听已通过Nodejs流操作实现文件监听读取提取核心代码并实现同一文件中不同编辑下的新旧数据Diff。 2请求中间层代码自动生成思路已有,挑战性不足,所以还未进行代码实现

TsxVueClassApi

基于Vue Class ApiTypeScriptJSX,搭建的一套项目脚手架,实现了很多常用的注解,同时基于babel插件通过Ast语法树进行路由配置文件的自动生成等。

如果你喜欢JSX,那么这套脚手架你应该会十分喜欢,代码语法如下:

import "@pageLess/Home.less";
import { Component } from 'vue-property-decorator';
import HelloWorld from '@components/HelloWorld';
import { HomeLogic } from "@logic/page/Home.logic";
import { Getter } from "vuex-class";
import { IndexUtils } from "@utils/index.utils";
import { Autowired } from "@ann/Ioc.annotation";
import { VueCustomize, RouterMeta } from "@logic/Base.type";

@Component
export default class Home extends VueCustomize {
  // RouterMeta 是 vue-router 路由meta配置信息会被 我们的插件
  // vue-cli-plugin-tsx-autorouter 进行 ast 提取注入到 自动生成的 路由配置文件中
  public RouterMeta: RouterMeta = {
    title: '首页',
    showNav: true,
    isLogin: true
  }

  // 抽离组件所有逻辑到独立类,解耦 页面层 和 逻辑层
  // 通过 Autowired 依赖注入装饰器 实现 注入 逻辑 -> 页面
  // 同时 传入 vue 的 this实现逻辑层可以调用vue方法
  @Autowired(Home)
  private logic!: HomeLogic<Home>

  @Autowired()
  public readonly Utils!: IndexUtils;

  @Getter('GettersTabsContentArr')
  public readonly getterFoo!: Array<any>;

  public async created() {
    await this.logic.StartUp();
  }

  public ClickButton(): JSX.Element {
    return (
      <a-button type="primary" onClick={async () => {
        console.log("按钮被点击22222");
      }}>
        Primary
      </a-button>
    )
  }

  public back() {
    console.log("qqqq");
  }

  protected render() {
    return (
      <div class="home">
        <img src="/img/baidu.png" alt="" />
        <h1 on-click={this.back}>111</h1>
        <HelloWorld msg="向HelloWorld props传参" />
        <input type="text" v-model={this.logic.title} />
        <h2>{this.logic.title}</h2>
        {this.ClickButton()}
        <ul>
          {
            this.logic.List.map(v => {
              return <li>
                {v.user_id}
                {v.user_name}
              </li>
            })
          }
        </ul>
      </div>
    )
  }
}

这个脚手架我们正在项目中使用,同时也在不断的开发和完善!!!!

1安装

需要额外全局安装的插件有:

npm i -g concurrently cross-env gulp

然后下载项目,初始化并启动:

git clone https://gitee.com/bmycode/vue-class-api-tsx.git
npm i
npm run start
# 注意网站运行后使用电脑本机的局域网ip地址来访问例如http://192.168.1.101:8080/#/Home

注意

Vue官方原生底层就支持JSX语法,但是官方没有关于Vue中使用JSX的文档,而且很多Vueui框架和第三方插件都没有相关语法但是这不影响我们在Vue中正常使用JSX。很多语法需要特殊注意和改造一下!!

2使用

下面说下这个脚手架的使用和注意事项。

2.1:项目结构

请仔细看文件后面的中文说明!!!

├── README.md
├── babel.config.js babel配置文件
├── bin   终端NewFile工具
│   ├── config 
│   │   └── index.js
│   └── tinit
├── dist  打包后的文件夹
├── gulpfile.js  gulp配置文件实现监听page自动生成路由文件
├── package.json 核心依赖配置文件
├── public       公共的资源文件
├── src          存放核心源码
│   ├── application  页面相关
│   │   ├── app.tsx 最外层顶级父组件
│   │   ├── assets  静态资源回合webpack打包进源码
│   │   ├── components 公共组件
│   │   ├── logic      【重要】TSX组件中的js逻辑抽象层
│   │   │   ├── base.logic.ts  【重要】所有TSX组件的js逻辑父类
│   │   │   ├── base.type.ts 组件中 通用类型的编写
│   │   │   └── page   【重要】对应页面的TSX组件逻辑抽象
│   │   └── page  【重要】存放TSX页面组件
│   └── core  核心JS层
│       ├── annotation 存放自己开发的装饰器
        │   ├── JsonToClass json-mapper-class 的源代码
│       │   ├── http.annotation.ts  请求装饰器
│       │   ├── ioc.annotation.ts   IOC依赖装饰器
│       │   └── register.annotation.ts 启动装饰器
│       ├── config    站点配置文件
│       │   ├── configure.config.ts 核心配置文件
│       │   └── route.config.ts     自动生成的路由配置文件
│       ├── dao                     axios的封装
│       ├── model                   TS存取器
│       ├── run                     项目的启动类
│       │   ├── init.run.ts   初始化Vue各种配置
│       ├── service           请求的service层封装
│       │   └── impl          请求service的具体类
│       ├── store             Vuex的配置
│       ├── types             自定义的声明文件
│       └── utils             工具函数
├── tsconfig.json             TS的配置文件
└── vue.config.js             Vue-cli3 的配合文件

2.2:编码注意事项和规范,严格遵守!!!

1page/文件夹中的所有tsx组件必须继承自VueCustomizeVueCustomize是所有页面的父类,可以在这里定义一些公共的类型!

2logic/文件夹中的所有logic.ts必须继承BaseLogic并实现接口MethodsBaseLogic是所有页面逻辑层的公共封装,可以把使用率高的接口或者变量放在BaseLogic 中去定义和实现,这样页面的逻辑层子类可以实现直接使用!

3logic/中页面的逻辑层可以使用装饰器@Autowired()去注入多个service的依赖,实现对ajax中间层方法的调用,以发送ajax请求!具体的看下面代码

import { Autowired } from "@/core/annotation/Ioc.annotation";
import { UserServiceImpl, ResponseType} from "@/core/service/impl/User.service.impl";
import { BaseLogic } from "@logic/Base.logic";
import { Methods, VueCustomize } from "@logic/Base.type";

export class HomeLogic<T extends VueCustomize> extends BaseLogic implements Methods {

  @Autowired()
  public readonly UserServiceImpl!: UserServiceImpl;

  public title: string = "12222";
  
  public List: ResponseType[] = [];

  constructor(_: T) {
    super();
    this._ = _
  }

  /**
   * 在这里面调用需要打开页面就执行的ajax请求
   * @constructor
   */
  public async StartUp (): Promise<void> {
    await this.getData();
  }

  /**
   * 请求首页数据
   */
  public async getData (): Promise<void> {
    this.List = await this.UserServiceImpl.IndexTest({ type: 1, page: 1 });
    console.log("this.List: ", this.List);


    // let res = await this.UserServiceImpl.login({ type: 2, page: 2 });
    // console.log("this.res: ", res);
    
    // this._.$setToken("")
    // await this._.$router.push('/About')
  }
}

4logic/中必须实现构造函数constructor,在构造函数中保存tsx页面传入指向vue实例的this,这样才能在logic中正确使用vue的一些方法,具体看代码:

constructor(_: T) {
  super();
  this._ = _
}

/**
 * 请求首页数据
 */
public async getData (): Promise<void> {
  this.List = await this.UserServiceImpl.IndexTest({ type: 1, page: 1 });
  console.log("this.List: ", this.List);
}

5如何将自定义的方法通过 Vue.prototype.xxx 挂载到Vue上以方便全局使用?

答:在utils/index.utils.ts中定义方法的时候请使用装饰器@GlobalMethod()装饰方法,然后如果你在tsx页面组件中需要使用此方法,那么请在base.type.ts中定义变量并编写变量类型!

同时如果你需要在logic逻辑层使用此方法,那么需要在base.logic.tsVueType接口中编写类型。具体请看代码:

// src/core/utils/index.utils.ts

import { ConfigureConfig } from "@config/configure.config";
import { GlobalMethod } from "@ann/Register.annotation";

export class IndexUtils {
  /**
   * 方法上打上 @GlobalMethod() 注解这个方法会自动成为vue的全局方法
   * 组件中直接this.$setToken() 即可
   */
  @GlobalMethod()
  public setToken (args: string): void {
    localStorage.setItem("token", args)
  }
}

// src/application/logic/base.logic.ts

// 定义 $setToken 方法和入参类型,返回值等!
export class VueCustomize extends Vue {
  $setToken!: (token: string) => void
}

如果你觉得上面方式使用全局方法太过于麻烦,那么你可以在你需要使用的logic类或tsx组件中使用装饰器@Autowired()来注入index.utils.ts到类属性中,代码示例:

import "@pageLess/Home.less";
import { Component } from 'vue-property-decorator';
import HelloWorld from '@components/HelloWorld';
import { HomeLogic } from "@logic/page/Home.logic";
import { Getter } from "vuex-class";
// 1导入需要被注入的类
import { IndexUtils } from "@utils/index.utils";
// 2导入装饰器
import { Autowired } from "@ann/Ioc.annotation";
import { VueCustomize, RouterMeta } from "@logic/Base.type";
import { toClass, toInterface, configFilePath } from "json-class-interface";
@Component
export default class Home extends VueCustomize {

  // 抽离组件所有逻辑到独立类,解耦页面和数据
  @Autowired(Home)
  private logic!: HomeLogic<Home>

  // RouterMeta 是 vue-router 路由meta配置信息会被ast提取注入到自动生成的路由配置文件中
  public RouterMeta: RouterMeta = {
    title: '首页',
    showNav: true,
    isLogin: true
  }

  // 3将 IndexUtils 注入到属性 Utils 中
  @Autowired()
  public readonly Utils!: IndexUtils;

  @Getter('GettersTabsContentArr')
  public readonly getterFoo!: Array<any>;


  public async created () {
    // 4使用 setToken 方法
    this.Utils.setToken("1111")
  }



  public ClickButton(): JSX.Element {
    return (
      <a-button type="primary" onClick={async () => {
        console.log("按钮被点击22222");
      }}>
        Primary
      </a-button>
    )
  }

  public back() {
    console.log("qqqq");
  }


  protected render() {
    return (
      <div class="home">
        <img src="/img/baidu.png" alt="" />
        <h1 on-click={this.back}>111</h1>
        <HelloWorld msg="向HelloWorld props传参" />
        <input type="text" v-model={this.logic.title} />
        <h2>{this.logic.title}</h2>
        {this.ClickButton()}
        <ul>
          {
            this.logic.List.map(v => {
              return <li>
                {v.user_id}
                {v.user_name}
                </li>
            })
          }
        </ul>
      </div>
    )
  }
}

2.3:使用注意事项

1 项目中的路由使用的是vue-router,同时我借鉴了Nuxt.js的思想,自己开发了路由配置文件自动生成的插件,这个插件是Vue-cli 3的插件,所以不能在Vue cli 2的项目中使用!!

插件源码已经提交npm包市场!请完整阅读下面的插件文档,路由的配置文件让插件帮我们自动生成就好了!!!

vue-cli-plugin-tsx-autorouter

2 同时借鉴PHP开发框架Laravel开发终端命令行工具,通过命令帮我们创建带有模板代码能直接运行的文件!代码放在 bin/ 文件夹中!

使用手册:

╭─bmy@MacBook-Pro /Applications/Source/TsxVueClassApi master* 
╰─$ ./bin/tinit -h
Usage: tinit [options]

Options:
  -t, --file-type <type>  文件类型: [pagelogicserviceimplless]
  -n, --file-name <name>  被创建的文件名称
  -i, --is-create <is>    是否为 -t 参数自动创建相关文件类型 (default: false)
  -v, --version           显示当前的版本
  -h, --help              display help for command

参数说明:

  • -t需要被创建的文件类型取值 pageTSX页面logicTSX页面的js抽象层service请求中间层的接口impl实现接口的类lesscss样式文件。可以多传
  • -n需要被创建的文件名
  • -i如果数值为true那么会自动创建 -t 参数所有的文件类型

使用案例:

╭─bmy@MacBook-Pro /Applications/Source/TsxVueClassApi master* 
╰─$ ./bin/tinit -t page logic -n Test
成功创建文件...

上面命令执行后会分别在src/application/page中创建创建文件Text.tsx页面组件,同时在src/application/logic/page中创建Test.logic.ts的逻辑层文件。

多试几次,请自行熟练掌握!!

3开发中功能

  • 【重要】1实现ajax请求到的数据和model层的映射绑定,这种数据绑定关系,可以完全解决后端改接口字段从而导致前端代码也需要同步大量修改的问题!!

  • 【不太重要】1实时监听configure.config.ts配置文件,然后根据ApiList中的对象key名称自动在service层的类中生成对应的方法,降低手动复制的低效率!

    • 已实现功能,但未整合进项目!
Description
TsxVueClassApi
Readme Apache-2.0 500 KiB
Languages
TypeScript 57.7%
JavaScript 24%
Less 17.6%
HTML 0.7%