UniApp表單校驗(yàn)兩種方式對比詳解
以下主要針對Demo講解,從實(shí)戰(zhàn)中的體會
何為命令式 何為聲明式
- 命令式的體驗(yàn),隨時(shí)都會有提交的按鈕,但是點(diǎn)擊提交才會顯示不滿足的條件!
- 聲明式的體驗(yàn),不滿足條件時(shí),按鈕框是灰色的!
命令式:
提交邏輯復(fù)雜,需要異步校驗(yàn)(如服務(wù)端唯一性檢查)
表單字段多,依賴用戶行為觸發(fā)驗(yàn)證
需要復(fù)用校驗(yàn)函數(shù),或表單邏輯分散多處聲明式:
表單簡單明了
用戶體驗(yàn)優(yōu)先,提前告知無法提交的情況
狀態(tài)可視化,一目了然
對比項(xiàng) | 命令式校驗(yàn)(方法中校驗(yàn)) | 聲明式校驗(yàn)(computed + disabled 控制) |
---|---|---|
方式 | 在 submit() 方法內(nèi)通過 validateForm() 顯式校驗(yàn) | 通過 computed 計(jì)算屬性實(shí)時(shí)判斷是否可提交 |
編程范式 | 命令式(Imperative) | 聲明式(Declarative) |
表達(dá)方式 | 手動控制流程:如果失敗就 return false | 自動計(jì)算狀態(tài):按鈕根據(jù)是否滿足條件自動禁用 |
可復(fù)用性 | 校驗(yàn)邏輯聚焦在 validateForm(),但要手動調(diào)用 | 校驗(yàn)邏輯綁定在狀態(tài)中,按鈕等 UI 自動響應(yīng) |
用戶體驗(yàn) | 用戶點(diǎn)擊“提交”后才提示不通過 | 一目了然,提交按鈕禁用,無法誤觸提交 |
靈活性 | 可以靈活插入額外邏輯,如提交前彈窗確認(rèn) | 邏輯適合純狀態(tài)驅(qū)動,復(fù)雜流程需另外處理 |
適用場景 | 需要流程控制、嵌套邏輯、異步校驗(yàn)時(shí)更適合 | 表單項(xiàng)簡單明確、狀態(tài)驅(qū)動時(shí)更適合 |
1. 實(shí)戰(zhàn)
實(shí)戰(zhàn)中抽取的Demo比較簡易:
命令式 submit 校驗(yàn)方式(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: '', // 對應(yīng) imgCntrF side: '' }, damPhotoList: [], photoField: [ { key: 'door', label: '箱門照片' }, { key: 'side', label: '側(cè)面照片' } ] }; }, 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 寫法)
命令式校驗(yàn)提交(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>
到此這篇關(guān)于UniApp表單校驗(yàn)兩種方式對比詳解的文章就介紹到這了,更多相關(guān)UniApp表單校驗(yàn)方式內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Object.defineProperty()?完整指南示例詳解
本文深入理解`Object.defineProperty()`的方法,包括基礎(chǔ)概念、屬性描述符的完整選項(xiàng)、常見使用場景等,感興趣的朋友跟隨小編一起看看吧2025-01-01詳解JS: reduce方法實(shí)現(xiàn) webpack多文件入口
本篇文章主要介紹了詳解JS: reduce方法實(shí)現(xiàn) webpack多文件入口,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-02-02微信小程序基于高德地圖API實(shí)現(xiàn)天氣組件(動態(tài)效果)
這篇文章主要介紹了微信小程序基于高德地圖API實(shí)現(xiàn)天氣組件(動態(tài)效果),本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-10-10JavaScript cookie的設(shè)置獲取刪除詳解
這篇文章主要介紹了JavaScript cookie的設(shè)置獲取刪除等等,,需要的朋友可以參考下2014-02-02JavaScript將坐標(biāo)字符串轉(zhuǎn)為數(shù)組的項(xiàng)目實(shí)踐
本文主要介紹了JavaScript將坐標(biāo)字符串轉(zhuǎn)為數(shù)組的項(xiàng)目實(shí)踐,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2024-01-01JS正則驗(yàn)證多個(gè)郵箱完整實(shí)例【郵箱用分號隔開】
這篇文章主要介紹了JS正則驗(yàn)證多個(gè)郵箱的方法,且郵箱字符串使用分號隔開,非常簡單實(shí)用,需要的朋友可以參考下2017-04-04JavaScript中變量提升導(dǎo)致未定義(undefined)的問題及解決方法
在 JavaScript 中,變量提升(Hoisting)是一個(gè)相對常見的行為,尤其是當(dāng)你遇到 undefined 錯誤時(shí),本文將詳細(xì)探討變量提升的概念、其對代碼執(zhí)行的影響以及如何避免因?yàn)樽兞刻嵘鴮?dǎo)致 undefined 的問題,需要的朋友可以參考下2024-09-09