最近发布了一款支持IOC容器的Vue3框架:Zova。与以往的OOP或者Class方案不同,Zova在界面交互层面仍然采用Setup语法,仅仅在业务层面引入IOC容器。IOC容器犹如一把钥匙,为我们打开了业务工程化的大门,允许我们探索更多工程化方面的设计和能力。有网友提出一个非常好的建议:可否提供一些业务场景,说明有哪些是Class可做而Composable做不了的,这样才更有说服力。
首先说明一点,其实没有哪些业务需求是这个能做而那个不能做的。不同的编程范式带来的是不同的代码风格,不同的编程体验,从不同的路径指向开发效率和代码可维护性方面的评估。因此,最终根据用户自身的偏好和业务实际需求而定。
那么,在这里,我们就针对这个话题,如何为路由Query参数标注类型,为例,看看Composable和IOC容器的代码风格究竟有什么不同。
这里有一个页面组件User,可以通过Query传递三个参数:
参数名 | 类型 | 缺省值 |
---|---|---|
id | number | 0 |
name | string | ” |
married | boolean | false |
const router = useRouter();
router.push({
path: ‘/test/demo/user’,
query: {
id: 1,
name: ‘kevin’,
married: false.toString(),
},
});
从Typescript类型的角度来看,这段代码有以下两个问题:
path:没有类型约束和智能提示
记不住
写错了
被改了
query:只有有限的类型约束,与业务类型并不一致
const route = useRoute();
const id = parseInt(route.query.id ?? 0);
const name = route.query.name ?? ”;
const married = route.query.married === ‘true’ ? true : false;
由于没有提供类型工具,需要针对每一个参数单独处理
(同上)
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;
},
});
import { zz } from ‘zova’;
export const QuerySchema = zz.object({
id: zz.number().default(0),
name: zz.string().default(”),
married: zz.boolean().default(false),
});
const url = this.$router.resolvePath(‘/test/demo/user’, {
id: 0,
name: ‘kevin’,
married: false,
});
this.$router.push(url);
const id = this.$query.id;
const name = this.$query.name;
const married = this.$query.married;
this.$query
从上面的示例对比可以看出,采用IOC容器,可以实现
定义
与
使用
的分离,而且
定义
侧可以通过工具来创建脚手架,进一步简化
定义
的书写。由于TS类型和缺省值等规范性代码都在
定义
侧完成了,那么在
使用
侧代码就更加简洁直观了。不知您的代码风格偏好是什么,是否还有更好的表达方式,欢迎在评论区交流。