Skip to content

表单:输入、校验与受控写法

表单是新用户最容易“看起来能写、实际最容易踩坑”的场景。

因为这里会同时撞上:

  • 输入事件差异
  • v-model 边界
  • 同步与异步校验
  • 提交状态管理

先看一个常见表单例子

vue
<script setup lang="ts">
import { ref } from 'wevu'

const form = ref({
  name: '',
  phone: '',
})

const errors = ref({
  name: '',
  phone: '',
})

function validate() {
  errors.value.name = form.value.name ? '' : '请输入姓名'
  errors.value.phone = /^1\d{10}$/.test(form.value.phone) ? '' : '请输入正确手机号'

  return !errors.value.name && !errors.value.phone
}

function submit() {
  if (!validate()) {
    return
  }
  console.log('submit', form.value)
}
</script>

<template>
  <view class="form">
    <input v-model="form.name" placeholder="姓名">
    <text v-if="errors.name">
      {{ errors.name }}
    </text>

    <input v-model="form.phone" placeholder="手机号">
    <text v-if="errors.phone">
      {{ errors.phone }}
    </text>

    <button @tap="submit">
      提交
    </button>
  </view>
</template>

这个例子体现了一个很适合新项目的基本思路:

  • 表单值单独放
  • 错误状态单独放
  • 校验函数和提交函数分开

输入类组件的常见处理方式

input / textarea

简单场景可以直接 v-model

picker

通常更适合显式写 :value + @change,因为它的值语义和输入框不完全一致。

例如:

vue
<picker :value="selectedIndex" :range="cityOptions" @change="onCityChange">
  <view>{{ cityOptions[selectedIndex] }}</view>
</picker>

“输入中校验”和“提交前校验”建议分开

这点特别重要。

输入中校验

适合做:

  • 长度限制提示
  • 必填提示
  • 简单格式提示

提交前校验

适合做:

  • 完整字段检查
  • 组合规则校验
  • 提交前最后拦截

异步校验要注意什么

例如手机号、用户名是否可用这类接口校验,不要每次输入都无控制地直接发请求。

更稳的思路是:

  • 做防抖
  • 只保留最后一次输入的结果
  • 不要让旧请求覆盖新结果

什么时候该考虑 bindModel

如果你表单里已经出现这种情况:

  • 不同组件事件名不一致
  • 值不都在 detail.value
  • 需要统一 number / trim / parser

那就值得继续看:

一个很实用的表单建议

不要让模板承担太多表单逻辑。 模板负责展示和触发,脚本负责:

  • 值管理
  • 错误状态
  • 提交流程
  • 校验规则

一句话总结

表单场景里,能用简单 v-model 的地方就用;一旦事件和取值开始复杂,就改成显式受控写法。

接下来建议继续看:

Released under the MIT License.