ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

wot-design-uni Input 输入框组件完全指南:从 v-model 双向绑定到表单校验的实战详解

wot-design-uni Input 输入框组件完全指南:从 v-model 双向绑定到表单校验的实战详解
  • 前端
  • UI组件
  • 移动开发
  • 小程序

【免费下载链接】wot-design-uni

一个基于Vue3+TS开发的uni-app组件库,提供70+高质量组件,支持暗黑模式、国际化和自定义主题。

项目地址:https://gitcode.com/gh_mirrors/wo/wot-design-uni
点击查看免费下载

wd-input是 wot-design-uni 组件库(基于 Vue 3 + TypeScript 的 uni-app 组件库)中最基础、使用频率最高的表单输入组件,它基于 uni-app 原生input封装,统一了微信小程序、支付宝小程序、H5 与 App 端的行为差异。本文以官方文档 docs/component/input.md 为主线,结合组件源码 wd-input.vue、类型定义 types.ts 与测试用例 wd-input.test.ts,系统讲解它的全部用法:状态控制、清空按钮、密码框、前后图标、字数限制、label/cell 布局,以及与wd-form的联动校验,读完即可在真实项目中直接落地使用。

组件定位与版本说明

wd-input用于收集用户文本输入,支持v-model双向绑定,并内置禁用、只读、清空、密码可见性切换、字数统计、错误提示、表单校验等开箱即用的能力。

注意:自0.2.0版本起,Input组件的textarea文本域功能已迁移至 Textarea 组件,且两者 API 保持一致。因此新版中wd-input专注于单行输入,多行文本请使用wd-textarea。

从 types.ts 可以看到,组件 props 由三部分组成:baseProps(通用customStyle/customClass)、大量 uni-app 原生input属性透传(placeholder、focus、cursor-spacing、confirm-type等),以及组件自定义的增强属性(clearable、showPassword、label、rules等)。

基本用法:v-model 双向绑定与 input 事件

通过v-model双向绑定输入框的值,通过placeholder设置占位提示文字:

<wd-input type="text" v-model="value" placeholder="请输入用户名" @input="handleInput" />
const value = ref<string>('') function handleInput(event) { console.log(event) }

源码要点:在 wd-input.vue 中,handleInput会同时触发update:modelValue(驱动v-model)和input事件(透传 uni-app 原生 detail,包含value、cursor、keyCode等字段):

function handleInput({ detail }: any) { emit('update:modelValue', inputValue.value) emit('input', detail) }

组件内部通过watch监听props.modelValue,将外部值同步为内部inputValue(isDef(newValue) ? String(newValue) : ''),并在初始化时通过getInitValue对超长值做一次截断格式化。

另外,placeholder不传时并非固定空字符串,而是从国际化语言包读取默认文案。placeholderValue计算属性在未传入placeholder时回退到translate('placeholder')(见 wd-input.vue),对应语言包 zh-CN.ts 中input: { placeholder: '请输入...' },这就是文档中默认值"请输入..."的来源。

状态控制:禁用与只读

<!-- 禁用:不可输入,样式置灰 --> <wd-input v-model="value" disabled /> <!-- 只读:可聚焦但内容不可编辑 --> <wd-input v-model="value" readonly />

两者的底层实现不同:

  • disabled:直接透传到原生input的disabled属性(:disabled="disabled || readonly"),并给根节点追加is-disabled样式类,源码见 wd-input.vue。
  • readonly:除了透传 disabled 属性外,组件还会渲染一个覆盖整个输入区域的.wd-input__readonly-mask遮罩层(见 wd-input.vue),用于保证在部分平台上只读状态不被穿透点击。

测试用例 wd-input.test.ts 分别断言了is-disabled类名、input 的disabled属性和.wd-input__readonly-mask的存在。

清空按钮:clearable 与触发时机控制

设置clearable属性,输入框有内容时展示一键清空按钮:

<wd-input v-model="value" clearable @input="handleInput" />

默认清空按钮在"输入框不为空"时即展示(clearTrigger默认always)。如需聚焦且有值时才展示,设置clear-trigger="focus":

<wd-input v-model="value" clear-trigger="focus" clearable @input="handleInput" />

点击清除按钮默认会自动聚焦回输入框,若希望点击清除后不聚焦(例如键盘已弹出、清空后保持原状态),设置:focus-when-clear="false":

<wd-input type="text" :focus-when-clear="false" v-model="value" clearable />

源码剖析:清空与失焦的竞态处理

清空按钮的显隐由showClear计算属性驱动(见 wd-input.vue):

const showClear = computed(() => { const { disabled, readonly, clearable, clearTrigger } = props if (clearable && !readonly && !disabled && inputValue.value && (clearTrigger === 'always' || (props.clearTrigger === 'focus' && focusing.value))) { return true } else { return false } })

即:必须满足"可清空 + 非只读 + 非禁用 + 有值",再叠加触发时机条件。对应测试 wd-input.test.ts 验证了两种模式。

handleClear与handleBlur之间有一段精心设计的竞态处理(wd-input.vue):点击清空时,若focusWhenClear为 true,先置clearing标志、取消聚焦,await pause()(微任务)后重新聚焦;而handleBlur会await pause(150)等待 150ms 后再判断,若检测到clearing标志则跳过 blur 事件发射,避免"清空导致失焦误触发 blur"。

平台兼容提示

支付宝小程序暂不支持clear-trigger属性,且某种情况下清空按钮无法点击(该问题与 ant-design-mini 的已知 issue 同源)。因此在支付宝端做表单设计时,建议保持默认always触发,或对清空交互做降级处理。

密码输入框:show-password

设置show-password属性,输入框以密文展示,并在右侧提供眼睛图标切换明文/密文:

<wd-input v-model="value" clearable show-password @input="handleInput" />

实现原理:组件通过:password="showPassword && !isPwdVisible"将密码态透传给原生 input(wd-input.vue),点击右侧图标时调用togglePwdVisible反转isPwdVisible状态(wd-input.vue),图标在eye-close(密文)与view(明文)之间切换。测试用例 wd-input.test.ts 通过断言 input 的password属性在'true'与'false'间切换来验证该行为。

注意:show-password与type并不互斥,它通过独立布尔开关控制密文显示,即使type="text"也能生效(示例页面 src/subPages/input/Index.vue 中的密码框 demo 即为type="text" + show-password)。

前后 icon 与插槽

内置图标

设置前置 icon 使用prefix-icon,后置 icon 使用suffix-icon,值取 Icon 组件 章节中提供的图标类名:

<wd-input v-model="value" prefix-icon="dong" suffix-icon="list" @input="handleInput" />

自定义插槽

如果没有你需要的图标,使用prefix、suffix插槽进行自定义插入:

<wd-input v-model="value"> <template #prefix> <view style="padding: 0 10px;">前缀内容</view> </template> <template #suffix> <wd-button size="small">获取验证码</wd-button> </template> </wd-input>

图标点击会分别触发clickprefixicon、clicksuffixicon事件(见 wd-input.vue),可用来实现"点击搜索图标发起搜索"、"点击清除前缀"等交互。插槽优先级高于图标属性——当同时提供prefixIcon与prefix插槽时,插槽内容会覆盖图标渲染(模板中v-if="prefixIcon && !$slots.prefix"的判断逻辑)。

完整的前置/后置渲染逻辑同时存在于两种布局中:有 label 时 icon 渲染在 label 区域(wd-input.vue),无 label 时渲染在输入值区域(wd-input.vue)。

字数限制与字数统计

设置maxlength限制最大输入长度;若需显示"已输入/上限"的字数统计,同时设置show-word-limit:

<wd-input v-model="value" :maxlength="20" show-word-limit @input="handleInput" />

实现细节:

  • maxlength直接透传原生 input(wd-input.vue),默认值在支付宝小程序为无默认值,其余平台默认为-1(不限制),条件编译代码见 types.ts。
  • showWordCount计算属性要求"未禁用、未只读、maxlength 已定义且大于 -1、showWordLimit 为 true"才展示计数(wd-input.vue)。
  • 组件在初始化与外部值变化时还会通过formatValue对超过maxlength的值主动截断(value.toString().slice(0, maxlength)),保证即使外部塞入超长字符串也不会溢出(wd-input.vue)。
  • 当当前字数超过maxlength时,计数数字会追加is-error样式类变为红色(wd-input.vue)。

对应测试 wd-input.test.ts 验证了超长值截断与.wd-input__count的渲染。

label 标题与 cell 组合布局

设置label属性在左侧展示标题,可与 CellGroup 组件 组合使用,形成cell展示类型(表单列表风格):

<wd-input type="text" label="基本用法" v-model="value" placeholder="请输入..." />

配合wd-cell-group使用,每个输入项会自动获得分组边框:

<wd-cell-group border> <wd-input type="text" label="用户名" v-model="username" placeholder="请输入用户名" /> <wd-input type="text" label="手机号" v-model="phone" placeholder="请输入手机号" /> </wd-cell-group>

相关属性说明:

属性说明默认值
label-width设置左侧标题宽度33%
center设置标题和输入框垂直居中,默认为顶部居中false
requiredcell 类型下展示必填星号样式false
marker-side必填标记(星号)的位置,可选before/afterbefore
no-border非 cell 类型下隐藏底部下划线false
<!-- 设置标题宽度 --> <wd-input type="text" label="基本用法" v-model="value" label-width="100px" /> <!-- 标题与输入框垂直居中 --> <wd-input type="text" label="基本用法" v-model="value" center /> <!-- 必填样式:星号默认在标题前 --> <wd-input v-model="value" placeholder="请输入..." label="必填" required></wd-input> <!-- 必填星号放在标题后(1.12.0+) --> <wd-input v-model="value" placeholder="请输入..." label="必填" required marker-side="after" />

源码佐证:labelWidth通过labelStyle计算属性同时设置min-width与max-width(wd-input.vue);center给根节点追加is-center类,配合 index.scss 中align-items: center实现垂直居中。测试 wd-input.test.ts 验证了label-width: 100px会同时写入 min-width/max-width。

no-border的用途在示例页面 src/subPages/input/Index.vue 中有典型展示——去除下划线后,输入框可以作为行内元素嵌入到"金额 + 单位"等自定义排版中。

错误状态与表单错误提示

设置error属性,输入框内的文字显示为红色错误样式:

<wd-input type="text" v-model="value" placeholder="请输入用户名" error />

两种错误来源:

  1. 手动控制:error属性为 true 时,根节点追加is-error类,index.scss 中.is-error .wd-input__inner将文字颜色改为$input-error-color。
  2. 表单联动:当配合wd-form且设置了prop时,errorMessage计算属性会从 form 的errorMessages中按prop字段名读取错误文案,并渲染到.wd-input__error-message区域(wd-input.vue)。

输入框大小:size

通过size属性修改输入框大小,将size设置为large时字号为 16px:

<wd-input type="text" label="基本用法" size="large" v-model="value" placeholder="请输入..." />

size类型定义见 types.ts(InputSize = 'large'),根节点追加is-large类,index.scss 中large形态同步放大了内边距、字号($input-fs-large)、图标与计数尺寸。

原生属性透传与键盘控制

wd-input将 uni-app 原生input的常用属性几乎全部透传,方便在特定场景下精细控制:

属性说明默认值
type类型:text/number/digit/idcard/safe-password/nickname/teltext
confirm-type键盘右下角按钮文字:done/go/next/search/send,仅type='text'时生效done
confirm-hold点击键盘右下角按钮时是否保持键盘不收起false
focus原生属性,获取焦点false
cursor-spacing光标与键盘的距离(取 input 距底部距离与指定值的最小值)0
cursorfocus 时的光标位置-1
selection-start/selection-end自动聚焦时的光标选中起止位置,需搭配使用-1/-1
adjust-position键盘弹起时是否自动上推页面true
always-embed微信小程序原生属性,强制 input 处于同层状态(默认 focus 时切非同层,仅 iOS 生效)false
placeholder-style指定 placeholder 样式,目前仅支持color、font-size、font-weight-
placeholder-class指定 placeholder 的样式类-
inputmode提示用户可能输入的数据类型(uni-app 3.6.16+ 新增)text
enable-native支付宝小程序,enable-native="false"可避免弹出键盘后内容上移(1.14.0+)true
ignore-composition-event是否忽略组件内对文本合成系统事件的处理;为false时将触发 composition 系列事件(1.3.11+)true

示例:搜索框场景下让键盘右下角显示"搜索"按钮并监听确认事件:

<wd-input type="text" v-model="keyword" confirm-type="search" placeholder="搜索商品" @confirm="handleSearch" />
function handleSearch({ value }) { // value 为当前输入框的值 console.log('搜索:', value) }

InputMode 可选值

说明:inputmode是 HTML 规范后期更新的内容,各家小程序还未支持此属性。在符合条件的高版本 webview 里,uni-app 的 web 和 app-vue 平台中可使用本属性。新增于 uni-app 3.6.16+。

值说明
none无虚拟键盘。在应用程序或者站点需要实现自己的键盘输入控件时很有用
text使用用户本地区域设置的标准文本输入键盘
decimal小数输入键盘,包含数字和分隔符(通常是.或,),设备可能也可能不显示减号键
numeric数字输入键盘,只需要 0 到 9 的数字,设备可能也可能不显示减号键
tel电话输入键盘,包含 0 到 9 的数字、星号(*)和井号(#)键;表单输入里的电话输入通常应使用<input type="tel">
search为搜索输入优化的虚拟键盘,返回键可能被重新标记为"搜索"
email为邮件地址输入优化的虚拟键盘,通常包含@符号和其他优化;表单里的邮件地址输入应使用<input type="email">
url为网址输入优化的虚拟键盘,/键更明显、支持历史记录访问等;表单里的网址输入通常应使用<input type="url">

类型定义与默认值见 types.ts,测试 wd-input.test.ts 覆盖了全部 8 个可选值的透传。

与 wd-form 集成:表单校验(prop + rules)

wd-input深度集成了wd-form表单校验能力,这是它区别于裸原生 input 的核心价值之一。使用方式如下:

<wd-form ref="form" :model="model" :rules="rules"> <wd-input v-model="model.username" label="用户名" prop="username" placeholder="请输入用户名" /> <wd-button @click="handleSubmit">提交</wd-button> </wd-form>
const model = reactive({ username: '' }) const rules: FormRules = { username: [ { required: true, message: '请输入用户名' }, { pattern: /^[a-zA-Z0-9_]{4,16}$/, message: '用户名需为 4-16 位字母、数字或下划线' } ] } async function handleSubmit() { const { valid, errors } = await form.value.validate() if (valid) { // 提交表单 } }

关键属性

属性说明
prop表单域model字段名,在使用表单校验功能时必填
rules表单验证规则,结合wd-form组件使用,类型为FormItemRule[],默认[]

FormItemRule 规则说明

键名说明类型
required是否为必选字段boolean
message错误提示文案string
validator通过函数进行校验,可以返回一个Promise来进行异步校验(value, rule) => boolean \| Promise
pattern通过正则表达式进行校验,正则无法匹配表示校验不通过RegExp

类型定义见 wd-form/types.ts。异步校验示例(校验用户名是否被占用):

const rules: FormRules = { username: [ { validator: (value) => { return new Promise((resolve) => { setTimeout(() => { // resolve(false) 表示校验不通过,展示 message resolve(value !== 'admin') }, 500) }) }, message: '该用户名已被占用' } ] }

校验与错误展示的底层链路

wd-input通过useParent(FORM_KEY)注入父级表单上下文(wd-input.vue),其isRequired计算属性会合并三种必填来源:自身required属性、自身rules中的required规则、以及父级 form 的rules中对应prop的必填规则(wd-input.vue)。

实际校验发生在 wd-form.vue 的validate方法中:按prop取 model 值,依次执行required判空、pattern正则匹配、validator函数(支持同步返回值与Promise异步结果),收集{ prop, message }错误列表后写入errorMessages响应式对象,wd-input的errorMessage计算属性随之更新并渲染错误文案。更多用法可参考 Form 表单文档。

事件总览

事件名称说明参数最低版本
input监听输入框 input 事件{ value, cursor, keyCode }-
focus监听输入框 focus 事件{ value, height },height 为键盘高度-
blur监听输入框 blur 事件{ value }-
clear监听输入框清空按钮事件--
confirm点击键盘完成按钮时触发{ value }-
keyboardheightchange键盘高度发生变化时触发{ height, duration }-
clickprefixicon点击前置图标时触发--
clicksuffixicon点击后置图标时触发--

测试用例 wd-input.test.ts 逐一验证了input、focus、blur、clear、confirm、keyboardheightchange、clickprefixicon、clicksuffixicon事件的发射逻辑。

插槽与外部样式类

插槽(Slot)

name说明最低版本
label左侧标题插槽,可自定义标题内容-
prefix前置插槽,位于输入框左侧-
suffix后置插槽,位于输入框右侧-

外部样式类

类名说明最低版本
custom-class根节点样式-
custom-input-classinput 外部自定义样式-
custom-label-classlabel 外部自定义样式-

示例:通过外部样式类调整输入框文字样式,custom-input-class在 wd-input.vue 中被合并进原生 input 的 class 列表,可直接覆盖其字体、颜色等:

<wd-input v-model="value" custom-input-class="my-input" /> <style> .my-input { font-size: 14px; color: #4d80f0; } </style>

综合实战示例

将上述能力组合,完成一个带图标、清空、字数统计、必填校验的手机号输入项:

<wd-form ref="form" :model="formData" :rules="rules"> <wd-cell-group border> <wd-input v-model="formData.phone" prop="phone" type="tel" label="手机号" placeholder="请输入 11 位手机号" prefix-icon="dong" clearable show-word-limit :maxlength="11" required @confirm="handleConfirm" /> </wd-cell-group> <wd-button type="primary" @click="submit">提交</wd-button> </wd-form>
import { reactive, ref } from 'vue' import type { FormInstance, FormRules } from '@/uni_modules/wot-design-uni/components/wd-form/types' const form = ref<FormInstance>() const formData = reactive({ phone: '' }) const rules: FormRules = { phone: [ { required: true, message: '请输入手机号' }, { pattern: /^1[3-9]\d{9}$/, message: '手机号格式不正确' } ] } async function submit() { const { valid } = await form.value!.validate() if (valid) { console.log('提交数据:', formData) } }

小结

wd-input在原生 input 之上补齐了三类能力:交互增强(清空按钮、密码可见切换、前后图标、字数统计)、布局形态(label/cell/必填/居中/大小/无边框)与表单体系(prop 关联、rules 校验、错误文案注入),同时保留了完整的原生属性透传与键盘控制能力,是 wot-design-uni 表单场景(配合 Form、CellGroup)的基础输入单元。实际开发中建议:多行文本优先使用 Textarea;支付宝端注意clear-trigger与enable-native的平台差异;涉及校验时务必为每个输入项设置prop并定义rules。

  • 前端
  • UI组件
  • 移动开发
  • 小程序

【免费下载链接】wot-design-uni

一个基于Vue3+TS开发的uni-app组件库,提供70+高质量组件,支持暗黑模式、国际化和自定义主题。

项目地址:https://gitcode.com/gh_mirrors/wo/wot-design-uni
点击查看免费下载

相关推荐

上一篇:跨平台桌面待办工具My-TODOs:如何用极简设计告别任务焦虑?
下一篇:LogExpert终极指南:三步搞定Windows日志分析难题

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进