当前位置: 首页 > article >正文

UniApp 表单校验两种方式对比:命令式与声明式

目录

  • 前言
  • 1. 实战
  • 2. Demo

前言

🤟 找工作,来万码优才:👉 #小程序://万码优才/r6rqmzDaXpYkJZF

以下主要针对Demo讲解,从实战中的体会

何为命令式 何为声明式

  • 命令式的体验,随时都会有提交的按钮,但是点击提交才会显示不满足的条件!
    在这里插入图片描述
  • 声明式的体验,不满足条件时,按钮框是灰色的!
    在这里插入图片描述
  1. 命令式:
    提交逻辑复杂,需要异步校验(如服务端唯一性检查)
    表单字段多,依赖用户行为触发验证
    需要复用校验函数,或表单逻辑分散多处

  2. 声明式:
    表单简单明了
    用户体验优先,提前告知无法提交的情况
    状态可视化,一目了然

对比项命令式校验(方法中校验)声明式校验(computed + disabled 控制)
📋 方式在 submit() 方法内通过 validateForm() 显式校验通过 computed 计算属性实时判断是否可提交
🧠 编程范式命令式(Imperative)声明式(Declarative)
💡 表达方式手动控制流程:如果失败就 return false自动计算状态:按钮根据是否满足条件自动禁用
🔁 可复用性校验逻辑聚焦在 validateForm(),但要手动调用校验逻辑绑定在状态中,按钮等 UI 自动响应
🧪 用户体验用户点击“提交”后才提示不通过一目了然,提交按钮禁用,无法误触提交
⚙️ 灵活性可以灵活插入额外逻辑,如提交前弹窗确认逻辑适合纯状态驱动,复杂流程需另外处理
🪛 适用场景需要流程控制、嵌套逻辑、异步校验时更适合表单项简单明确、状态驱动时更适合

1. 实战

实战中抽取的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;// 执行提交逻辑console.log("提交成功");}}
}
</script>

声明式 computed 控制按钮状态

<template><button type="primary" :disabled="!canSubmit" @click="submit">提交</button>
</template><script>
export default {data() {return {photoList: {door: '',  // 对应 imgCntrFside: ''},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: '', // 箱门照片 URLdamPhotoList: [] // 破损照片 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 表单校验两种方式对比:命令式与声明式

目录 前言1. 实战2. Demo 前言 &#x1f91f; 找工作&#xff0c;来万码优才&#xff1a;&#x1f449; #小程序://万码优才/r6rqmzDaXpYkJZF 以下主要针对Demo讲解&#xff0c;从实战中的体会 何为命令式 何为声明式 命令式的体验&#xff0c;随时都会有提交的按钮&#xff…...

【树莓派Pico FreeRTOS】-Mutex(互斥体)

Mutex(互斥体) 文章目录 Mutex(互斥体)1、硬件准备2、软件准备3、FreeRTOS的Mutex介绍4、完整示例RP2040 由 Raspberry Pi 设计,具有双核 Arm Cortex-M0+ 处理器和 264KB 内部 RAM,并支持高达 16MB 的片外闪存。 广泛的灵活 I/O 选项包括 I2C、SPI 和独特的可编程 I/O (P…...

LCR 187. 破冰游戏(python3解法)

难度&#xff1a;简单 社团共有 num 位成员参与破冰游戏&#xff0c;编号为 0 ~ num-1。成员们按照编号顺序围绕圆桌而坐。社长抽取一个数字 target&#xff0c;从 0 号成员起开始计数&#xff0c;排在第 target 位的成员离开圆桌&#xff0c;且成员离开后从下一个成员开始计数…...

【漏洞修复】为了修复ARM64 Android10系统的第三方库漏洞,将ARM64 Android16的系统库直接拷贝到Android10系统如何?

直接替换系统库的风险分析 将高版本Android&#xff08;如Android 16&#xff09;的系统库直接拷贝到低版本系统&#xff08;如Android 10&#xff09;可能会导致以下问题&#xff1a; 符号与依赖不兼容 高版本库可能依赖更高版本的NDK或Bionic libc&#xff08;Android的C库&…...

Flutter环境配置

配置环境变量 PUB_HOSTED_URLhttps://pub.flutter-io.cnFLUTTER_STORAGE_BASE_URLhttps://storage.flutter-io.cn 这个命令是用来配置 Flutter 的镜像源地址&#xff0c;主要是为了解决在中国大陆地区访问 Flutter 官方资源较慢的问题。 具体的操作如下&#xff1a; 右键点…...

centOS 7.9 65bit 修复Openssh漏洞

一、背景&#xff1a; 在使用centos 7.9 64bit版本操作系统时有扫描出如下的漏洞&#xff1a; 二、修复openssh漏洞操作 升级注意事项 (一下所有的操作默认都是root或者管理员权限&#xff0c;如果遇到权限问题每个指令以及指令组合都要在前面加sudo) 1、查看CentOS操作系统信…...

金融级密码管理器——生物特征密钥绑定方案

目录 金融级密码管理器 —— 生物特征密钥绑定方案一、模块概述与设计目标1.1 模块背景与意义1.2 设计目标二、系统架构设计2.1 系统模块划分2.2 系统架构图(Mermaid示意图)三、核心算法与安全原理3.1 生物特征数据预处理3.2 密钥生成算法3.3 安全认证与密钥绑定验证3.4 密钥…...

JDBC-添加数据

文章目录 准备数据库添加数据引入数据库依赖包 准备数据库 自行安装软件&#xff0c;利用小皮内嵌的数据 添加数据 引入数据库依赖包 结构 drivercom.mysql.cj.jdbc.Driver urljdbc:mysql://127.0.0.1:3308/yanyuuserroot passwordrootpackage com.yanyu;import java.sql.*;…...

衡石科技HENGSHI SENSE异构数据关联技术深度解析:揭秘5-8倍性能提升背后的“异构过滤“架构

引言&#xff1a;多源数据关联的行业痛点 在大数据时代&#xff0c;企业数据通常分散在多个异构系统中——关系型数据库、NoSQL、数据仓库、湖仓一体平台等。根据Forrester调研&#xff0c;超过78%的企业需要同时访问5种以上不同类型的数据源进行分析&#xff0c;但传统ETL和跨…...

基于Netlify + Localtunnel 实现本地项目“无服务器”部署上线

基于Netlify Localtunnel 实现本地项目“无服务器”部署上线 1. 先看效果图2. 实现步骤2.1 分两步走2.2 netlify 部署前端资源2.3 Localtunnel 映射 localhost 服务 3. 其它工具内网穿透工具对比4. 总结5. 参考资料 1. 先看效果图 地址&#xff1a;zqchat 2. 实现步骤 2.1 …...

C#从入门到精通(3)

目录 第九章 窗体 &#xff08;1&#xff09;From窗体 &#xff08;2&#xff09;MDI窗体 &#xff08;3&#xff09;继承窗体 第十章 控件 &#xff08;1&#xff09;控件常用操作 &#xff08;2&#xff09;Label控件 &#xff08;3&#xff09;Button控件 &…...

设计模式之创建型5种

设计模式 为什么设计模式是23种创建型 对象创建为什么设计模式是23种 设计模式之所以被归纳为23种,而非其他数量,源于GoF(Gang of Four)在1994年的系统性总结和分类。这一数量的确定并非偶然,而是基于以下核心原因: 他们遵循“大三律”(Rule of Three),即只有经过三个…...

Java + LangChain 实战入门,开发大语言模型应用!

在 Baeldung 上看到了一篇介绍基于 Java LangChain 开发大语言模型应用的基础入门文章&#xff0c;写的非常不错&#xff0c;非常适合初学者。于是&#xff0c;我抽空翻译了一下。 原文地址&#xff1a;https://www.baeldung.com/java-langchain-basics翻译&#xff1a; Java…...

el-date-picker时间范围 编辑回显后不能修改问题

el-date-picker daterange时间范围 编辑回显后不能修改 <el-form-item:label"LABELS.gplanRecordDateLabel"prop"gplanRecordDate"><el-date-pickerstyle"width: 300px"v-model"formData.gplanRecordDate"type"daterang…...

Java多线程与高并发专题—— CyclicBarrier 和 CountDownLatch 有什么异同?

引入 上一篇我们了解CountDownLatch的原理和常见用法&#xff0c;在CountDownLatch的源码注释中&#xff0c;有提到&#xff1a; 另一种典型用法是将一个问题分解为 N 个部分&#xff0c;用一个Runnable描述每个部分&#xff0c;该Runnable执行相应部分的任务并对闭锁进行倒计…...

leetcode543.二叉树的直径

当前顶点作为拐点时&#xff0c;求左子树加上右子树的高度可以求出该通过该顶点的直径大小&#xff0c;再对该顶点和左右子节点作为拐点时直径大小进行比对&#xff0c;返回最大值 缺点是递归了多次 /*** Definition for a binary tree node.* public class TreeNode {* …...

Java EE 进阶:MyBatis案例练习

表白墙 首先我们先准备一下数据库的数据 创建一个信息表 DROP TABLE IF EXISTS message_info;CREATE TABLE message_info (id INT ( 11 ) NOT NULL AUTO_INCREMENT,from VARCHAR ( 127 ) NOT NULL,to VARCHAR ( 127 ) NOT NULL,message VARCHAR ( 256 ) NOT NULL,delete_fla…...

Dubbo 全面解析:从 RPC 核心到服务治理实践

一、分布式系统与 RPC 框架概述 在当今互联网时代&#xff0c;随着业务规模的不断扩大&#xff0c;单体架构已经无法满足高并发、高可用的需求&#xff0c;分布式系统架构成为主流选择。而在分布式系统中&#xff0c;远程服务调用&#xff08;Remote Procedure Call&#xff0…...

路由选型终极对决:直连/静态/动态三大类型+华为华三思科配置差异,一张表彻底讲透!

路由选型终极对决&#xff1a;直连/静态/动态三大类型华为华三思科配置差异&#xff0c;一张表彻底讲透&#xff01; 一、路由&#xff1a;互联网世界的导航系统二、路由类型深度解析三者的本质区别 三、 解密路由表——网络设备的GPS华为&#xff08;Huawei&#xff09;华三&a…...

[微信小程序]对接sse接口

[微信小程序]对接sse接口 在uni开发中&#xff0c;在微信小程序中实现sse接口请求 相关连接 微信小程序对接SSE接口记录 uni中实现sse代码 注意的坑点 接收的并不是字符串&#xff0c;而是ArrayBuffer模拟流推送并不是流推送&#xff0c;会有data:字符扰乱推送并不是完全按照…...

01 相机标定与相机模型介绍

学完本文,您将了解不同相机模型分类、内参意义,及对应的应用代码模型 标定的意义 建模三维世界点投影到二维图像平面的过程。标定输出的是相机模型。 相机模型 相机模型可以解理解为投影模型 +...

【商城实战(72)】解锁用户评价与晒单功能开发秘籍

【商城实战】专栏重磅来袭&#xff01;这是一份专为开发者与电商从业者打造的超详细指南。从项目基础搭建&#xff0c;运用 uniapp、Element Plus、SpringBoot 搭建商城框架&#xff0c;到用户、商品、订单等核心模块开发&#xff0c;再到性能优化、安全加固、多端适配&#xf…...

2025.03.27【基因分析新工具】| MAST:解锁基因表达差异分析与网络构建

文章目录 1. MAST工具简介&#xff1a;探索生物信息分析的新利器1.1 什么是MAST工具&#xff1f;1.2 MAST工具的优势1.3 MAST工具的应用场景 2. MAST的安装方法&#xff1a;轻松入门的第一步2.1 安装R语言环境2.2 安装MAST包2.3 安装依赖库 3. MAST常用命令&#xff1a;掌握数据…...

浅谈WebSocket-FLV

FLV是一种视频数据封装格式&#xff0c;这种封装被标准通信协议HTTP-FLV和RTMP协议应用。 而WebSocket-FLV是一种非标的FLV封装数据从后端发送到前端的一种方式。 在WebSocket的url请求中&#xff0c;包含了需要请求设备的视频相关信息&#xff0c;在视频数据到达时&#xff0c…...

SICAR标准 汽车焊装生产线触摸屏操作说明

目录 SIMATIC HMI 是西门子工业自动化解决方案的核心组件&#xff0c;支持实时设备监控与交互&#xff0c;文档中展示了其在焊装生产线中以SICAR标准为基础的具体应用&#xff0c;包括车型切换&#xff08;如 AY2/A26&#xff09;、KMC 夹具配置及能源效率分析&#xff0c;适用…...

CentOS 7 磁盘及分区管理笔记

一、查看磁盘信息 1. lsblk 命令 作用&#xff1a;列出系统中所有的块设备&#xff08;包括磁盘、分区等&#xff09;及其相关信息&#xff0c;如设备名称、大小、类型等。 命令格式&#xff1a;lsblk 示例&#xff1a; lsblk NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT sd…...

Unity Standard Shader 解析(一)之ForwardBase(标准版)

一、ForwardBase // Base forward pass (directional light, emission, lightmaps, ...)Pass{Name "FORWARD"Tags { "LightMode" "ForwardBase" }Blend [_SrcBlend] [_DstBlend]ZWrite [_ZWrite]CGPROGRAM#pragma target 3.0// --------------…...

关于bug总结记录

1、vs中出现bug error C1083:无法打开文件 链接&#xff1a;vs中出现bug error C1083:无法打开文件_vs20151083错误解决方法-CSDN博客 2、 VS小技巧&#xff1a;系统却提示&#xff1a;示msvcp120.dll丢失 链接&#xff1a;VS小技巧&#xff1a;系统却提示&#xff1a;示msvc…...

go - grpc入门

前期准备 工具安装及使用 grpc开发 编写proto文件 proto文件是符合Protocol Buffers语言规范的数据交换协议文件&#xff0c;就像以前WebService定义服务时使用的XML文件。现在一般都是用proto3了&#xff0c;这里创建一个名为 hello.proto 的文件&#xff0c;放到项目的pr…...

Selenium Web自动化如何快速又准确的定位元素路径,强调一遍是元素路径

如果文章对你有用&#xff0c;请给个赞&#xff01; 匹配的ChromeDriver和浏览器版本是更好完成自动化的基础&#xff0c;可以从这里去下载驱动程序&#xff1a; 最全ChromeDriver下载含win linux mac 最新版本134.0.6998.165 持续更新..._chromedriver 134-CSDN博客 如果你问…...