- 我查看了市面上所有的表單庫,都有一個致命的缺點,定義多次才能實現表單
- 比如,像下面的代碼(偽代碼)
interface Test {
firstName: string;
}
const form = useForm<Test>({
defaultValues: {
firstName: "default",
},
onSubmit: async ({ value }) => {
console.log(value);
},
});
<form.Field
name="firstName"
//...
/>
- 眾所周知,實現的越多,那麼未來出現錯誤的概率越大
- 像上面的場景,如果我們想修改
firstName為name,那麼至少需要修改三次,這極大的增加了代碼的不穩定性 - 所以我實現了一個表單庫皮影.僅用一次定義,實現了以上所有邏輯
v.object({ firstName: v.optional(v.string(), "default") });
皮影是如何實現上面的邏輯的?
- 首先感謝valibot,上面的代碼其實就是一個簡單的
schema定義 - 皮影實現了一個遍歷器,收集相關元數據
- 然後將元數據轉換為組件和表單配置
- 使其可以在任何前端框架上使用
定義是固定的,那麼怎麼實現佈局呢?
- 皮影實現了佈局移動,通過
layout方法可以將任何控件移動到可以存在子級的schema中
v.intersect([
v.pipe(v.object({}), setAlias("scope1")),
v.object({
key1: v.pipe(
v.object({
test1: v.pipe(v.optional(v.string(), "value1"), layout({ keyPath: ["#", "@scope1"] })),
}),
),
}),
]);
- 也就是説,定義雖然是固定的,但是在視圖中是可以自由決定位置的,做到了定義與視圖位置分離
- 關於
object的字段順序,則可以參照MDN
如何進行更加高級的佈局?
- 我們都知道,有時候不僅僅要顯示字段,可能還需要更多額外的功能
- 比如控件的標籤,驗證,懸停提示,則可以通過包裝器實現
v.pipe(v.number(), v.title("k2-label"), setWrappers(["label"]));
-
而如果要修改空間組的樣式,則可以自定義組件
雖然包裝器也可以用於控件組,但是直接自定義會更方便些
v.pipe(
v.object({
k1: v.pipe(v.string(), v.title("k1-label"), setWrappers(["label"])),
k2: v.pipe(v.number(), v.title("k2-label"), v.minValue(10), setWrappers(["label", "validator"])),
}),
setComponent("fieldset"),
);
如何自定義包裝器/組件?
- 上面的一些代碼,我並沒有説是應用於哪個前端框架,因為它們都是通用的
- 而包裝器和組件的定義卻是每個框架各有不同的方法
- 大家可以查看快速開始查找自己所使用的框架的定義方法.目前已支持
Angular,Vue,React,如果您還需要其他框架兼容,歡迎反饋
現在是否可以使用?
- 皮影表單在正式開源之前,已經經過半年以上的內部使用,絕大部分功能已經經過嚴格的測試.代碼覆蓋率達到了95%以上;完全可以應用於生成環境
- 皮影表單實現了很多的用例演示及對市面上的主流庫的用例做了等價的實現,方便大家遷移
- ngx-formly 用例實現
- vee-validate 用例實現
- formik 用例實現
- react-hook-form 用例實現
- react-tanstack用例實現
項目地址
- piying-view
-
視頻講解
聯繫我
- 如果您有任何意見或建議,歡迎聯繫我
wszgrcy@gmail.com