Input 输入框
增强型输入框组件,支持文本输入、密码输入、前缀图标、后缀图标、清除按钮等功能。
基础用法
最简单的输入框用法。
<div class="sa-input" data-placeholder="请输入内容" data-autocomplete="off" style="width: 300px;"></div>
<script>
SA.init('body');
</script>
带图标的输入框
前缀图标
<div class="sa-input"
data-placeholder="请输入用户名"
data-prefix-icon="search"
data-autocomplete="off"
style="width: 300px;">
</div>
<script>
SA.init('body');
</script>
后缀图标
<div class="sa-input"
data-placeholder="请输入内容"
data-suffix-icon="close"
data-autocomplete="off"
style="width: 300px;">
</div>
<script>
SA.init('body');
</script>
清除按钮
通过 data-clearable="true" 启用清除按钮,点击可以清空输入内容。
<div class="sa-input"
data-placeholder="带清除按钮"
data-clearable="true"
data-autocomplete="off"
style="width: 300px;">
</div>
<script>
SA.init('body');
</script>
密码输入框
设置 data-type="password" 可以创建密码输入框,通过 data-show-password="true" 可以显示密码显示/隐藏切换按钮。
<div class="sa-input"
data-placeholder="请输入密码"
data-type="password"
data-show-password="true"
data-autocomplete="off"
style="width: 300px;">
</div>
<script>
SA.init('body');
</script>
其他输入类型
Input 组件支持多种 HTML5 输入类型,包括 email、number、tel、url 等。
邮箱输入框
<div class="sa-input"
data-placeholder="请输入邮箱地址"
data-type="email"
data-clearable="true"
data-autocomplete="off"
style="width: 300px;">
</div>
<script>
SA.init('body');
</script>
数字输入框
<div class="sa-input"
data-placeholder="请输入数字"
data-type="number"
data-clearable="true"
data-autocomplete="off"
style="width: 300px;">
</div>
<script>
SA.init('body');
</script>
URL 输入框
<div class="sa-input"
data-placeholder="请输入网址"
data-type="url"
data-clearable="true"
data-autocomplete="off"
style="width: 300px;">
</div>
<script>
SA.init('body');
</script>
文本域
用于输入多行文本信息可缩放的输入框。添加 data-type="textarea" 属性来将 input 元素转换为原生的 textarea 元素。
基础文本域
<div class="sa-input"
data-type="textarea"
data-placeholder="Please input"
data-rows="4"
style="width: 300px;">
</div>
<script>
SA.init('body');
</script>
文本域高度控制
文本域高度可通过 data-rows 属性控制。
<div class="sa-input"
data-type="textarea"
data-placeholder="请输入内容"
data-rows="6"
style="width: 300px;">
</div>
<script>
SA.init('body');
</script>
自适应文本域
设置 data-autosize="true" 属性使得根据内容自动调整的高度。
<div class="sa-input"
data-type="textarea"
data-placeholder="请输入内容"
data-autosize="true"
style="width: 300px;">
</div>
<script>
SA.init('body');
</script>
自适应文本域(限制范围)
你可以给 data-autosize 提供一个包含有最大和最小高度的对象,让输入框自动调整。
<div class="sa-input"
data-type="textarea"
data-placeholder="请输入内容"
data-autosize='{"minRows": 2, "maxRows": 6}'
style="width: 300px;">
</div>
<script>
SA.init('body');
</script>
禁用状态
通过 data-disabled="true" 禁用输入框。
<div class="sa-input"
data-placeholder="禁用状态"
data-disabled="true"
data-value="已禁用"
data-autocomplete="off"
style="width: 300px;">
</div>
<script>
SA.init('body');
</script>
只读状态
通过 data-readonly="true" 设置输入框为只读状态,只读状态下用户无法编辑内容。
<div class="sa-input"
data-placeholder="只读状态"
data-readonly="true"
data-value="只读内容,无法编辑"
data-autocomplete="off"
style="width: 300px;">
</div>
<script>
SA.init('body');
</script>
不同尺寸
通过 data-size 属性设置输入框大小。
<!-- 大尺寸 -->
<div class="sa-input" data-size="large" data-placeholder="大尺寸" data-autocomplete="off" style="width: 300px;"></div>
<!-- 默认尺寸 -->
<div class="sa-input" data-placeholder="默认尺寸" data-autocomplete="off" style="width: 300px;"></div>
<!-- 小尺寸 -->
<div class="sa-input" data-size="small" data-placeholder="小尺寸" data-autocomplete="off" style="width: 300px;"></div>
<script>
SA.init('body');
</script>
统一自动初始化
使用 SA.init() 可以自动初始化容器内的所有支持自动初始化的组件(包括 input、form、button 等)。
<div style="display: flex; flex-direction: column; gap: 16px; max-width: 600px;">
<div class="sa-input"
id="username-input"
data-placeholder="用户名"
data-value="admin"
data-prefix-icon="search"
data-clearable="true"
data-autocomplete="off"
style="width: 100%;"></div>
<div class="sa-input"
id="password-input"
data-placeholder="密码"
data-value="123456"
data-type="password"
data-show-password="true"
data-clearable="false"
data-autocomplete="off"
style="width: 100%;"></div>
<div class="sa-input"
id="email-input"
data-placeholder="邮箱"
data-type="email"
data-clearable="true"
data-autocomplete="off"
style="width: 100%;"></div>
</div>
<script>
// 使用 SA.init() 统一初始化所有组件
const page = SA.init('body');
// 按钮组件已自动初始化,所有带有 class="sa-input" 的元素都会被处理
// 图标按钮的图标也会自动添加
// 输入框组件通常不需要手动初始化,直接使用 HTML 类名即可
</script>
API
构造函数
new SaInput(container, config)参数
| 参数 | 说明 | 类型 | 默认值 |
|---|---|---|---|
container | 容器选择器或元素 | string | HTMLElement | - |
config | 配置选项 | SaInputOptions | {} |
配置选项
| 参数 | 说明 | 类型 | 默认值 |
|---|---|---|---|
value | 输入框的值 | string | '' |
placeholder | 占位符文本 | string | '' |
type | 输入框类型 | 'text' | 'password' | 'email' | 'number' | 'tel' | 'url' | 'textarea' | 'text' |
rows | 文本域行数(当 type="textarea" 时) | number | 2 |
autosize | 文本域自适应高度(当 type="textarea" 时),可以是布尔值或对象 { minRows, maxRows } | boolean | Object | false |
clearable | 是否显示清除按钮 | boolean | true |
showPassword | 是否显示密码切换按钮(仅 type="password" 时有效) | boolean | false |
prefixIcon | 前缀图标名称 | string | null | null |
suffixIcon | 后缀图标名称 | string | null | null |
disabled | 是否禁用 | boolean | false |
readonly | 是否只读 | boolean | false |
autocomplete | 浏览器自动填充控制 | string | - |
size | 输入框尺寸 | 'large' | 'default' | 'small' | 'default' |
onInput | 输入事件回调 | function(value: string) | null |
onEnter | 回车键事件回调 | function(value: string) | null |
onClear | 清除事件回调 | function() | null |
onChange | 值变化事件回调 | function(value: string) | null |
Data 属性
Input 组件支持通过 data-* 属性进行配置:
| 属性 | 说明 | 类型 | 默认值 | 示例 |
|---|---|---|---|---|
data-value | 输入框的值 | string | '' | data-value="初始值" |
data-placeholder | 占位符文本 | string | '' | data-placeholder="请输入" |
data-type | 输入框类型,支持 'textarea' | string | 'text' | data-type="password"data-type="textarea" |
data-rows | 文本域行数(当 type="textarea" 时) | string | '2' | data-rows="4" |
data-autosize | 文本域自适应高度,可以是 'true' 或 JSON 对象字符串 | string | 'false' | data-autosize="true"data-autosize='{"minRows": 2, "maxRows": 6}' |
data-clearable | 是否显示清除按钮 | boolean | true | data-clearable="true" |
data-show-password | 是否显示密码切换按钮 | boolean | false | data-show-password="true" |
data-prefix-icon | 前缀图标名称 | string | - | data-prefix-icon="search" |
data-suffix-icon | 后缀图标名称 | string | - | data-suffix-icon="close" |
data-disabled | 是否禁用 | boolean | false | data-disabled="true" |
data-readonly | 是否只读 | boolean | false | data-readonly="true" |
data-autocomplete | 浏览器自动填充控制 | string | - | data-autocomplete="off"data-autocomplete="new-password" |
data-size | 输入框尺寸 | string | 'default' | data-size="large" |
方法
| 方法名 | 说明 | 参数 | 返回值 |
|---|---|---|---|
getValue() | 获取输入框的值 | - | string |
setValue(value) | 设置输入框的值 | value: string | SaInput |
setDisabled(disabled) | 设置禁用状态 | disabled: boolean | SaInput |
setReadonly(readonly) | 设置只读状态 | readonly: boolean | SaInput |
focus() | 聚焦输入框 | - | void |
blur() | 失焦输入框 | - | void |
togglePasswordVisibility() | 切换密码显示/隐藏(仅 type="password" 时有效) | - | void |
destroy() | 销毁实例 | - | void |
事件回调
| 事件名 | 说明 | 回调参数 |
|---|---|---|
onInput | 输入时触发 | value: string - 当前输入值 |
onEnter | 按下回车键时触发 | value: string - 当前输入值 |
onClear | 点击清除按钮时触发 | - |
onChange | 值变化时触发(失焦时) | value: string - 当前输入值 |
实际使用场景
场景 1:登录表单
完整的登录表单,包含用户名和密码输入框,带验证和提交功能。
<form id="login-form" style="max-width: 400px;">
<div style="margin-bottom: 1rem;">
<label style="display: block; margin-bottom: 0.5rem; font-weight: 500;">用户名</label>
<div
class="sa-input"
id="username-input"
data-placeholder="请输入用户名"
data-prefix-icon="search"
data-clearable="true"
data-autocomplete="off"
style="width: 100%;"
></div>
</div>
<div style="margin-bottom: 1rem;">
<label style="display: block; margin-bottom: 0.5rem; font-weight: 500;">密码</label>
<div
class="sa-input"
id="password-input"
data-placeholder="请输入密码"
data-type="password"
data-show-password="true"
data-clearable="false"
data-autocomplete="off"
style="width: 100%;"
></div>
</div>
<button type="submit" class="sa-button sa-button--primary" style="width: 100%;">
登录
</button>
</form>
<script>
SA.init('body');
const form = document.getElementById('login-form');
const usernameInput = document.getElementById('username-input');
const passwordInput = document.getElementById('password-input');
form.addEventListener('submit', (e) => {
e.preventDefault();
const username = usernameInput._saInputInstance?.getValue() || '';
const password = passwordInput._saInputInstance?.getValue() || '';
// 简单验证
if (!username) {
alert('请输入用户名');
usernameInput._saInputInstance?.focus();
return;
}
if (!password) {
alert('请输入密码');
passwordInput._saInputInstance?.focus();
return;
}
// 模拟登录
console.log('登录信息:', { username, password });
alert('登录成功!');
});
</script>
场景 2:实时搜索
带搜索功能的输入框,支持实时搜索和清除功能。
<div style="max-width: 500px;">
<div
class="sa-input"
id="search-input"
data-placeholder="搜索用户、文章、标签..."
data-prefix-icon="search"
data-clearable="true"
data-autocomplete="off"
style="width: 100%;"
></div>
<div id="search-results" style="margin-top: 1rem; padding: 1rem; border: 1px solid #ddd; border-radius: 4px; min-height: 100px;">
<p style="color: #999; margin: 0;">输入关键词开始搜索...</p>
</div>
</div>
<script>
SA.init('body');
const searchInput = document.getElementById('search-input');
const searchResults = document.getElementById('search-results');
let searchTimer = null;
// 模拟搜索结果
const mockResults = [
'用户:张三',
'用户:李四',
'文章:如何使用 SanoUI',
'文章:组件库最佳实践',
'标签:前端开发',
'标签:UI 设计'
];
// 监听输入事件
if (searchInput._saInputInstance) {
searchInput._saInputInstance.config.onInput = (value) => {
// 防抖处理
clearTimeout(searchTimer);
if (!value) {
searchResults.innerHTML = '<p style="color: #999; margin: 0;">输入关键词开始搜索...</p>';
return;
}
searchTimer = setTimeout(() => {
// 模拟搜索
const results = mockResults.filter(item =>
item.toLowerCase().includes(value.toLowerCase())
);
if (results.length > 0) {
searchResults.innerHTML = results.map(item =>
`<div style="padding: 0.5rem; border-bottom: 1px solid #eee;">${item}</div>`
).join('');
} else {
searchResults.innerHTML = '<p style="color: #999; margin: 0;">未找到相关结果</p>';
}
}, 300);
};
// 清除时重置结果
searchInput._saInputInstance.config.onClear = () => {
searchResults.innerHTML = '<p style="color: #999; margin: 0;">输入关键词开始搜索...</p>';
};
}
</script>
场景 3:表单验证
带实时验证的输入框,显示验证错误信息。
<div style="max-width: 400px;">
<div style="margin-bottom: 1.5rem;">
<label style="display: block; margin-bottom: 0.5rem; font-weight: 500;">邮箱地址</label>
<div
class="sa-input"
id="email-input"
data-placeholder="请输入邮箱地址"
data-type="email"
data-clearable="true"
data-autocomplete="off"
style="width: 100%;"
></div>
<div id="email-error" style="color: #f56c6c; font-size: 0.875rem; margin-top: 0.25rem; display: none;"></div>
</div>
<div style="margin-bottom: 1.5rem;">
<label style="display: block; margin-bottom: 0.5rem; font-weight: 500;">手机号码</label>
<div
class="sa-input"
id="phone-input"
data-placeholder="请输入手机号码"
data-type="tel"
data-clearable="true"
data-autocomplete="off"
style="width: 100%;"
></div>
<div id="phone-error" style="color: #f56c6c; font-size: 0.875rem; margin-top: 0.25rem; display: none;"></div>
</div>
<button class="sa-button sa-button--primary" onclick="validateForm()">
提交
</button>
</div>
<script>
SA.init('body');
const emailInput = document.getElementById('email-input');
const phoneInput = document.getElementById('phone-input');
const emailError = document.getElementById('email-error');
const phoneError = document.getElementById('phone-error');
// 邮箱验证
function validateEmail(email) {
const re = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
return re.test(email);
}
// 手机号验证
function validatePhone(phone) {
const re = /^1[3-9]\d{9}$/;
return re.test(phone);
}
// 邮箱输入验证
if (emailInput._saInputInstance) {
emailInput._saInputInstance.config.onChange = (value) => {
if (value && !validateEmail(value)) {
emailError.textContent = '请输入有效的邮箱地址';
emailError.style.display = 'block';
} else {
emailError.style.display = 'none';
}
};
}
// 手机号输入验证
if (phoneInput._saInputInstance) {
phoneInput._saInputInstance.config.onChange = (value) => {
if (value && !validatePhone(value)) {
phoneError.textContent = '请输入有效的手机号码';
phoneError.style.display = 'block';
} else {
phoneError.style.display = 'none';
}
};
}
function validateForm() {
const email = emailInput._saInputInstance?.getValue() || '';
const phone = phoneInput._saInputInstance?.getValue() || '';
let isValid = true;
if (!email) {
emailError.textContent = '请输入邮箱地址';
emailError.style.display = 'block';
isValid = false;
} else if (!validateEmail(email)) {
emailError.textContent = '请输入有效的邮箱地址';
emailError.style.display = 'block';
isValid = false;
} else {
emailError.style.display = 'none';
}
if (!phone) {
phoneError.textContent = '请输入手机号码';
phoneError.style.display = 'block';
isValid = false;
} else if (!validatePhone(phone)) {
phoneError.textContent = '请输入有效的手机号码';
phoneError.style.display = 'block';
isValid = false;
} else {
phoneError.style.display = 'none';
}
if (isValid) {
alert('验证通过!');
}
}
</script>
场景 4:密码强度检测
密码输入框带实时强度检测功能。
<div style="max-width: 400px;">
<div style="margin-bottom: 0.5rem;">
<label style="display: block; margin-bottom: 0.5rem; font-weight: 500;">设置密码</label>
<div
class="sa-input"
id="password-strength-input"
data-placeholder="请输入密码"
data-type="password"
data-show-password="true"
data-clearable="true"
data-autocomplete="off"
style="width: 100%;"
></div>
</div>
<div id="password-strength" style="margin-bottom: 1rem;">
<div style="display: flex; gap: 4px; margin-bottom: 0.5rem;">
<div id="strength-bar-1" style="flex: 1; height: 4px; background: #ddd; border-radius: 2px;"></div>
<div id="strength-bar-2" style="flex: 1; height: 4px; background: #ddd; border-radius: 2px;"></div>
<div id="strength-bar-3" style="flex: 1; height: 4px; background: #ddd; border-radius: 2px;"></div>
</div>
<div id="strength-text" style="font-size: 0.875rem; color: #999;">请输入密码</div>
</div>
</div>
<script>
SA.init('body');
const passwordInput = document.getElementById('password-strength-input');
const strengthText = document.getElementById('strength-text');
const bars = [
document.getElementById('strength-bar-1'),
document.getElementById('strength-bar-2'),
document.getElementById('strength-bar-3')
];
function checkPasswordStrength(password) {
let strength = 0;
let text = '';
let color = '#999';
if (password.length === 0) {
return { strength: 0, text: '请输入密码', color: '#999' };
}
if (password.length >= 6) strength++;
if (password.length >= 10) strength++;
if (/[a-z]/.test(password) && /[A-Z]/.test(password)) strength++;
if (/\d/.test(password)) strength++;
if (/[^a-zA-Z\d]/.test(password)) strength++;
if (strength <= 2) {
text = '弱';
color = '#f56c6c';
} else if (strength <= 3) {
text = '中';
color = '#e6a23c';
} else {
text = '强';
color = '#67c23a';
}
return { strength: Math.min(strength, 3), text, color };
}
if (passwordInput._saInputInstance) {
passwordInput._saInputInstance.config.onInput = (value) => {
const result = checkPasswordStrength(value);
// 更新强度条
bars.forEach((bar, index) => {
if (index < result.strength) {
bar.style.background = result.color;
} else {
bar.style.background = '#ddd';
}
});
// 更新文本
strengthText.textContent = `密码强度:${result.text}`;
strengthText.style.color = result.color;
};
}
</script>
场景 5:动态禁用/启用
根据条件动态控制输入框的禁用状态。
<div style="max-width: 400px;">
<div style="margin-bottom: 1rem;">
<label>
<input type="checkbox" id="enable-input" checked onchange="toggleInput()">
启用输入框
</label>
</div>
<div
class="sa-input"
id="dynamic-input"
data-placeholder="此输入框可动态启用/禁用"
data-clearable="true"
data-autocomplete="off"
style="width: 100%;"
></div>
</div>
<script>
SA.init('body');
const enableCheckbox = document.getElementById('enable-input');
const dynamicInput = document.getElementById('dynamic-input');
function toggleInput() {
if (dynamicInput._saInputInstance) {
dynamicInput._saInputInstance.setDisabled(!enableCheckbox.checked);
}
}
// 初始化状态
toggleInput();
</script>
注意事项
- 自动初始化:使用
SA.init()会自动初始化所有带class="sa-input"的输入框 - 实例访问:初始化后可以通过
element._saInputInstance访问组件实例 - 密码类型:当
type="password"时,默认启用showPassword功能 - 浏览器自动填充:通过
data-autocomplete属性可以控制浏览器的自动填充行为data-autocomplete="off"- 禁用自动填充(适用于用户名等敏感信息)data-autocomplete="new-password"- 告诉浏览器这是新密码,不要自动填充(适用于注册/修改密码场景)data-autocomplete="username"- 允许自动填充用户名- 其他标准 autocomplete 值也支持,如
email、tel等
- 清除按钮:清除按钮只在有输入值且
clearable="true"时显示 - 事件触发:
onChange在失焦时触发,onInput在输入时实时触发 - 方法返回值:
setValue()、setDisabled()、setReadonly()等方法返回this,支持链式调用
常见问题
Q: 如何获取输入框的值?
A: 通过组件实例的 getValue() 方法:
const value = inputElement._saInputInstance.getValue();Q: 如何动态设置输入框的值?
A: 使用 setValue() 方法:
inputElement._saInputInstance.setValue('新值');Q: 如何监听输入事件?
A: 在配置中设置 onInput 回调,或通过实例配置:
inputElement._saInputInstance.config.onInput = (value) => {
console.log('输入值:', value);
};Q: 如何实现输入框的联动?
A: 通过事件回调实现:
// 输入框 A 变化时,更新输入框 B
inputA._saInputInstance.config.onChange = (value) => {
inputB._saInputInstance.setValue(value.toUpperCase());
};