TextInput 文本输入
源代码 | 原版组件
单行文本输入框,同时也是 MultilineTextInput、NumberInput、SearchInput 等输入组件的基础。
基本用法
传入 value 即受控,否则组件自行维护输入状态,defaultValue 只作初始值。onChange 为值优先签名,第一个参数就是新的字符串值。
import { useState } from "react";
import { TextInput } from "ooui-react";
function App() {
const [text, setText] = useState("");
return (
<div style={{ display: "flex", flexDirection: "column", gap: 12, maxWidth: 320 }}>
<TextInput value={text} onChange={setText} placeholder="受控输入" />
<div>当前值:{text || "(空)"}</div>
<TextInput defaultValue="非受控,组件自己记住输入" />
</div>
);
}
export default App;
类型
type 同时决定 <input> 的 type 属性与根元素的 oo-ui-textInputWidget-type-{type} 类,取值限定在主题有样式的白名单 text、password、email、url、number、search,非法值回退为 text。
import { TextInput } from "ooui-react";
function App() {
return (
<div style={{ display: "flex", flexDirection: "column", gap: 12, maxWidth: 320 }}>
<TextInput type="password" defaultValue="secret" labelPosition="before" label="密码" />
<TextInput type="email" placeholder="you@example.com" />
</div>
);
}
export default App;
标签
label 是字段标签文本,labelPosition 控制在输入框前(before)还是后(after,默认)。标签视觉隐藏时打开 invisibleLabel:保留可访问名称,title 未显式给出时以标签文本兜底。
带标签的表单字段更推 荐用 FieldLayout
把标签写在输入框自身上适合独立摆放的场景;在表单里,标签、对齐与「点标签聚焦输入框」的联动通常交给 FieldLayout,字段控件本身不写 label。
import { TextInput } from "ooui-react";
function App() {
return (
<div style={{ display: "flex", flexDirection: "column", gap: 12, maxWidth: 320 }}>
<TextInput label="用户名" labelPosition="before" defaultValue="alice" />
<TextInput label="仅图标可读的标签" invisibleLabel icon="user" />
</div>
);
}
export default App;
图标与指示器
icon 渲染在输入框一侧(见 Icon),indicator 渲染在另一侧(见 Indicator)。未显式给 indicator 且 required 为真时,自动回退为 required 指示器。
import { TextInput } from "ooui-react";
function App() {
return (
<div style={{ display: "flex", flexDirection: "column", gap: 12, maxWidth: 320 }}>
<TextInput icon="search" placeholder="带图标" />
<TextInput indicator="down" readOnly defaultValue="带指示器(只读)" />
<TextInput required placeholder="必填,自动显示 required 指示器" />
</div>
);
}
export default App;
软校验
validate 是软反馈:值不满足时输入元素输出 aria-invalid、根元素叠加 invalid 标志类,但不改写值。缺省只有浏览器原生约束(如 required)参与提交校验。触发时机为值变更(防抖 250ms)、失焦即校验、聚焦时清除。
validate 接受三种形态:正则(test 判定)、函数(返回布尔或 Promise<boolean>)、或符号名 'non-empty'(非空)、'integer'(纯数字)。
import { TextInput } from "ooui-react";
function App() {
return (
<div style={{ display: "flex", flexDirection: "column", gap: 12, maxWidth: 320 }}>
<TextInput validate="non-empty" placeholder="清空后失焦会标红" />
<TextInput validate="integer" placeholder="只接受纯数字" />
<TextInput validate={(v) => v.length >= 6} placeholder="至少 6 个字符" />
</div>
);
}
export default App;
禁用与只读
disabled 输出 oo-ui-widget-disabled 与 aria-disabled(不写原生 disabled),输入框不可聚焦、不可输入。readOnly 保留聚焦与可选中复制,仅禁止修改。
import { TextInput } from "ooui-react";
function App() {
return (
<div style={{ display: "flex", flexDirection: "column", gap: 12, maxWidth: 320 }}>
<TextInput disabled defaultValue="禁用" />
<TextInput readOnly defaultValue="只读,可选中复制" />
</div>
);
}
export default App;
属性落点
组件根是 <div>、输入元素是 <input>,三条落点规则(输入类组件通用):
- props 的
...rest(id、className、data-* 等未声明属性)落在根 div 上;要写到原生 <input> 上的属性(如 role、aria-*、autoComplete)必须走 inputProps 通道。
inputRef 指向内部 <input>(组件 ref 指向根 div),聚焦输入框用 inputRef。
tabIndex、title、dir、accessKey 由组件接管,直接落在 <input> 上(对齐原版落点),不走 rest。
inputProps 里的 onChange / onBlur / onFocus 会串联在组件自身逻辑之后,不会截断值管线与软校验。
import { useRef } from "react";
import { Button, TextInput } from "ooui-react";
function App() {
const inputRef = useRef<HTMLInputElement>(null);
return (
<div style={{ display: "flex", alignItems: "center", gap: 8 }}>
<TextInput
inputRef={inputRef}
inputProps={{ autoComplete: "off", "aria-label": "自定义标签" }}
placeholder="autoComplete 走 inputProps"
/>
<Button onClick={() => inputRef.current?.focus()}>聚焦</Button>
</div>
);
}
export default App;
API
required 为真时,本组件在原生 <input> 上同时输出 aria-required(原版只写原生 required 属性)。该行为覆盖 TextInput 继承线(MultilineTextInput、NumberInput、ComboBoxInput 同);非文本形态(Dropdown、Checkbox、Radio、SelectFile)不输出。
另见