前言
最近釋出了一款支援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型別的角度來看,這段程式碼有以下兩個問題:
path:沒有型別約束和智慧提示
。這會存在以下三個隱患:記不住
:如果路徑較長,或者單詞較複雜,就記不住路徑,需要從原始檔查詢寫錯了
:如果不小心寫錯了,沒有提示,只有到實際執行時才會暴露錯誤被改了
:如果後續維護程式碼時,路徑有了變更,那麼這裡的程式碼同樣沒有提示,只有到實際執行時才會暴露錯誤
query:只有有限的型別約束,與業務型別並不一致
- 比如不支援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
- 在定義型別的同時可以指定預設值
2. 訪問頁面
const url = this.$router.resolvePath('/test/demo/user', {
id: 0,
name: 'kevin',
married: false,
});
this.$router.push(url);
- resolvePath的引數都有型別約束和智慧提示,並且與業務型別保持一致
3. 獲取引數
const id = this.$query.id;
const name = this.$query.name;
const married = this.$query.married;
- 直接透過
this.$query
獲取引數值,有明確的型別,並且不需要處理預設值
總結
從上面的示例對比可以看出,採用IOC容器,可以實現定義
與使用
的分離,而且定義
側可以透過工具來建立腳手架,進一步簡化定義
的書寫。由於TS型別和預設值等規範性程式碼都在定義
側完成了,那麼在使用
側程式碼就更加簡潔直觀了。不知您的程式碼風格偏好是什麼,是否還有更好的表達方式,歡迎在評論區交流。
參考資料
- VueUse: useRouteQuery
- Zova: 路由Query