Input 文本框
v-model 双向绑定的单行输入框 / 多行文本框,默认是 outlined 样式:描边、浮动标签、可选的辅助文字与字数统计。
- 标签悬停(浮动)由 CSS 完成:聚焦或有内容时,标签上浮到描边缺口处,缺口由
fieldset/legend切出,不需要给标签加背景色,因此在任何页面背景上都正确。 variant="filled"切换为浅色填充 + 底边的样式。shape="pill"换成胶囊形搜索栏:无描边、浅色填充、40px 高、两端全圆角。- 前置 / 尾部内容用
#leading/#trailing插槽,也可以用leadingIcon/trailingIcon直接传图标数据。 type="password"自带明文切换,clearable自带清除按钮;传validator后,不通过时描边、标签、辅助文字与尾部图标一起切到错误样式。
基础用法
必填
当前值:(空)
vue
<script setup lang="ts">
import { ref } from "vue";
import { Input } from "@sharpdotnut/dotsharp";
const name = ref("");
</script>
<template>
<Input v-model="name" label="用户名" description="必填" />
</template>label 会同时作为原生 <label for> 的名称;已经用 label 时不要再传 placeholder,否则两者会在未聚焦的空状态下重叠。
字数统计
maxlength 会限制输入长度,并自动在辅助文字行的右侧显示 当前 / 上限。只想要计数、不限制长度时用 showCount。
2 / 100
vue
<script setup lang="ts">
import { ref } from "vue";
import { Input } from "@sharpdotnut/dotsharp";
const amount = ref("55");
</script>
<template>
<Input v-model="amount" label="金额" :maxlength="100" />
</template>前置与尾部内容
#leading 和 #trailing 接受任意内容:图标、图片、按钮、下拉箭头,或完全自定义的排版。
vue
<script setup lang="ts">
import { ref } from "vue";
import { Input } from "@sharpdotnut/dotsharp";
import mic from "@iconify-icons/material-symbols/mic";
import search from "@iconify-icons/material-symbols/search";
const searchText = ref("");
</script>
<template>
<Input v-model="searchText" label="搜索" :leading-icon="search" :trailing-icon="mic" />
</template>插槽优先于同名图标属性,适合放图片或交互控件:
vue
<script setup lang="ts">
import { ref } from "vue";
import { Icon, Input } from "@sharpdotnut/dotsharp";
import expandMore from "@iconify-icons/material-symbols/expand-more";
const email = ref("[email protected]");
</script>
<template>
<Input v-model="email" label="邮箱">
<template #trailing>
<button type="button" aria-label="选择邮箱">
<Icon :icon="expandMore" />
</button>
</template>
</Input>
</template>- 前置内容固定占
1.5rem宽并居中,浮动标签据此对齐描边缺口;放图片时用class="h-6 w-6 rounded-full"之类的尺寸。 - 尾部内容宽度自适应,不参与标签排版,可以放心放长文本或按钮。
- 图标建议继续用
Icon(见 Icon 图标),直接传@iconify-icons/material-symbols的图标数据。
清除与密码可见性
clearable 在有内容时显示清除按钮,点击后把模型设为 ""、回焦输入框并触发 clear 事件。type="password" 默认带明文切换按钮;revealable="false" 可关闭。
vue
<script setup lang="ts">
import { ref } from "vue";
import { Input } from "@sharpdotnut/dotsharp";
const password = ref("secret123");
</script>
<template>
<Input v-model="password" type="password" label="密码" clearable />
</template>type 直通原生 input:text、email、number、search、tel、url 等都能用;number 下模型读到的仍是字符串。
自动完成
autocomplete 是原生属性名,因此候选函数用 suggest:它接收当前输入文本,同步返回候选文本数组,渲染为与 Select / Menu 同一套规格的弹层(elevated 底色、4px 圆角、阴影、48px 行高)。
当前值:黑
vue
<script setup lang="ts">
import { ref } from "vue";
import { Input } from "@sharpdotnut/dotsharp";
const fruit = ref("黑");
const fruits = ["苹果", "杏", "香蕉", "黑莓", "蓝莓", "樱桃", "葡萄", "桃"];
function suggestFruit(input: string): string[] {
const keyword = input.trim().toLowerCase();
if (!keyword) return fruits;
return fruits.filter((item) => item.toLowerCase().includes(keyword));
}
</script>
<template>
<Input v-model="fruit" label="水果" :suggest="suggestFruit" clearable />
</template>- 聚焦或输入时打开,函数返回空数组、
Escape、Tab或点击外部时收起;用代码改v-model不会弹出候选栏。 - 键盘遵循 ARIA combobox 模式:
↓/↑移动高亮、Enter采用高亮项、Escape收起;没有高亮项时Enter仍按原生行为提交。 - 选中后模型被替换为候选文本,并触发
select事件;候选栏宽度与输入框一致,视口下方空间不足时向上展开。 - 只对单行文本框生效(
textarea忽略);disabled/readonly下不弹出。原生autocomplete属性仍照常透传给<input>。
多行文本
textarea 渲染为 <textarea>,rows 控制初始行数,maxlength / showCount / clearable 等行为保持一致。多行时标签总是浮在描边缺口上。
最多 120 个字符0 / 120
vue
<script setup lang="ts">
import { ref } from "vue";
import { Input } from "@sharpdotnut/dotsharp";
const note = ref("");
</script>
<template>
<Input
v-model="note"
textarea
label="备注"
:rows="3"
:maxlength="120"
description="最多 120 个字符"
/>
</template>Filled 变体
filled 变体
vue
<script setup lang="ts">
import { ref } from "vue";
import { Input } from "@sharpdotnut/dotsharp";
const filled = ref("晓雨");
</script>
<template>
<Input v-model="filled" variant="filled" label="名称" description="filled 变体" />
</template>filled 的标签固定在填充区顶部,聚焦时底边加粗,不使用 fieldset 缺口。
胶囊搜索栏
shape="pill" 换成胶囊形搜索栏:去掉描边、改用 --ds-surface-hover 填充、高度 40px、两端全圆角;聚焦与校验不通过用 ring 表示,不改变盒子尺寸。多行(textarea)时忽略该属性。
vue
<script setup lang="ts">
import { ref } from "vue";
import { Input } from "@sharpdotnut/dotsharp";
const searchText = ref("");
</script>
<template>
<Input v-model="searchText" shape="pill" type="search" placeholder="搜索" />
</template>- 胶囊形没有标签缺口:
label不渲染成可见标签,只作为aria-label提供给读屏,视觉提示交给placeholder。 - 胶囊形下
variant不生效(既不画描边,也不加底边)。
表单校验
validator 接收当前值,返回 false 表示通过;返回 true 或错误文案表示不通过。默认在输入与失焦时各校验一次,用 validateOn 调整;控件还暴露 validate() / clearValidate()。
vue
<script setup lang="ts">
import { ref } from "vue";
import { Input } from "@sharpdotnut/dotsharp";
const username = ref("aurora");
const usernameValidator = (value: string | number) =>
String(value).trim().length >= 2 ? false : "用户名至少 2 个字符";
</script>
<template>
<Input v-model="username" label="用户名" :validator="usernameValidator" />
</template>不通过时描边、标签、辅助文字与尾部错误图标一起切到错误样式,错误文案优先使用验证函数返回的字符串。放在 Form / FormItem 里时,Form.validate() 会一起校验;完整约定见表单指南。
API
属性
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| v-model | string | number | "" | 绑定值 |
| variant | "outlined" | "filled" | "outlined" | 容器样式 |
| shape | "default" | "pill" | "default" | 容器形状;pill 为 40px 胶囊形搜索栏(多行忽略) |
| label | string | — | 浮动标签,同时作为控件的可访问名称 |
| floatLabel | boolean | false | 标签始终上浮;默认仅在聚焦或有内容时上浮 |
| type | string | "text" | 原生 input 类型 |
| disabled | boolean | false | 禁用 |
| readonly | boolean | false | 只读 |
| textarea | boolean | false | 渲染为多行 <textarea> |
| rows | number | 3 | textarea 的初始行数 |
| clearable | boolean | false | 有内容时显示清除按钮 |
| revealable | boolean | true | type="password" 时显示明文切换按钮 |
| leadingIcon | IconifyIcon | string | — | 前置图标;#leading 插槽优先 |
| trailingIcon | IconifyIcon | string | — | 尾部图标;#trailing 插槽优先 |
| description | string | — | 辅助文字 |
| validator | (value) => boolean | string | — | 验证函数:false 通过,true / 字符串不通过 |
| validateOn | "input" | "blur" | ("input" | "blur")[] | ["input", "blur"] | 自动校验时机;传 [] 关闭自动校验 |
| maxlength | number | — | 最大长度,同时自动开启字数统计 |
| showCount | boolean | false | 只显示字数统计、不限制长度 |
| suggest | (input: string) => string[] | — | 自动完成候选函数;返回空数组时收起候选栏 |
插槽
| 插槽 | 说明 |
|---|---|
leading | 输入框前置内容,固定 1.5rem 宽并居中,通常是图标或头像图片 |
trailing | 输入框尾部内容,宽度自适应,可放图标、图片、下拉箭头或自定义按钮 |
事件
| 事件 | 说明 |
|---|---|
update:modelValue | 输入值变化 |
clear | 点击清除按钮,模型已被重置为 "" 之后触发 |
select | 从自动完成候选栏选中一项,模型已更新之后触发 |
可访问性
label通过for关联控件;校验不通过时控件带aria-invalid。- 辅助文字 / 错误信息会被控件的
aria-describedby引用。 - 清除与明文切换是原生
button,带aria-label;明文切换同时维护aria-pressed。 - 提供
suggest时控件是role="combobox"+aria-autocomplete="list",通过aria-expanded/aria-controls/aria-activedescendant关联候选栏(role="listbox"与role="option")。 - 根元素是
div:class/style作用在根元素上,其余属性与事件(id、name、autocomplete、inputmode、@blur等)透传给内部input/textarea。