Input 输入框
单行文本录入的基础控件。只承载「取值」这一件事:值完全由 v-model 控制,组件内部不缓存输入内容,因此可以安全地做格式化、过滤或异步校验。
代码演示
基础用法
v-model 绑定字符串,输入过程实时同步;下方两个输入框共用同一个 ref,在任意一个里输入都会同步到另一个。
<script setup lang="ts">
import { ref } from 'vue'
const keyword = ref('')
</script>
<template>
<div class="m-row-demo--col">
<MInput v-model="keyword" placeholder="搜索组件" clearable width="200px" />
<MInput v-model="keyword" placeholder="同一个 v-model" width="200px" />
</div>
</template>尺寸
size 三档对应全局令牌 --m-size-small(28px)、--m-size-default(36px)、--m-size-large(48px)。
<script setup lang="ts">
import { ref } from 'vue'
const small = ref('small')
const normal = ref('default')
const large = ref('large')
</script>
<template>
<div class="m-row-demo--col">
<MInput v-model="small" size="small" placeholder="small 28px" width="260px" />
<MInput v-model="normal" size="default" placeholder="default 36px" width="260px" />
<MInput v-model="large" size="large" placeholder="large 48px" width="260px" />
</div>
</template>前后缀插槽
prefix / suffix 分别渲染在输入框左右两侧,可以直接放 MIcon、货币符号或纯文本。
往 suffix 里放计数表达式,就是一个现成的字数指示器。
<script setup lang="ts">
import { ref } from 'vue'
import { mdiAccountOutline, mdiMagnify } from '@mdi/js'
const account = ref('')
const keyword = ref('')
const amount = ref('')
</script>
<template>
<div class="m-row-demo--col">
<MInput v-model="account" placeholder="用户名" width="280px">
<template #prefix>
<MIcon :path="mdiAccountOutline" :size="18" />
</template>
</MInput>
<MInput v-model="keyword" placeholder="搜索" clearable width="280px">
<template #prefix>
<MIcon :path="mdiMagnify" :size="18" />
</template>
<template #suffix>{{ keyword.length }}</template>
</MInput>
<MInput v-model="amount" placeholder="金额" width="280px">
<template #prefix>¥</template>
<template #suffix>.00</template>
</MInput>
</div>
</template>清除与字数限制
clearable 在「有值且非只读、非禁用」时显示清除按钮,点击后清空并重新聚焦;maxlength 透传给原生 input。
点击清除会触发 clear 事件,这里用 toast.info() 给出反馈。
<script setup lang="ts">
import { ref } from 'vue'
import { toast } from 'miao-design'
const remark = ref('输入内容后右侧出现清除按钮')
const limited = ref('')
function onClear() {
toast.info('已清空输入内容')
}
</script>
<template>
<div class="m-row-demo--col">
<MInput
v-model="remark"
placeholder="试试点右侧的 × 清空"
clearable
width="280px"
@clear="onClear" />
<MInput v-model="limited" :maxlength="10" placeholder="最多 10 个字" width="280px">
<template #suffix>{{ limited.length }}/10</template>
</MInput>
</div>
</template>只读、禁用与原生 type
readonly 保留聚焦与选中复制能力但不接受输入,disabled 完全阻断交互;type 直接透传给原生 input。
<script setup lang="ts">
import { ref } from 'vue'
const readonlyText = ref('这段文字可以选中复制,但不能修改')
const password = ref('')
const number = ref('')
</script>
<template>
<div class="m-row-demo--col">
<MInput v-model="readonlyText" readonly width="280px" />
<MInput v-model="password" type="password" placeholder="type=password" width="280px" />
<MInput v-model="number" type="number" placeholder="type=number" width="280px" />
<MInput model-value="禁用状态,不可聚焦" disabled width="280px" />
</div>
</template>圆角与宽度
radius 接受任意 CSS 长度并写入 --m-control-radius,width 覆盖组件默认宽度。
<script setup lang="ts">
import { ref } from 'vue'
const sharp = ref('radius="0"')
const normal = ref('radius="4px"')
const pill = ref('radius="999px"')
const fixed = ref('width="200px"')
</script>
<template>
<div class="m-row-demo--col">
<MInput v-model="sharp" radius="0" width="280px" />
<MInput v-model="normal" radius="4px" width="280px" />
<MInput v-model="pill" radius="999px" width="280px" />
<MInput v-model="fixed" width="200px" />
</div>
</template>API
Props
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
modelValue | string | undefined(内部按 '' 处理) | 输入值(v-model) |
type | string | 'text' | 原生 input 的 type |
placeholder | string | undefined(未提供) | 占位文本 |
disabled | boolean | false | 是否禁用 |
readonly | boolean | false | 是否只读 |
clearable | boolean | false | 有值时显示清除按钮(readonly / disabled 时不显示) |
size | 'small' | 'default' | 'large' | 'default' | 高度取全局 --m-size-* 令牌:small 28px / default 36px / large 48px |
maxlength | number | undefined(未提供) | 最大输入长度(原生 maxlength) |
name | string | undefined(未提供) | 原生 input 的 name(表单提交) |
autofocus | boolean | undefined(未提供) | 自动聚焦 |
width | string | undefined(未提供;样式默认 220px) | 宽度 |
radius | string | undefined(未提供) | 输入框圆角(任意 CSS 长度,如 '8px');默认 4px |
Events
| 事件 | 参数 | 说明 |
|---|---|---|
update:modelValue | value: string | 输入值变化 |
focus | event: FocusEvent | 聚焦 |
blur | event: FocusEvent | 失焦 |
change | value: string | 失焦时触发 |
clear | 无 | 点击清除按钮 |
Slots
| 插槽 | 参数 | 说明 |
|---|---|---|
prefix | 无 | 输入框左侧附加内容 |
suffix | 无 | 输入框右侧附加内容 |
类型定义
export type InputSize = 'small' | 'default' | 'large';Expose:源码未暴露实例方法,需要操作原生输入框时请通过 focus / blur 事件配合模板引用处理。
使用建议
change 是「失焦时」触发
change 不是每次输入都抛,而是失焦(blur)时抛出当前值,语义与原生 change 一致。需要实时响应请用 update:modelValue(即 v-model)。
清除按钮的出现条件
清除按钮仅在 clearable && !disabled && !readonly && 有值 时渲染。如果只读输入框也需要「清空」动作,请在业务层放一个独立的按钮。
v-model 值请用字符串
modelValue 的类型是 string。传入 number 不会被自动转换,而是被 String() 处理后渲染,回写时仍是字符串——需要数字请改用 InputNumber 数字输入框。
相关组件
- InputNumber 数字输入框:数值录入、步进与精度控制。
- Select 选择器:从固定选项中选择,替代自由文本。
- Checkbox 复选框 / Radio 单选框:布尔值与互斥单选的录入。