组件 = 模板 + 业务逻辑

简介: 各位网友大家好,今天给大家推荐我刚发布的 Vue 3 开发库 —— vue-clazz-decorator。名字里的 "clazz" 是 class 的谐音梗,为什么不直接叫 `vue-class-decorator` 呢?很简单,因为这个已经有人叫了。

各位网友大家好,今天给大家推荐我刚发布的 Vue 3 开发库 —— vue-clazz-decorator

名字里的 "clazz" 是 class 的谐音梗,为什么不直接叫 vue-class-decorator 呢?很简单,因为这个已经有人叫了。

这个库就干一件事:让你用 类 + 装饰器 写 Vue 3 组件,同时把模板和逻辑彻底解开

这个库的主要特色

  • 通过类和装饰器来写 Vue 组件
  • 方便地复用模板和逻辑
  • 保证自定义类型的纯净
  • 支持多种装饰器编译方式

创建组件

这个库的核心思想就是 【组件 = 模板 + 业务逻辑】。createComponent 这个函数就是围绕这个思想设计的,在避开 Vue 3 不能用 class 组件这个限制的同时,顺便把模板和逻辑的复用也安排得明明白白。

先看看 Vue 3 里同类库的写法,往往长这样

class HelloPage {
  render() {
    return xxxxxx;
  }
}

export default toVue(HelloPage);

能用,但总觉得拧巴:

  • render 方法硬生生塞进业务类里,UI 和逻辑搅在一起,类本身就不纯粹了;
  • 外面还得套一层转换函数,多余,但又不能没有。

我换了个更干脆的思路:模板归模板,逻辑归逻辑,两者彻底分开,最后拼一下就是组件。

@ViewModel
export class CounterViewModel {
    @State
    public count = 0;

    public increment() {
        this.count++;
    }
}
export function CounterView(props: CounterViewModel) {
    return <div>
        <p>Count: {props.count}</p>
        <button onClick={props.increment}>+1</button>
    </div>;
}

export const Counter = createComponent(CounterView, CounterViewModel);

业务逻辑全在 ViewModel 里,就是个干干净净的普通类;模板就是个纯渲染函数,不碰任何业务实现。最后 createComponent 轻轻一粘,就是个标准 Vue 组件。

这么拆开之后,很多事情就顺了:

  • 业务类想单测直接实例化测,不用挂载组件、不用模拟 DOM;
  • 同一份逻辑可以配多套模板,同一份模板也能套不同逻辑;

优雅的逻辑复用

复用逻辑,直接 use() 把另一个 ViewModel 组合进来,天然带命名空间,互不干扰。

@ViewModel
export class FooViewModel {
    ... }

@ViewModel
export class BarViewModel {
   
    public foo1 = use(FooViewModel);
    public foo2 = use(FooViewModel);
}

分页、筛选、弹窗这类通用逻辑,抽一次就能到处用,依赖关系明明白白。

组件生命周期:灵活且不设限

使用注解声明生命周期方法,不强制固定方法名。更爽的是,一个生命周期钩子可以绑定多个方法,进一步保证了类的纯净度和内聚性

@ViewModel
export class FooViewModel {
   
    @OnDidCreate
    protected init() {
   
        console.log("ViewModel created");
    }

    @OnDidMount
    protected fetchData() {
   
        console.log("拉数据");
    }
    @OnDidMount
    protected initDict() {
   
        console.log("初始化字典");
    }
}

数据模型 + 元数据能力

前面说的 ViewModel 是管组件逻辑的,那纯数据呢?前端处理后端 JSON 时往往需要许多转化规则。于是我干脆把模型层也一并做进库里了,从接口数据到业务实例,一条龙用 Class + 装饰器搞定。

模型层声明

@Model 标记一个数据模型类,字段的映射规则、格式化、类型转换全用装饰器写在类上。后端返回的原始数据,丢进 reactive() 直接就是带类型、带业务方法的响应式实例,再也不用自己手写转换函数了。

@Model
export class UserBo {
   
    @JsonProperty("user_id")  // 下划线字段自动映射
    public id: string;

    @JsonFormat("yyyy-MM-dd") // 日期自动格式化解析
    public birthday: Date;

    @Type(Dept)               // 嵌套对象自动实例化
    public dept: Dept;
}

// 后端原始数据直接转成响应式模型实例
const user = reactive(response.data, UserBo);

自定义注解,扩展性拉满

库内置了完整的元数据系统,你可以像 Java 那样自己写注解,给字段打标签,运行时直接读取配置。

做动态表单、配置化表格、低代码页面的时候特别好用 —— 模型类写完,表单和表格直接照着元数据自动渲染,不用重复写配置。

// 一行代码定义一个自定义注解
const Label = (text: string) => metadata('label', text);
const Required = metadata('required', true);

@Model
export class UserBo {
   
    @Label("用户ID")
    @Required
    public id: string;

    @Label("用户名")
    public name: string;
}

// 运行时直接读取所有字段元数据
getMetadataValues(UserBo);
// { id: { label: "用户ID", required: true }, name: { label: "用户名" } }

编译方式随便选,我都兜底了

简单说,不管你项目是 TS 还是 Babel,是老版装饰器还是新提案,直接装上就能跑,不用为编译环境折腾配置。内部 6 套 vitest 配置覆盖了这些组合,不是写着玩的。

编译方式 proposal experimental experimental + emitMetadata
typescript ✅ 支持 ✅ 支持 ✅ 支持
babel ✅ 支持 ✅ 支持 ✅ 支持

常见问题

Q:内部用的是 setup 还是 Options API?

纯 setup 实现,所有测试都是在 __VUE_OPTIONS_API__: false 环境下跑的。ViewModel 不是 Vue 的子类,就是个被 setup () 消费的普通 class 实例。

Q:有 React 版吗?

有,但 React 版是我公司内部用的。这次开源的 Vue3 版本,是我吸取了之前 React 版的经验教训,完全重构的,设计上更成熟。

Q:你这刚发布的东西,能直接上生产吗?

不建议。

如果你认同我的设计思路,我的建议是:可以先点个关注、收个藏。等我把上层管理端和移动端的框架都完整重构到 Vue3 上的时候,才是我真正推荐大家上手用的时候。

这只是整个方案的底层基石,后面还有更上层的东西要放出来。


最后

项目刚发,还热乎着。

欢迎去仓库逛逛,有想法、有 bug 都可以提。更欢迎点个 Star 蹲后续,等上层框架出来了,直接上手成品体验会好得多。

目录
相关文章
|
4月前
|
前端开发 JavaScript 安全
前端开发:不处理浏览器兼容性,才是最佳的浏览器兼容性处理方式
领导:"小明同学,用户反映你做的页面打不开。" 小明:"怎么可能,我测过多次了。" 领导发来一段视频。小明找到对应的用户日志,上面赫然写着`"foo.bar.at is not a function"`。 小明瞬间想起,自己为了简化数组取最后一个元素的逻辑,用了ES2022的新特性`Array.prototype.at()`。
256 2
|
4月前
|
存储 JavaScript 前端开发
Web 新 API cookieStore 值得用吗?
现代前端开发中,Cookie 依旧是前端存储、会话保持、跨域标识等场景不可或缺的能力。而长期以来,浏览器提供的原生 Cookie 操作方式一直依赖于 document.cookie,这套 API 从设计上就饱受诟病。随着现代 Web 标准的推进,cookieStore 作为新一代 Cookie 操作 API 被推出,很多开发者会自然产生疑问:这个新 API 到底好不好用?是否值得在业务中直接替换传统方式?本文就从实际开发体验、能力差异、适用场景三个角度,聊聊 cookieStore 到底值不值得用。
167 9
|
27天前
|
前端开发 JavaScript API
一个案例教你彻底搞明白`AbortController` 、`AbortSignal`
今天这个案例,最硬核、最扎心、最真相、最干脆、最不墨迹、最不留情面、最一针见血、最开门见山、最单刀直入、最不铺垫、最不客套、最不煽情、最不废话、最不拐弯、最不磨叽、最不装、最不端着、最不啰嗦、最不拖沓、最不委婉、最不掩饰、最不藏着掖着、最直白、最彻底、最决绝、最了当。
120 1
|
Java Android开发
如何在idea中使用jstl标签库
如何在idea中使用jstl标签库
|
2月前
|
存储
阿里云无影云电脑个人版收费价格表:黄金款、白金款、铂金款、钛金款和黑金款收费标准,2026年最新
阿里云无影云电脑个人版是面向个人/家庭的高性能云电脑,支持办公、游戏等场景。提供黄金至黑金5款套餐,含40–1000GB存储、40–640灵豆/月,连续包年低至79.9元起,支持免费试用。阿里云无影云电脑官网:https://t.aliyun.com/U/Qlbmzx
474 0
|
3月前
|
人工智能 安全 JavaScript
零代码部署OpenClaw智能体Win11详细教程(包含新版安装包)
OpenClaw(小龙虾)是GitHub星标28W+的开源本地AI智能体,专为Windows 11优化,支持一键解压即用。无需代码、免配环境,可自动操控电脑、整理文件、浏览器自动化,数据全程本地运行,隐私安全。
|
4月前
|
缓存 Java 编译器
Java 异常体系:从底层实现到性能优化的核心真相
Java异常远不止语法糖!本文深度剖析JVM异常表机制、栈轨迹生成开销、JIT四大优化(快速抛出/冷路径/异常消除/表合并),破除“try-catch拖慢性能”等四大误区,揭示异常性能损耗的真实源头,并给出业务异常关闭栈轨迹等6条生产级最佳实践。(239字)
259 8
|
运维 Kubernetes Java
Koupleless 助力「人力家」实现分布式研发集中式部署,又快又省!
通过引入Koupleless框架,解决了多应用部署中资源浪费和运维成本高的问题,实现了模块瘦身、快速部署及流量控制优化,大幅降低了服务器资源占用和发布耗时,提升了系统稳定性和运维效率。最终,人力家成功实现了多应用的轻量集中部署,显著减少了运维成本。
 Koupleless 助力「人力家」实现分布式研发集中式部署,又快又省!
|
运维 自然语言处理 Cloud Native
云栖实录 | 智能运维年度重磅发布及大模型实践解读
云栖实录 | 智能运维年度重磅发布及大模型实践解读
705 0