This commit is contained in:
oneao committed 2026-10-08 22:38:34 +08:00
1 parent f572dce2f6
commit e99a9fb274
356 files changed
+28877 -1055

No files matched your search

@@ -0,0 +1,167 @@
---
title: Input 输入框
description: 单行 / 密码 / 数字 / 多行四种模式,支持清除、前后缀与字数统计
---
# Input 输入框
`Input` 是受控输入控件:值通过 `v-model` 双向绑定,`type` 决定它是单行、密码、数字还是多行文本。
## 何时使用
- 录入短文本(名称、标题、编码)用默认模式;
- 密码输入用 `type="password"`(自带显示/隐藏切换);
- 只允许数字的字段用 `type="number"`(限制字符并转换类型);
- 描述、备注等多行文本用 `type="textarea"`;
- 需要从固定选项里选值,请用 [Select](/ui/form/select)。
## 基础用法
:::demo{name="input/basic"}
:::
`v-model` 的值类型是 `string`;`type="number"` 时提交值为 `number`(空值保留为 `''`)。
## 密码输入
`type="password"` 会在右侧渲染一个显示/隐藏按钮,按钮带 `aria-pressed` 与无障碍标签。
:::demo{name="input/password"}
:::
密码框建议同时设置 `autocomplete="current-password"`,让浏览器密码管理器正确识别。
## 数字输入
`type="number"` 做了三件事:过滤非数字字符、保留输入中间态(`12.` 不会被打断)、**失焦或回车时把字符串提交为 `Number`**。
:::demo{name="input/number"}
:::
## 多行文本
`rows` 是初始行数;`show-count` 显示字数统计;右下角有拖拽手柄,可以拖拽或聚焦后用 `↑ / ↓ / Home` 调整高度(聚焦后是 `role="slider"`)。
:::demo{name="input/textarea"}
:::
## 可清除
`allowClear` 时,有值且 hover / 聚焦会出现清除按钮;点击清空值并触发 `clear` 事件。
:::demo{name="input/clearable"}
:::
## 前后缀插槽
`#prefix` / `#suffix` 放图标或单位,图标尺寸跟随字号(`1em`)。
:::demo{name="input/slots"}
:::
## 校验状态
`status` 让输入框表达校验结果:`error` 红边、`warning` 黄边。配合 `G3FormItem` 时通常由表单自动管理,无需手写。
:::demo{name="input/status"}
:::
## 实例方法
通过 `ref` 调用 `focus(options)` / `select()` / `blur()`,用于「点击单元格进入编辑」这类交互:
```ts
const inputRef = ref<InstanceType<typeof G3Input> | null>(null)
inputRef.value?.focus({ cursor: 'all' }) // 聚焦并全选
inputRef.value?.focus({ preventScroll: true }) // 聚焦但不滚动页面
```
:::demo{name="input/methods"}
:::
## API
### Props
| 名称 | 类型 | 默认值 | 说明 |
| --- | --- | --- | --- |
| `modelValue` | `string \| number` | `''` | 双向绑定的值 |
| `type` | `'default' \| 'password' \| 'number' \| 'textarea'` | `'default'` | 输入模式 |
| `disabled` | `boolean` | `false` | 禁用态 |
| `readonly` | `boolean` | `false` | 只读态:可聚焦、可复制,但不可修改 |
| `status` | `'' \| 'error' \| 'warning'` | `''` | 校验状态 |
| `allowClear` | `boolean` | `false` | 有值时显示清除按钮(hover / 聚焦时出现),多行模式不支持 |
| `showCount` | `boolean` | `false` | 显示字数统计(`maxlength` 存在时显示 `当前 / 上限`) |
| `maxlength` | `string \| number` | — | 最大长度,透传给原生 `maxlength` |
| `rows` | `string \| number` | `3` | 多行模式的初始行数(仅 `textarea` 生效) |
| `placeholder` | `string` | — | 占位文案。声明为 prop 是为了让它落到内部 `<input>` 而不是外层容器 |
| `autocomplete` | `string` | — | 浏览器自动填充语义,如 `username` / `current-password` / `off` |
### Events
| 名称 | 参数 | 说明 |
| --- | --- | --- |
| `update:modelValue` | `(value: string \| number)` | 输入时触发。`number` 模式提交 `number`,清空时为 `''` |
| `change` | `(value: string \| number, event: Event)` | 原生 `change`(失焦或回车后值变化)。`number` 模式在此时完成类型转换 |
| `focus` | `(event: FocusEvent)` | 获得焦点 |
| `blur` | `(event: FocusEvent)` | 失去焦点 |
| `clear` | `()` | 点击清除按钮(此时 `update:modelValue` 先发出 `''`) |
### Slots
| 名称 | 参数 | 说明 |
| --- | --- | --- |
| `prefix` | — | 输入框左侧内容(图标、单位),多行模式不渲染 |
| `suffix` | — | 输入框右侧内容,多行模式不渲染 |
### Exposed(通过 ref 调用)
| 名称 | 签名 | 说明 |
| --- | --- | --- |
| `focus` | `(options?: { preventScroll?: boolean; cursor?: 'all' }) => void` | 聚焦;`cursor: 'all'` 聚焦后全选 |
| `select` | `() => void` | 选中全部内容 |
| `blur` | `() => void` | 失焦 |
### 类型定义
```ts
export type InputType = 'default' | 'password' | 'number' | 'textarea'
export type InputStatus = '' | 'error' | 'warning'
export interface InputProps {
modelValue?: string | number
type?: InputType
disabled?: boolean
readonly?: boolean
status?: InputStatus
allowClear?: boolean
showCount?: boolean
maxlength?: string | number
rows?: string | number
placeholder?: string
autocomplete?: string
}
export interface InputFocusOptions {
preventScroll?: boolean
cursor?: 'all'
}
```
### 样式变量
| 变量 | 默认值 | 说明 |
| --- | --- | --- |
| `--g3-control-height` | `32px` | 输入框高度(单行) |
| `--g3-input-resize-handle` | 右下角手柄 | 多行模式的拖拽手柄位置由组件内部处理 |
| `--g3-color-primary` / `--g3-color-primary-ring` | `#18181b` / 主色 20% | 聚焦边框与聚焦环 |
| `--g3-color-danger` / `--g3-color-warning` | `#ec4246` / `#e79a0d` | `error` / `warning` 边框 |
## 实现说明
- **数字模式的取舍**:输入过程保留字符串(否则用户打不出 `12.`),只在 `change` / 失焦时转为 `Number`,空串保持 `''`,避免 `Number('')` 变成 `0`;
- 光标位置在数字过滤后会重新计算(`setSelectionRange`),因此在中间插入非法字符不会把光标弹到末尾;
- 多行模式的高度拖拽用 Pointer Events + `requestAnimationFrame` 合并更新,拖拽期间改的是内联 `height`(从小高度往大拖不会跳变);
- `placeholder` 等原生属性声明为 prop 是刻意的:容器是 `<div>`,如果不声明,`placeholder` 会作为 fallthrough 属性挂到外层容器上,对真实输入框无效;
- 聚焦样式用 `--g3-color-primary-ring` 画 2px 外环(而非 `outline`),这样在 `Space` / `Grid` 里不会因为 outline 被相邻元素裁掉。