UniApp表單校驗兩種方式對比詳解
以下主要針對Demo講解,從實戰(zhàn)中的體會
何為命令式 何為聲明式
- 命令式的體驗,隨時都會有提交的按鈕,但是點擊提交才會顯示不滿足的條件!
- 聲明式的體驗,不滿足條件時,按鈕框是灰色的!
命令式:
提交邏輯復雜,需要異步校驗(如服務端唯一性檢查)
表單字段多,依賴用戶行為觸發(fā)驗證
需要復用校驗函數(shù),或表單邏輯分散多處聲明式:
表單簡單明了
用戶體驗優(yōu)先,提前告知無法提交的情況
狀態(tài)可視化,一目了然
對比項 | 命令式校驗(方法中校驗) | 聲明式校驗(computed + disabled 控制) |
---|---|---|
方式 | 在 submit() 方法內(nèi)通過 validateForm() 顯式校驗 | 通過 computed 計算屬性實時判斷是否可提交 |
編程范式 | 命令式(Imperative) | 聲明式(Declarative) |
表達方式 | 手動控制流程:如果失敗就 return false | 自動計算狀態(tài):按鈕根據(jù)是否滿足條件自動禁用 |
可復用性 | 校驗邏輯聚焦在 validateForm(),但要手動調(diào)用 | 校驗邏輯綁定在狀態(tài)中,按鈕等 UI 自動響應 |
用戶體驗 | 用戶點擊“提交”后才提示不通過 | 一目了然,提交按鈕禁用,無法誤觸提交 |
靈活性 | 可以靈活插入額外邏輯,如提交前彈窗確認 | 邏輯適合純狀態(tài)驅(qū)動,復雜流程需另外處理 |
適用場景 | 需要流程控制、嵌套邏輯、異步校驗時更適合 | 表單項簡單明確、狀態(tài)驅(qū)動時更適合 |
1. 實戰(zhàn)
實戰(zhàn)中抽取的Demo比較簡易:
命令式 submit 校驗方式(validateForm)
<template> <button type="primary" @click="submit">提交</button> </template> <script> export default { data() { return { imgCntrF: [], damPhotoList: [] }; }, methods: { validateForm() { if (!this.imgCntrF.length) { uni.showToast({ title: '請拍攝箱門照片', icon: 'none' }); return false; } if (this.damPhotoList.length < 2) { uni.showToast({ title: '請至少拍攝 2 張照片', icon: 'none' }); return false; } return true; }, async submit() { if (!this.validateForm()) return; // 執(zhí)行提交邏輯 console.log("提交成功"); } } } </script>
聲明式 computed 控制按鈕狀態(tài)
<template> <button type="primary" :disabled="!canSubmit" @click="submit">提交</button> </template> <script> export default { data() { return { photoList: { door: '', // 對應 imgCntrF side: '' }, damPhotoList: [], photoField: [ { key: 'door', label: '箱門照片' }, { key: 'side', label: '側面照片' } ] }; }, computed: { canSubmit() { return this.photoField.every(field => this.photoList[field.key]) && this.damPhotoList.length >= 2; } }, methods: { submit() { console.log("提交成功"); } } } </script>
2. Demo
以UniApp( Vue2 語法 + script 寫法)
命令式校驗提交(Imperative)
<template> <view class="container"> <view class="section"> <text>箱門照片:</text> <button @click="selectBoxDoorPhoto">選擇照片</button> <image v-if="imgCntrF" :src="imgCntrF" class="img-preview" /> </view> <view class="section"> <text>破損照片:</text> <button @click="addDamPhoto">添加照片</button> <view class="photo-list"> <image v-for="(photo, index) in damPhotoList" :key="index" :src="photo" class="img-preview" /> </view> </view> <button type="primary" @click="submit">提交</button> </view> </template> <script> export default { data() { return { imgCntrF: '', // 箱門照片 URL damPhotoList: [] // 破損照片 URL 列表 }; }, methods: { selectBoxDoorPhoto() { uni.chooseImage({ count: 1, success: (res) => { this.imgCntrF = res.tempFilePaths[0]; } }); }, addDamPhoto() { uni.chooseImage({ count: 1, success: (res) => { this.damPhotoList.push(res.tempFilePaths[0]); } }); }, validateForm() { if (!this.imgCntrF) { uni.showToast({ title: '請拍攝箱門照片', icon: 'none' }); return false; } if (this.damPhotoList.length < 2) { uni.showToast({ title: '請至少拍攝 2 張破損照片', icon: 'none' }); return false; } return true; }, submit() { if (!this.validateForm()) return; // 模擬提交成功 uni.showToast({ title: '提交成功', icon: 'success' }); } } }; </script> <style> .container { padding: 20rpx; } .section { margin-bottom: 30rpx; } .img-preview { width: 200rpx; height: 200rpx; margin-top: 10rpx; } .photo-list { display: flex; flex-wrap: wrap; gap: 10rpx; } </style>
聲明式按鈕控制提交(Declarative)
<template> <view class="container"> <view class="section"> <text>箱門照片:</text> <button @click="selectBoxDoorPhoto">選擇照片</button> <image v-if="photoList.door" :src="photoList.door" class="img-preview" /> </view> <view class="section"> <text>破損照片:</text> <button @click="addDamPhoto">添加照片</button> <view class="photo-list"> <image v-for="(photo, index) in damPhotoList" :key="index" :src="photo" class="img-preview" /> </view> </view> <button type="primary" :disabled="!canSubmit" @click="submit">提交</button> </view> </template> <script> export default { data() { return { photoList: { door: '' // 箱門照片 }, damPhotoList: [] }; }, computed: { canSubmit() { return !!this.photoList.door && this.damPhotoList.length >= 2; } }, methods: { selectBoxDoorPhoto() { uni.chooseImage({ count: 1, success: (res) => { this.photoList.door = res.tempFilePaths[0]; } }); }, addDamPhoto() { uni.chooseImage({ count: 1, success: (res) => { this.damPhotoList.push(res.tempFilePaths[0]); } }); }, submit() { uni.showToast({ title: '提交成功', icon: 'success' }); } } }; </script> <style> .container { padding: 20rpx; } .section { margin-bottom: 30rpx; } .img-preview { width: 200rpx; height: 200rpx; margin-top: 10rpx; } .photo-list { display: flex; flex-wrap: wrap; gap: 10rpx; } </style>
到此這篇關于UniApp表單校驗兩種方式對比詳解的文章就介紹到這了,更多相關UniApp表單校驗方式內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
Object.defineProperty()?完整指南示例詳解
本文深入理解`Object.defineProperty()`的方法,包括基礎概念、屬性描述符的完整選項、常見使用場景等,感興趣的朋友跟隨小編一起看看吧2025-01-01詳解JS: reduce方法實現(xiàn) webpack多文件入口
本篇文章主要介紹了詳解JS: reduce方法實現(xiàn) webpack多文件入口,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-02-02微信小程序基于高德地圖API實現(xiàn)天氣組件(動態(tài)效果)
這篇文章主要介紹了微信小程序基于高德地圖API實現(xiàn)天氣組件(動態(tài)效果),本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-10-10JavaScript將坐標字符串轉(zhuǎn)為數(shù)組的項目實踐
本文主要介紹了JavaScript將坐標字符串轉(zhuǎn)為數(shù)組的項目實踐,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2024-01-01JavaScript中變量提升導致未定義(undefined)的問題及解決方法
在 JavaScript 中,變量提升(Hoisting)是一個相對常見的行為,尤其是當你遇到 undefined 錯誤時,本文將詳細探討變量提升的概念、其對代碼執(zhí)行的影響以及如何避免因為變量提升而導致 undefined 的問題,需要的朋友可以參考下2024-09-09