在 Vue3 中如何为路由 Query 参数标注类型 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
zhennann
V2EX    前端开发

在 Vue3 中如何为路由 Query 参数标注类型

  •  
  •   zhennann
    zhennann 2024-08-05 22:31:56 +08:00 1171 次点击
    这是一个创建于 462 天前的主题,其中的信息可能已经有所发展或是发生改变。

    前言

    最近发布了一款支持 IOC 容器的 Vue3 框架:Zova。与以往的 OOP 或者 Class 方案不同,Zova 在界面交互层面仍然采用 Setup 语法,仅仅在业务层面引入 IOC 容器。IOC 容器犹如一把钥匙,为我们打开了业务工程化的大门,允许我们探索更多工程化方面的设计和能力。有网友提出一个非常好的建议:可否提供一些业务场景,说明有哪些是 Class 可做而 Composable 做不了的,这样才更有说服力。

    首先说明一点,其实没有哪些业务需求是这个能做而那个不能做的。不同的编程范式带来的是不同的代码风格,不同的编程体验,从不同的路径指向开发效率和代码可维护性方面的评估。因此,最终根据用户自身的偏好和业务实际需求而定。

    那么,在这里,我们就针对这个话题如何为路由 Query 参数标注类型为例,看看 Composable 和 IOC 容器的代码风格究竟有什么不同。

    需求说明

    这里有一个页面组件 User ,可以通过 Query 传递三个参数:

    参数名 类型 缺省值
    id number 0
    name string ''
    married boolean false

    Composable:原生

    1. 访问页面

    const router = useRouter(); router.push({ path: '/test/demo/user', query: { id: 1, name: 'kevin', married: false.toString(), }, }); 

    从 Typescript 类型的角度来看,这段代码有以下两个问题:

    1. path:没有类型约束和智能提示。这会存在以下三个隐患:
      1. 记不住:如果路径较长,或者单词较复杂,就记不住路径,需要从源文件查找
      2. 写错了:如果不小心写错了,没有提示,只有到实际运行时才会暴露错误
      3. 被改了:如果后续维护代码时,路径有了变更,那么这里的代码同样没有提示,只有到实际运行时才会暴露错误
    2. query:只有有限的类型约束,与业务类型并不一致
      1. 比如不支持 Boolean 类型,必须强制转换为 String 类型

    2. 获取参数

    const route = useRoute(); const id = parseInt(route.query.id ?? 0); const name = route.query.name ?? ''; const married = route.query.married === 'true' ? true : false; 

    由于没有提供类型工具,需要针对每一个参数单独处理

    Composable:useRouteQuery

    1. 访问页面

    (同上)

    2. 获取参数

    import { useRouteQuery } from '@vueuse/router'; const id = useRouteQuery('id', 0, { transform: Number }); const name = useRouteQuery('name', ''); const married = useRouteQuery('married', 'false', { transform: value => { return value === 'true' ? true : false; }, }); 

    IOC 容器

    1. 定义类型

    import { zz } from 'zova'; export const QuerySchema = zz.object({ + id: zz.number().default(0), + name: zz.string().default(''), + married: zz.boolean().default(false), }); 
    • zz 是在 zod 基础上做的加强版,特别针对路由参数做了处理,支持 array 数组和 json 对象,具体参见:Zova: zod
    • 在定义类型的同时可以指定缺省值

    route-query-1-1.gif

    2. 访问页面

    const url = this.$router.resolvePath('/test/demo/user', { id: 0, name: 'kevin', married: false, }); this.$router.push(url); 
    • resolvePath 的参数都有类型约束和智能提示,并且与业务类型保持一致

    route-query-2.gif

    3. 获取参数

    const id = this.$query.id; const name = this.$query.name; const married = this.$query.married; 
    • 直接通过this.$query获取参数值,有明确的类型,并且不需要处理缺省值

    route-query-3.gif

    总结

    从上面的示例对比可以看出,采用 IOC 容器,可以实现定义使用的分离,而且定义侧可以通过工具来创建脚手架,进一步简化定义的书写。由于 TS 类型和缺省值等规范性代码都在定义侧完成了,那么在使用侧代码就更加简洁直观了。不知您的代码风格偏好是什么,是否还有更好的表达方式,欢迎在评论区交流。

    参考资料

    目前尚无回复
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     992 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 24ms UTC 19:19 PVG 03:19 LAX 11:19 JFK 14:19
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86