马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
×
前言
🤟 找工作,来万码优才:👉 #小步伐://万码优才/r6rqmzDaXpYkJZF
以下重要针对Demo教学,从实战中的领会
作甚下令式 作甚声明式
- 下令式的体验,随时都会有提交的按钮,但是点击提交才会表现不满意的条件!
- 声明式的体验,不满意条件时,按钮框是灰色的!
- 下令式:
提交逻辑复杂,须要异步校验(如服务端唯一性查抄)
表单字段多,依赖用户活动触发验证
须要复用校验函数,或表单逻辑分散多处
- 声明式:
表单简朴明白
用户体验优先,提前告知无法提交的情况
状态可视化,一清二楚
对比项下令式校验(方法中校验)声明式校验(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: '', // 对应 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>
复制代码 |