前端发展真的是一个轮回,越发展越偏向原生,Vue3
开发阶段就参与并使用了,但是Vue3
真的垃圾,十分的不喜欢这种垃圾的语法,钟爱class
和ts装饰器
,所以有了本项目!!
本项目作为Vue
脚手架而存在,已在很多公司项目中落地并经过不断打磨,同时为了更优雅的代码开发,本人写了很多周边的辅助插件,装饰器,shell,为你提供类似java
开发中SpringBoot
那般优雅的爽快感!
围绕项目开发的插件有:
1: vue-cli-plugin-tsx-autorouter tsx自动路由插件
受Nuxt.js
的思想启发,针对本项目tsx
开发,根据页面结构自动生成路由配置文件,借助babel
的ast
实现提取tsx
中类的属性进而实现路由meta
。
2:./bin/tinit 封装shell命令行工具,实现通过命令行直接创建众多代码文件
3:解耦前端 页面 & JSON数据,实现JSON映射存储到类属性:
TypeScript
项目中通用的JSON数据自动生成类型工具,支持生成 json-mapper-class 标准代码。tauri
Svelte
写的json-class-interface 桌面端工具,支持Mac
,linux
,windows
。4:装饰器(将封装成通用TS项目插件):
@GET()
@Mapper(ResponseType)
public async IndexTest (params: object): Promise<ResponseType[]> {
// 留空,不要写请求代码 即可发送请求,除非 useHandle: true,这时 方法入参 params 为 ajax 接口数据,直接处理 params
// 即可,同时也不需要写请求代码!!
}
5:AutoServiceCodeGeneration:实时监听configure.config.ts
配置文件,然后根据ApiList
中的对象key
名称自动生成请求中间层的代码,降低手动复制的低效率!
介绍:
1: 文件监听:已通过Nodejs流操作实现文件监听,读取,提取,核心代码,并实现同一文件中不同编辑下的新旧数据Diff
。
2:请求中间层代码自动生成:思路已有,挑战性不足,所以还未进行代码实现
基于Vue Class Api
,TypeScript
,JSX
,搭建的一套项目脚手架,实现了很多常用的注解,同时基于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>
)
}
}
这个脚手架我们正在项目中使用,同时也在不断的开发和完善!!!!
需要额外全局安装的插件有:
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
的文档,而且很多Vue
ui框架和第三方插件都没有相关语法,但是这不影响我们在Vue
中正常使用JSX
。很多语法需要特殊注意和改造一下!!
下面说下这个脚手架的使用和注意事项。
请仔细看文件后面的中文说明!!!
├── 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 的配合文件
1:page/
文件夹中的所有tsx
组件必须继承自VueCustomize
,VueCustomize
是所有页面的父类,可以在这里定义一些公共的类型!
2:logic/
文件夹中的所有logic.ts
必须继承BaseLogic
并实现接口Methods
,BaseLogic
是所有页面逻辑层的公共封装,可以把使用率高的接口或者变量放在BaseLogic
中去定义和实现,这样页面的逻辑层子类可以实现直接使用!
3:logic/
中页面的逻辑层可以使用装饰器@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')
}
}
4:logic/
中必须实现构造函数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.ts
的VueType
接口中编写类型。具体请看代码:
// 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>
)
}
}
1: 项目中的路由使用的是vue-router
,同时我借鉴了Nuxt.js
的思想,自己开发了路由配置文件自动生成的插件,这个插件是Vue-cli 3
的插件,所以不能在Vue cli 2
的项目中使用!!
插件源码已经提交npm
包市场!请完整阅读下面的插件文档,路由的配置文件让插件帮我们自动生成就好了!!!
2: 同时借鉴PHP
开发框架Laravel
开发终端命令行工具,通过命令帮我们创建带有模板代码能直接运行的文件!代码放在 bin/
文件夹中!
使用手册:
╭─bmy@MacBook-Pro /Applications/Source/TsxVueClassApi ‹master*›
╰─$ ./bin/tinit -h
Usage: tinit [options]
Options:
-t, --file-type <type> 文件类型: [page,logic,service,impl,less]
-n, --file-name <name> 被创建的文件名称
-i, --is-create <is> 是否为 -t 参数自动创建相关文件类型 (default: false)
-v, --version 显示当前的版本
-h, --help display help for command
参数说明:
使用案例:
╭─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
的逻辑层文件。
多试几次,请自行熟练掌握!!
【重要】1:实现ajax
请求到的数据和model
层的映射绑定,这种数据绑定关系,可以完全解决后端改接口字段从而导致前端代码也需要同步大量修改的问题!!
【不太重要】1:实时监听configure.config.ts
配置文件,然后根据ApiList
中的对象key
名称自动在service
层的类中生成对应的方法,降低手动复制的低效率!
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。