使用场景 ​
适合名称、邮箱、搜索词等单行输入。密码使用 AsamPassword,多行文本使用 AsamTextarea,数字步进使用 AsamInputNumber。普通 v-model 更新为字符串;number 修饰符可更新为数字。
type 支持 text、number、email、search、tel、url。单选、多选、日期及上传等场景使用对应的独立组件。
双向绑定与输入状态 ​
input 随输入触发,change 在值提交或失焦后触发;clearable 提供清空操作,readonly 和 disabled 表达不同的交互状态。
双向绑定与输入状态
<template>
<div class="example">
<AsamInput
v-model="value"
v-bind="{ class: 'field', 'aria-label': '项目名称' }"
placeholder="请输入项目名称"
clearable
:maxlength="20"
show-word-limit
@input="event = 'input: ' + $event"
@change="event = 'change: ' + $event"
@clear="event = 'clear'"
/>
<AsamInput
model-value="只读值"
readonly
v-bind="{ class: 'field', 'aria-label': '只读项目' }"
/>
<AsamInput
model-value="禁用值"
disabled
v-bind="{ class: 'field', 'aria-label': '禁用项目' }"
/>
<output>当前值:{{ value }};{{ event }}</output>
</div>
</template>
<script lang="ts" setup>
defineOptions({ name: 'AsamInputBasicExample' });
import { ref } from 'vue';
import { AsamInput } from '@asam-ui/ui';
const value = ref('ASAM');
const event = ref('尚未输入');
</script>
<style scoped>
.example {
display: grid;
gap: var(--asam-space-md, 16px);
min-width: 0;
}
.row {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: var(--asam-space-sm, 8px);
}
.field {
width: 100%;
max-width: 360px;
}
output {
overflow-wrap: anywhere;
color: var(--asam-color-text-secondary);
}
</style>
<template>
<div class="example">
<AsamInput
v-model="value"
v-bind="{ class: 'field', 'aria-label': '项目名称' }"
placeholder="请输入项目名称"
clearable
:maxlength="20"
show-word-limit
@input="event = 'input: ' + $event"
@change="event = 'change: ' + $event"
@clear="event = 'clear'"
/>
<AsamInput
model-value="只读值"
readonly
v-bind="{ class: 'field', 'aria-label': '只读项目' }"
/>
<AsamInput
model-value="禁用值"
disabled
v-bind="{ class: 'field', 'aria-label': '禁用项目' }"
/>
<output>当前值:{{ value }};{{ event }}</output>
</div>
</template>
<script setup>
defineOptions({ name: 'AsamInputBasicExample' });
import { ref } from 'vue';
import { AsamInput } from '@asam-ui/ui';
const value = ref('ASAM');
const event = ref('尚未输入');
</script>
<style scoped>
.example {
display: grid;
gap: var(--asam-space-md, 16px);
min-width: 0;
}
.row {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: var(--asam-space-sm, 8px);
}
.field {
width: 100%;
max-width: 360px;
}
output {
overflow-wrap: anywhere;
color: var(--asam-color-text-secondary);
}
</style>
图标、前后缀与复合输入 ​
prefix/suffix 放入内部装饰,prepend/append 放入输入框外侧的复合内容。数值属性 maxlength 用绑定数字传入。
图标、前后缀与复合输入
<!-- 此演示还使用 @asam-ui/icons-vue,请按官网对应指南配置这些公开依赖。 -->
<template>
<div class="example">
<AsamInput
v-model="email"
class="field"
type="email"
aria-label="联系邮箱"
:prefix-icon="Message"
:suffix-icon="Check"
/>
<AsamInput v-model="site" v-bind="{ class: 'field', 'aria-label': '站点名称' }">
<template #prepend> https:// </template>
<template #append> .example </template>
</AsamInput>
<AsamInput v-model="query" v-bind="{ class: 'field', 'aria-label': '搜索关键词' }">
<template #prefix>
<Search style="width: 16px" />
</template>
<template #suffix> 关键词 </template>
</AsamInput>
</div>
</template>
<script lang="ts" setup>
defineOptions({ name: 'AsamInputDecorationExample' });
import { ref } from 'vue';
import { AsamInput } from '@asam-ui/ui';
import { Message, Check, Search } from '@asam-ui/icons-vue';
const email = ref('team@example.com');
const site = ref('asam');
const query = ref('');
</script>
<style scoped>
.example {
display: grid;
gap: var(--asam-space-md, 16px);
min-width: 0;
}
.row {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: var(--asam-space-sm, 8px);
}
.field {
width: 100%;
max-width: 360px;
}
output {
overflow-wrap: anywhere;
color: var(--asam-color-text-secondary);
}
</style>
<!-- 此演示还使用 @asam-ui/icons-vue,请按官网对应指南配置这些公开依赖。 -->
<template>
<div class="example">
<AsamInput
v-model="email"
class="field"
type="email"
aria-label="联系邮箱"
:prefix-icon="Message"
:suffix-icon="Check"
/>
<AsamInput v-model="site" v-bind="{ class: 'field', 'aria-label': '站点名称' }">
<template #prepend> https:// </template>
<template #append> .example </template>
</AsamInput>
<AsamInput v-model="query" v-bind="{ class: 'field', 'aria-label': '搜索关键词' }">
<template #prefix>
<Search style="width: 16px" />
</template>
<template #suffix> 关键词 </template>
</AsamInput>
</div>
</template>
<script setup>
defineOptions({ name: 'AsamInputDecorationExample' });
import { ref } from 'vue';
import { AsamInput } from '@asam-ui/ui';
import { Message, Check, Search } from '@asam-ui/icons-vue';
const email = ref('team@example.com');
const site = ref('asam');
const query = ref('');
</script>
<style scoped>
.example {
display: grid;
gap: var(--asam-space-md, 16px);
min-width: 0;
}
.row {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: var(--asam-space-sm, 8px);
}
.field {
width: 100%;
max-width: 360px;
}
output {
overflow-wrap: anywhere;
color: var(--asam-color-text-secondary);
}
</style>
格式化与解析 ​
formatter 负责展示,parser 负责去掉展示装饰。辅助函数包含在双语言源码内,可与 SFC 一起复制。
格式化与解析
<template><StandaloneDemo /></template>
<script lang="ts" setup>
import * as __external0 from "vue";
import * as __external1 from "@asam-ui/ui";
const __external: any = {"vue": { ...__external0, __esModule: true },
"@asam-ui/ui": { ...__external1, __esModule: true }};
const __modules: any = {
"Demo.vue": (module: any, exports: any, require: any) => {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const vue_1: any = require("vue");
const vue_2: any = require("vue");
const _hoisted_1: any = { class: "example" };
const vue_3: any = require("vue");
const ui_1: any = require("@asam-ui/ui");
const format_1: any = require("./format");
exports.default = (0, vue_1.defineComponent)({
...{ name: 'AsamInputFormatExample' },
__name: 'Demo',
setup(__props?: any) {
const amount: any = (0, vue_3.ref)('1200');
return (_ctx?: any, _cache?: any) => {
return ((0, vue_2.openBlock)(), (0, vue_2.createElementBlock)("div", _hoisted_1, [
(0, vue_2.createVNode)((0, vue_2.unref)(ui_1.AsamInput), (0, vue_2.mergeProps)({
modelValue: amount.value,
"onUpdate:modelValue": _cache[0] || (_cache[0] = ($event?: any) => ((amount).value = $event))
}, { class: 'field', 'aria-label': '预算' }, {
formatter: (0, vue_2.unref)(format_1.formatAmount),
parser: (0, vue_2.unref)(format_1.parseAmount)
}), null, 16 /* FULL_PROPS */, ["modelValue", "formatter", "parser"]),
(0, vue_2.createElementVNode)("output", null, "模型值:" + (0, vue_2.toDisplayString)(amount.value), 1 /* TEXT */)
]));
};
}
});
exports.default.__scopeId = "data-v-7ead9270";
},
"format.ts": (module: any, exports: any, require: any) => {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.formatAmount = formatAmount;
exports.parseAmount = parseAmount;
function formatAmount(value?: any) {
return '$ ' + String(value).replace(/\B(?=(\d{3})+(?!\d))/g, ',');
}
function parseAmount(value?: any) {
return value.replace(/[$ ,]/g, '');
}
},
};
const __dependencies: any = {"Demo.vue":{"./format":"format.ts"},"format.ts":{}};
const __cache: any = Object.create(null);
function __require(id: any): any {
if (__external[id]) return __external[id];
if (__cache[id]) return __cache[id].exports;
const module: any = { exports: {} };
__cache[id] = module;
__modules[id](module, module.exports, (dependency: any) => __require(__dependencies[id][dependency] || dependency));
return module.exports;
}
const StandaloneDemo = __require('Demo.vue').default;
</script>
<style>
.example[data-v-7ead9270] {
display: grid;
gap: var(--asam-space-md, 16px);
min-width: 0;
}
.row[data-v-7ead9270] {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: var(--asam-space-sm, 8px);
}
.field[data-v-7ead9270] {
width: 100%;
max-width: 360px;
}
output[data-v-7ead9270] {
overflow-wrap: anywhere;
color: var(--asam-color-text-secondary);
}
</style>
<template><StandaloneDemo /></template>
<script setup>
import * as __external0 from "vue";
import * as __external1 from "@asam-ui/ui";
const __external = {"vue": { ...__external0, __esModule: true },
"@asam-ui/ui": { ...__external1, __esModule: true }};
const __modules = {
"Demo.vue": (module, exports, require) => {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const vue_1 = require("vue");
const _hoisted_1 = { class: "example" };
const vue_2 = require("vue");
const ui_1 = require("@asam-ui/ui");
const format_1 = require("./format");
exports.default = Object.assign({ name: 'AsamInputFormatExample' }, {
__name: 'Demo',
setup(__props) {
const amount = (0, vue_2.ref)('1200');
return (_ctx, _cache) => {
return ((0, vue_1.openBlock)(), (0, vue_1.createElementBlock)("div", _hoisted_1, [
(0, vue_1.createVNode)((0, vue_1.unref)(ui_1.AsamInput), (0, vue_1.mergeProps)({
modelValue: amount.value,
"onUpdate:modelValue": _cache[0] || (_cache[0] = $event => ((amount).value = $event))
}, { class: 'field', 'aria-label': '预算' }, {
formatter: (0, vue_1.unref)(format_1.formatAmount),
parser: (0, vue_1.unref)(format_1.parseAmount)
}), null, 16 /* FULL_PROPS */, ["modelValue", "formatter", "parser"]),
(0, vue_1.createElementVNode)("output", null, "模型值:" + (0, vue_1.toDisplayString)(amount.value), 1 /* TEXT */)
]));
};
}
});
exports.default.__scopeId = "data-v-aa2f0fc2";
},
"format.js": (module, exports, require) => {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.formatAmount = formatAmount;
exports.parseAmount = parseAmount;
function formatAmount(value) {
return '$ ' + String(value).replace(/\B(?=(\d{3})+(?!\d))/g, ',');
}
function parseAmount(value) {
return value.replace(/[$ ,]/g, '');
}
},
};
const __dependencies = {"Demo.vue":{"./format":"format.js"},"format.js":{}};
const __cache = Object.create(null);
function __require(id) {
if (__external[id]) return __external[id];
if (__cache[id]) return __cache[id].exports;
const module = { exports: {} };
__cache[id] = module;
__modules[id](module, module.exports, (dependency) => __require(__dependencies[id][dependency] || dependency));
return module.exports;
}
const StandaloneDemo = __require('Demo.vue').default;
</script>
<style>
.example[data-v-aa2f0fc2] {
display: grid;
gap: var(--asam-space-md, 16px);
min-width: 0;
}
.row[data-v-aa2f0fc2] {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: var(--asam-space-sm, 8px);
}
.field[data-v-aa2f0fc2] {
width: 100%;
max-width: 360px;
}
output[data-v-aa2f0fc2] {
overflow-wrap: anywhere;
color: var(--asam-color-text-secondary);
}
</style>
聚焦、选中与清空 ​
通过公开 AsamInputExpose 类型访问 focus、select、clear、blur。IME 组合状态通过 isComposing 读取,组合输入事件的参数见 API。
聚焦、选中与清空
<template>
<div class="example">
<AsamInput
ref="input"
v-model="value"
v-bind="{ class: 'field', 'aria-label': '实例操作输入' }"
/>
<div class="row">
<AsamButton type="default" @click="input?.focus()"> 聚焦 </AsamButton>
<AsamButton type="default" @click="input?.select()"> 选中 </AsamButton>
<AsamButton type="default" @click="input?.clear()"> 清空 </AsamButton>
<AsamButton type="default" @click="input?.blur()"> 失焦 </AsamButton>
</div>
<output>当前值:{{ value }}</output>
</div>
</template>
<script lang="ts" setup>
defineOptions({ name: 'AsamInputInstanceExample' });
import { ref } from 'vue';
import { AsamInput, AsamButton } from '@asam-ui/ui';
import type { AsamInputExpose } from '@asam-ui/ui';
const input = ref<AsamInputExpose>();
const value = ref('可以选中的文本');
</script>
<style scoped>
.example {
display: grid;
gap: var(--asam-space-md, 16px);
min-width: 0;
}
.row {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: var(--asam-space-sm, 8px);
}
.field {
width: 100%;
max-width: 360px;
}
output {
overflow-wrap: anywhere;
color: var(--asam-color-text-secondary);
}
</style>
<template>
<div class="example">
<AsamInput
ref="input"
v-model="value"
v-bind="{ class: 'field', 'aria-label': '实例操作输入' }"
/>
<div class="row">
<AsamButton type="default" @click="input?.focus()"> 聚焦 </AsamButton>
<AsamButton type="default" @click="input?.select()"> 选中 </AsamButton>
<AsamButton type="default" @click="input?.clear()"> 清空 </AsamButton>
<AsamButton type="default" @click="input?.blur()"> 失焦 </AsamButton>
</div>
<output>当前值:{{ value }}</output>
</div>
</template>
<script setup>
defineOptions({ name: 'AsamInputInstanceExample' });
import { ref } from 'vue';
import { AsamInput, AsamButton } from '@asam-ui/ui';
const input = ref();
const value = ref('可以选中的文本');
</script>
<style scoped>
.example {
display: grid;
gap: var(--asam-space-md, 16px);
min-width: 0;
}
.row {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: var(--asam-space-sm, 8px);
}
.field {
width: 100%;
max-width: 360px;
}
output {
overflow-wrap: anywhere;
color: var(--asam-color-text-secondary);
}
</style>
四档密度与继承 ​
large / big / default / small 分别为四档密度。显式 size 覆盖继承;省略 size 时按组件、组、表单、ConfigProvider 到 default 解析。通过切换 provider 验证继承响应。
四档密度与继承
<template>
<div class="example">
<div class="row">
<AsamInput
size="large"
v-bind="{ class: 'field', 'aria-label': 'large尺寸' }"
model-value="ASAM"
/>
<AsamInput
size="big"
v-bind="{ class: 'field', 'aria-label': 'big尺寸' }"
model-value="ASAM"
/>
<AsamInput
size="default"
v-bind="{ class: 'field', 'aria-label': 'default尺寸' }"
model-value="ASAM"
/>
<AsamInput
size="small"
v-bind="{ class: 'field', 'aria-label': 'small尺寸' }"
model-value="ASAM"
/>
</div>
<AsamConfigProvider :size="density">
<div class="example">
<AsamInput
v-bind="{ class: 'field', 'aria-label': '继承尺寸' }"
model-value="ASAM"
/>
<div class="row">
<AsamButton type="default" @click="density = 'small'"> 继承 small </AsamButton>
<AsamButton type="default" @click="density = 'big'"> 继承 big </AsamButton>
</div>
</div>
</AsamConfigProvider>
<output>配置提供器:{{ density }}</output>
</div>
</template>
<script lang="ts" setup>
defineOptions({ name: 'AsamInputSizesExample' });
import { ref } from 'vue';
import { AsamInput, AsamConfigProvider, AsamButton } from '@asam-ui/ui';
import type { AsamControlSize } from '@asam-ui/ui';
const density = ref<AsamControlSize>('big');
</script>
<style scoped>
.example {
display: grid;
gap: var(--asam-space-md, 16px);
min-width: 0;
}
.row {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: var(--asam-space-sm, 8px);
}
.field {
width: 100%;
max-width: 360px;
}
output {
overflow-wrap: anywhere;
color: var(--asam-color-text-secondary);
}
</style>
<template>
<div class="example">
<div class="row">
<AsamInput
size="large"
v-bind="{ class: 'field', 'aria-label': 'large尺寸' }"
model-value="ASAM"
/>
<AsamInput
size="big"
v-bind="{ class: 'field', 'aria-label': 'big尺寸' }"
model-value="ASAM"
/>
<AsamInput
size="default"
v-bind="{ class: 'field', 'aria-label': 'default尺寸' }"
model-value="ASAM"
/>
<AsamInput
size="small"
v-bind="{ class: 'field', 'aria-label': 'small尺寸' }"
model-value="ASAM"
/>
</div>
<AsamConfigProvider :size="density">
<div class="example">
<AsamInput
v-bind="{ class: 'field', 'aria-label': '继承尺寸' }"
model-value="ASAM"
/>
<div class="row">
<AsamButton type="default" @click="density = 'small'"> 继承 small </AsamButton>
<AsamButton type="default" @click="density = 'big'"> 继承 big </AsamButton>
</div>
</div>
</AsamConfigProvider>
<output>配置提供器:{{ density }}</output>
</div>
</template>
<script setup>
defineOptions({ name: 'AsamInputSizesExample' });
import { ref } from 'vue';
import { AsamInput, AsamConfigProvider, AsamButton } from '@asam-ui/ui';
const density = ref('big');
</script>
<style scoped>
.example {
display: grid;
gap: var(--asam-space-md, 16px);
min-width: 0;
}
.row {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: var(--asam-space-sm, 8px);
}
.field {
width: 100%;
max-width: 360px;
}
output {
overflow-wrap: anywhere;
color: var(--asam-color-text-secondary);
}
</style>
ASAM 扩展与迁移 ​
四档 size 是 ASAM 密度扩展。 完整说明。
原生数值约束 ​
min/max/step 原样传入实际 input,保留浏览器约束语义,不自动裁剪字符串模型。需要数值步进时使用 AsamInputNumber。动态 type、光标和编辑草稿由 底层组件 与浏览器处理;number 等不支持文本选区的类型可能出现原生选区限制,ASAM 不替换 input 的 DOM 方法。
原生约束与可访问性
<template>
<div class="example">
<AsamInput
v-model="value"
type="number"
min="1"
max="10"
step="2"
name="quantity"
inputmode="numeric"
aria-label="奇数数量"
/><output>字符串模型:{{ value }}</output>
<p class="example-paragraph">
min/max/step 是浏览器原生有效性约束,不自动裁剪模型;需要数值步进与裁剪时使用数字输入。
</p>
</div>
</template>
<script lang="ts" setup>
defineOptions({ name: 'AsamInputConstraintsExample' });
import { ref } from 'vue';
import { AsamInput } from '@asam-ui/ui';
const value = ref('3');
</script>
<style scoped>
.example {
display: grid;
gap: var(--asam-space-md);
min-width: 0;
}
.row {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: var(--asam-space-sm);
}
output {
color: var(--asam-color-text-secondary);
overflow-wrap: anywhere;
}
</style>
<style scoped>
p:where(.example-paragraph) {
margin-block: 16px;
line-height: 1.8;
overflow-wrap: anywhere;
}
</style>
<template>
<div class="example">
<AsamInput
v-model="value"
type="number"
min="1"
max="10"
step="2"
name="quantity"
inputmode="numeric"
aria-label="奇数数量"
/><output>字符串模型:{{ value }}</output>
<p class="example-paragraph">
min/max/step 是浏览器原生有效性约束,不自动裁剪模型;需要数值步进与裁剪时使用数字输入。
</p>
</div>
</template>
<script setup>
defineOptions({ name: 'AsamInputConstraintsExample' });
import { ref } from 'vue';
import { AsamInput } from '@asam-ui/ui';
const value = ref('3');
</script>
<style scoped>
.example {
display: grid;
gap: var(--asam-space-md);
min-width: 0;
}
.row {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: var(--asam-space-sm);
}
output {
color: var(--asam-color-text-secondary);
overflow-wrap: anywhere;
}
</style>
<style scoped>
p:where(.example-paragraph) {
margin-block: 16px;
line-height: 1.8;
overflow-wrap: anywhere;
}
</style>
字素计数 ​
countGraphemes 可按组合 emoji 或音调字符的可见字素计数。启用后计数、长度限制消费该函数,原生 maxlength/minlength 不设置;maxlength 仍用于展示与逻辑限制。wordLimitPosition 可以将计数放到外侧。
字素计数与长度限制
<template>
<div class="example">
<AsamInput
v-model="value"
:maxlength="5"
:count-graphemes="count"
show-word-limit
word-limit-position="outside"
aria-label="五个字符"
/>
<p class="example-paragraph">
试输组合 emoji、带音调字母。计数按可见字素;传入 countGraphemes 后原生
minlength/maxlength 不再设置。
</p>
<output>{{ value }};{{ count(value) }} 个字素</output>
</div>
</template>
<script lang="ts" setup>
defineOptions({ name: 'AsamInputGraphemesExample' });
import { ref } from 'vue';
import { AsamInput } from '@asam-ui/ui';
const value = ref('👨👩👧👦');
const segmenter = new Intl.Segmenter(undefined, { granularity: 'grapheme' });
const count = (text: string) => Array.from(segmenter.segment(text)).length;
</script>
<style scoped>
.example {
display: grid;
gap: var(--asam-space-md);
min-width: 0;
}
.row {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: var(--asam-space-sm);
}
output {
color: var(--asam-color-text-secondary);
overflow-wrap: anywhere;
}
</style>
<style scoped>
p:where(.example-paragraph) {
margin-block: 16px;
line-height: 1.8;
overflow-wrap: anywhere;
}
</style>
<template>
<div class="example">
<AsamInput
v-model="value"
:maxlength="5"
:count-graphemes="count"
show-word-limit
word-limit-position="outside"
aria-label="五个字符"
/>
<p class="example-paragraph">
试输组合 emoji、带音调字母。计数按可见字素;传入 countGraphemes 后原生
minlength/maxlength 不再设置。
</p>
<output>{{ value }};{{ count(value) }} 个字素</output>
</div>
</template>
<script setup>
defineOptions({ name: 'AsamInputGraphemesExample' });
import { ref } from 'vue';
import { AsamInput } from '@asam-ui/ui';
const value = ref('👨👩👧👦');
const segmenter = new Intl.Segmenter(undefined, { granularity: 'grapheme' });
const count = (text) => Array.from(segmenter.segment(text)).length;
</script>
<style scoped>
.example {
display: grid;
gap: var(--asam-space-md);
min-width: 0;
}
.row {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: var(--asam-space-sm);
}
output {
color: var(--asam-color-text-secondary);
overflow-wrap: anywhere;
}
</style>
<style scoped>
p:where(.example-paragraph) {
margin-block: 16px;
line-height: 1.8;
overflow-wrap: anywhere;
}
</style>
自定义清空与组合输入 ​
clearIcon 设置清空标记;compositionstart/update/end 提供原生 CompositionEvent。input 保持字符串 payload。clearable 会占用后缀区域,容器可配置宽度以保持布局稳定。
自定义清空与 IME 事件
<template>
<div class="example">
<AsamInput
v-model="value"
clearable
:clear-icon="clearIcon"
aria-label="自定义清空"
@clear="events.push('clear')"
@compositionstart="record"
@compositionupdate="record"
@compositionend="record"
/><output>{{ events.join(', ') }}</output>
</div>
</template>
<script lang="ts" setup>
defineOptions({ name: 'AsamInputClearIconExample' });
import { ref, h } from 'vue';
import { AsamInput } from '@asam-ui/ui';
const value = ref('可清空');
const events = ref<string[]>([]);
const clearIcon = () => h('span', { 'aria-hidden': 'true' }, '×');
function record(event: CompositionEvent) {
events.value.push(event.type);
}
</script>
<style scoped>
.example {
display: grid;
gap: var(--asam-space-md);
min-width: 0;
}
.row {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: var(--asam-space-sm);
}
output {
color: var(--asam-color-text-secondary);
overflow-wrap: anywhere;
}
</style>
<template>
<div class="example">
<AsamInput
v-model="value"
clearable
:clear-icon="clearIcon"
aria-label="自定义清空"
@clear="events.push('clear')"
@compositionstart="record"
@compositionupdate="record"
@compositionend="record"
/><output>{{ events.join(', ') }}</output>
</div>
</template>
<script setup>
defineOptions({ name: 'AsamInputClearIconExample' });
import { ref, h } from 'vue';
import { AsamInput } from '@asam-ui/ui';
const value = ref('可清空');
const events = ref([]);
const clearIcon = () => h('span', { 'aria-hidden': 'true' }, '×');
function record(event) {
events.value.push(event.type);
}
</script>
<style scoped>
.example {
display: grid;
gap: var(--asam-space-md);
min-width: 0;
}
.row {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: var(--asam-space-sm);
}
output {
color: var(--asam-color-text-secondary);
overflow-wrap: anywhere;
}
</style>
API 阅读方式 ​
下方 API 来自当前公开类型与运行默认值。默认值标为“未知 / 未声明”时,不代表 false、空值或未支持。省略 size 保留祖先上下文继承。省略 disabled 保留表单禁用继承;validateEvent 控制校验事件,不用 disabled 代替。
模型修饰符与真实更新类型 ​
支持 trim、number、lazy;number 可产生数字模型,lazy 在 change 时提交。切换 type 前先提交编辑,详见模型与提交规则。
模型修饰符与数字更新
<template>
<div class="example">
<AsamInput
v-model.trim.number.lazy="value"
aria-label="修饰符输入"
@update:model-value="record"
/>
<AsamButton type="default" native-type="button">移出焦点以提交</AsamButton>
<output>{{ JSON.stringify({ value, type: typeof value, updates }) }}</output>
<p class="example-paragraph">
输入数字并失焦后,更新为 number;非数字文本仍为 string。trim 移除两端空白,lazy
在提交时更新。
</p>
</div>
</template>
<script lang="ts" setup>
import { ref } from 'vue';
import { AsamButton, AsamInput } from '@asam-ui/ui';
import type { AsamInputEmits } from '@asam-ui/ui';
defineOptions({ name: 'AsamInputModifiersExample' });
const value = ref<string | number>('');
const updates = ref<(string | number)[]>([]);
function record(...[value]: AsamInputEmits['update:modelValue']) {
updates.value.push(value);
}
</script>
<style scoped>
.example {
display: grid;
gap: var(--asam-space-md);
}
</style>
<style scoped>
p:where(.example-paragraph) {
margin-block: 16px;
line-height: 1.8;
overflow-wrap: anywhere;
}
</style>
<template>
<div class="example">
<AsamInput
v-model.trim.number.lazy="value"
aria-label="修饰符输入"
@update:model-value="record"
/>
<AsamButton type="default" native-type="button">移出焦点以提交</AsamButton>
<output>{{ JSON.stringify({ value, type: typeof value, updates }) }}</output>
<p class="example-paragraph">
输入数字并失焦后,更新为 number;非数字文本仍为 string。trim 移除两端空白,lazy
在提交时更新。
</p>
</div>
</template>
<script setup>
import { ref } from 'vue';
import { AsamButton, AsamInput } from '@asam-ui/ui';
defineOptions({ name: 'AsamInputModifiersExample' });
const value = ref('');
const updates = ref([]);
function record(...[value]) {
updates.value.push(value);
}
</script>
<style scoped>
.example {
display: grid;
gap: var(--asam-space-md);
}
</style>
<style scoped>
p:where(.example-paragraph) {
margin-block: 16px;
line-height: 1.8;
overflow-wrap: anywhere;
}
</style>
五入口表单继承与校验 ​
本完整 TS/JS 组合实际实例化单行、密码、多行、建议和标签五个入口。省略各入口 disabled 以继承表单状态;validateEvent 控制各自 change/blur 自动校验。切换禁用不会清空模型,关闭自动校验不影响编辑。五页注册同一组合源码的自包含副本,复制当前示例即可运行,无需从其他组件页补齐文件。
五入口表单继承与校验
<template>
<!-- prettier-ignore -->
<div class="example">
<AsamCheckboxItem
v-model="disabled"
aria-label="禁用五入口表单">禁用整个表单</AsamCheckboxItem>
<AsamCheckboxItem v-model="validateEvent" aria-label="五入口自动校验">自动
change/blur 校验</AsamCheckboxItem>
<AsamBaseForm
ref="form"
:model="model"
:rules="rules"
:disabled="disabled"
@validate="record"
>
<AsamFormItem
label="单行"
prop="input"
>
<AsamInput
v-model="model.input"
:validate-event="validateEvent"
aria-label="表单单行"
/>
</AsamFormItem>
<AsamFormItem
label="密码"
prop="password"
>
<AsamPassword
v-model="model.password"
:validate-event="validateEvent"
aria-label="表单密码"
/>
</AsamFormItem>
<AsamFormItem
label="多行"
prop="textarea"
>
<AsamTextarea
v-model="model.textarea"
:validate-event="validateEvent"
aria-label="表单多行"
/>
</AsamFormItem>
<AsamFormItem
label="建议"
prop="autocomplete"
>
<AsamAutocomplete
v-model="model.autocomplete"
:fetch-suggestions="suggestions"
:validate-event="validateEvent"
aria-label="表单建议"
/>
</AsamFormItem>
<AsamFormItem
label="标签"
prop="tags"
>
<AsamInputTag
v-model="model.tags"
:validate-event="validateEvent"
aria-label="表单标签"
/>
</AsamFormItem>
</AsamBaseForm>
<AsamButton type="default" native-type="button" @click="reset">重置模型和校验记录</AsamButton>
<AsamButton type="default" native-type="button">提交编辑</AsamButton>
<output>{{ JSON.stringify({ model, disabled, validateEvent, validations }) }}</output>
</div>
</template>
<script lang="ts" setup>
import { ref } from 'vue';
import {
AsamCheckboxItem,
AsamButton,
AsamBaseForm,
AsamFormItem,
AsamInput,
AsamPassword,
AsamTextarea,
AsamAutocomplete,
AsamInputTag
} from '@asam-ui/ui';
import type { AsamBaseFormExpose } from '@asam-ui/ui';
defineOptions({ name: 'AsamFiveInputsFormExample' });
const model = ref({
input: '',
password: '',
textarea: '',
autocomplete: '',
tags: [] as string[]
});
const disabled = ref(false);
const validateEvent = ref(true);
const form = ref<AsamBaseFormExpose>();
const rules = Object.fromEntries(
['input', 'password', 'textarea', 'autocomplete', 'tags'].map((key) => [
key,
[{ required: true, message: '请完善此项', trigger: ['change', 'blur'] }]
])
);
const suggestions = [{ value: 'Alpha' }];
const validations = ref<{ prop: string; valid: boolean }[]>([]);
function record(prop: string | string[], valid: boolean) {
validations.value.push({ prop: String(prop), valid });
}
function reset() {
model.value = { input: '', password: '', textarea: '', autocomplete: '', tags: [] };
validations.value = [];
form.value?.clearValidate();
}
</script>
<style scoped>
.example {
display: grid;
gap: var(--asam-space-md);
}
</style>
<template>
<!-- prettier-ignore -->
<div class="example">
<AsamCheckboxItem
v-model="disabled"
aria-label="禁用五入口表单">禁用整个表单</AsamCheckboxItem>
<AsamCheckboxItem v-model="validateEvent" aria-label="五入口自动校验">自动
change/blur 校验</AsamCheckboxItem>
<AsamBaseForm
ref="form"
:model="model"
:rules="rules"
:disabled="disabled"
@validate="record"
>
<AsamFormItem
label="单行"
prop="input"
>
<AsamInput
v-model="model.input"
:validate-event="validateEvent"
aria-label="表单单行"
/>
</AsamFormItem>
<AsamFormItem
label="密码"
prop="password"
>
<AsamPassword
v-model="model.password"
:validate-event="validateEvent"
aria-label="表单密码"
/>
</AsamFormItem>
<AsamFormItem
label="多行"
prop="textarea"
>
<AsamTextarea
v-model="model.textarea"
:validate-event="validateEvent"
aria-label="表单多行"
/>
</AsamFormItem>
<AsamFormItem
label="建议"
prop="autocomplete"
>
<AsamAutocomplete
v-model="model.autocomplete"
:fetch-suggestions="suggestions"
:validate-event="validateEvent"
aria-label="表单建议"
/>
</AsamFormItem>
<AsamFormItem
label="标签"
prop="tags"
>
<AsamInputTag
v-model="model.tags"
:validate-event="validateEvent"
aria-label="表单标签"
/>
</AsamFormItem>
</AsamBaseForm>
<AsamButton type="default" native-type="button" @click="reset">重置模型和校验记录</AsamButton>
<AsamButton type="default" native-type="button">提交编辑</AsamButton>
<output>{{ JSON.stringify({ model, disabled, validateEvent, validations }) }}</output>
</div>
</template>
<script setup>
import { ref } from 'vue';
import {
AsamCheckboxItem,
AsamButton,
AsamBaseForm,
AsamFormItem,
AsamInput,
AsamPassword,
AsamTextarea,
AsamAutocomplete,
AsamInputTag
} from '@asam-ui/ui';
defineOptions({ name: 'AsamFiveInputsFormExample' });
const model = ref({ input: '', password: '', textarea: '', autocomplete: '', tags: [] });
const disabled = ref(false);
const validateEvent = ref(true);
const form = ref();
const rules = Object.fromEntries(
['input', 'password', 'textarea', 'autocomplete', 'tags'].map((key) => [
key,
[{ required: true, message: '请完善此项', trigger: ['change', 'blur'] }]
])
);
const suggestions = [{ value: 'Alpha' }];
const validations = ref([]);
function record(prop, valid) {
validations.value.push({ prop: String(prop), valid });
}
function reset() {
model.value = { input: '', password: '', textarea: '', autocomplete: '', tags: [] };
validations.value = [];
form.value?.clearValidate();
}
</script>
<style scoped>
.example {
display: grid;
gap: var(--asam-space-md);
}
</style>
动态原生类型与状态保留 ​
在同一入口切换 text 与 number,可观察模型、焦点和前缀插槽。类型切换和编辑均委托原生;本示例不承诺未提交 lazy 草稿、光标位置或焦点跨所有类型组合保留。number 的 setSelectionRange 限制由浏览器决定。
动态原生类型与状态保留
<template><StandaloneDemo /></template>
<script lang="ts" setup>
import * as __external0 from "vue";
import * as __external1 from "@asam-ui/ui";
const __external: any = {"vue": { ...__external0, __esModule: true },
"@asam-ui/ui": { ...__external1, __esModule: true }};
const __modules: any = {
"Demo.vue": (module: any, exports: any, require: any) => {
"use strict";
var __importDefault: any = function (mod?: any) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const vue_1: any = require("vue");
const vue_2: any = require("vue");
const _hoisted_1: any = { class: "example" };
const _hoisted_2: any = { class: "actions" };
const vue_3: any = require("vue");
const ui_1: any = require("@asam-ui/ui");
const SlotCounter_vue_1: any = __importDefault(require("./SlotCounter.vue"));
exports.default = (0, vue_1.defineComponent)({
...{ name: 'AsamInputDynamicTypeExample' },
__name: 'Demo',
setup(__props?: any) {
const kinds: any = ['text', 'number'];
const type: any = (0, vue_3.ref)('text');
const value: any = (0, vue_3.ref)('42');
const inputs: any = (0, vue_3.ref)([]);
return (_ctx?: any, _cache?: any) => {
return ((0, vue_2.openBlock)(), (0, vue_2.createElementBlock)("div", _hoisted_1, [
(0, vue_2.createElementVNode)("div", _hoisted_2, [
((0, vue_2.openBlock)(), (0, vue_2.createElementBlock)(vue_2.Fragment, null, (0, vue_2.renderList)(kinds, (kind?: any) => {
return (0, vue_2.createVNode)((0, vue_2.unref)(ui_1.AsamButton), {
type: "default",
key: kind,
"native-type": "button",
onPointerdown: _cache[0] || (_cache[0] = (0, vue_2.withModifiers)(() => { }, ["prevent"])),
onClick: ($event?: any) => (type.value = kind)
}, {
default: (0, vue_2.withCtx)(() => [
(0, vue_2.createTextVNode)((0, vue_2.toDisplayString)(kind), 1 /* TEXT */)
]),
_: 2 /* DYNAMIC */
}, 1032 /* PROPS, DYNAMIC_SLOTS */, ["onClick"]);
}), 64 /* STABLE_FRAGMENT */)),
_cache[3] || (_cache[3] = (0, vue_2.createElementVNode)("span", null, "先输入 42,再保持焦点切换类型;前缀按钮的计数应保留。", -1 /* CACHED */))
]),
(0, vue_2.createVNode)((0, vue_2.unref)(ui_1.AsamInput), {
modelValue: value.value,
"onUpdate:modelValue": _cache[1] || (_cache[1] = ($event?: any) => ((value).value = $event)),
type: type.value,
min: 2,
max: 10,
step: 2,
"aria-label": "动态输入类型",
onInput: _cache[2] || (_cache[2] = ($event?: any) => (inputs.value.push($event)))
}, {
prefix: (0, vue_2.withCtx)(() => [
(0, vue_2.createVNode)(SlotCounter_vue_1.default)
]),
_: 1 /* STABLE */
}, 8 /* PROPS */, ["modelValue", "type"]),
(0, vue_2.createElementVNode)("output", null, (0, vue_2.toDisplayString)(JSON.stringify({ type: type.value, value: value.value, inputs: inputs.value })), 1 /* TEXT */),
_cache[4] || (_cache[4] = (0, vue_2.createElementVNode)("p", { class: "example-paragraph" }, " number 的 min/max/step 保留原生约束;切回 text 后继续编辑。类型切换与光标行为由底层输入处理。number 不支持文本选区,调用文本选区方法可能抛出 InvalidStateError;此入口不补做游标恢复,也不保证未提交编辑值或焦点跨类型保留。 ", -1 /* CACHED */))
]));
};
}
});
exports.default.__scopeId = "data-v-c30f7e09";
},
"SlotCounter.vue": (module: any, exports: any, require: any) => {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const vue_1: any = require("vue");
const vue_2: any = require("vue");
const ui_1: any = require("@asam-ui/ui");
const vue_3: any = require("vue");
exports.default = (0, vue_1.defineComponent)({
__name: 'SlotCounter',
setup(__props?: any) {
const count: any = (0, vue_3.ref)(0);
return (_ctx?: any, _cache?: any) => {
return ((0, vue_2.openBlock)(), (0, vue_2.createBlock)((0, vue_2.unref)(ui_1.AsamButton), {
type: "default",
"native-type": "button",
onClick: _cache[0] || (_cache[0] = ($event?: any) => (count.value++))
}, {
default: (0, vue_2.withCtx)(() => [
(0, vue_2.createTextVNode)("前缀计数 " + (0, vue_2.toDisplayString)(count.value), 1 /* TEXT */)
]),
_: 1 /* STABLE */
}));
};
}
});
},
};
const __dependencies: any = {"Demo.vue":{"./SlotCounter.vue":"SlotCounter.vue"},"SlotCounter.vue":{}};
const __cache: any = Object.create(null);
function __require(id: any): any {
if (__external[id]) return __external[id];
if (__cache[id]) return __cache[id].exports;
const module: any = { exports: {} };
__cache[id] = module;
__modules[id](module, module.exports, (dependency: any) => __require(__dependencies[id][dependency] || dependency));
return module.exports;
}
const StandaloneDemo = __require('Demo.vue').default;
</script>
<style>
.example[data-v-c30f7e09] {
display: grid;
gap: var(--asam-space-md);
}
.actions[data-v-c30f7e09] {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: var(--asam-space-sm);
}
output[data-v-c30f7e09] {
overflow-wrap: anywhere;
}
p[data-v-c30f7e09]:where(.example-paragraph) {
margin-block: 16px;
line-height: 1.8;
overflow-wrap: anywhere;
}
</style>
<template><StandaloneDemo /></template>
<script setup>
import * as __external0 from "vue";
import * as __external1 from "@asam-ui/ui";
const __external = {"vue": { ...__external0, __esModule: true },
"@asam-ui/ui": { ...__external1, __esModule: true }};
const __modules = {
"Demo.vue": (module, exports, require) => {
"use strict";
var __importDefault = function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const vue_1 = require("vue");
const _hoisted_1 = { class: "example" };
const _hoisted_2 = { class: "actions" };
const vue_2 = require("vue");
const ui_1 = require("@asam-ui/ui");
const SlotCounter_vue_1 = __importDefault(require("./SlotCounter.vue"));
exports.default = Object.assign({ name: 'AsamInputDynamicTypeExample' }, {
__name: 'Demo',
setup(__props) {
const kinds = ['text', 'number'];
const type = (0, vue_2.ref)('text');
const value = (0, vue_2.ref)('42');
const inputs = (0, vue_2.ref)([]);
return (_ctx, _cache) => {
return ((0, vue_1.openBlock)(), (0, vue_1.createElementBlock)("div", _hoisted_1, [
(0, vue_1.createElementVNode)("div", _hoisted_2, [
((0, vue_1.openBlock)(), (0, vue_1.createElementBlock)(vue_1.Fragment, null, (0, vue_1.renderList)(kinds, (kind) => {
return (0, vue_1.createVNode)((0, vue_1.unref)(ui_1.AsamButton), {
type: "default",
key: kind,
"native-type": "button",
onPointerdown: _cache[0] || (_cache[0] = (0, vue_1.withModifiers)(() => { }, ["prevent"])),
onClick: $event => (type.value = kind)
}, {
default: (0, vue_1.withCtx)(() => [
(0, vue_1.createTextVNode)((0, vue_1.toDisplayString)(kind), 1 /* TEXT */)
]),
_: 2 /* DYNAMIC */
}, 1032 /* PROPS, DYNAMIC_SLOTS */, ["onClick"]);
}), 64 /* STABLE_FRAGMENT */)),
_cache[3] || (_cache[3] = (0, vue_1.createElementVNode)("span", null, "先输入 42,再保持焦点切换类型;前缀按钮的计数应保留。", -1 /* CACHED */))
]),
(0, vue_1.createVNode)((0, vue_1.unref)(ui_1.AsamInput), {
modelValue: value.value,
"onUpdate:modelValue": _cache[1] || (_cache[1] = $event => ((value).value = $event)),
type: type.value,
min: 2,
max: 10,
step: 2,
"aria-label": "动态输入类型",
onInput: _cache[2] || (_cache[2] = $event => (inputs.value.push($event)))
}, {
prefix: (0, vue_1.withCtx)(() => [
(0, vue_1.createVNode)(SlotCounter_vue_1.default)
]),
_: 1 /* STABLE */
}, 8 /* PROPS */, ["modelValue", "type"]),
(0, vue_1.createElementVNode)("output", null, (0, vue_1.toDisplayString)(JSON.stringify({ type: type.value, value: value.value, inputs: inputs.value })), 1 /* TEXT */),
_cache[4] || (_cache[4] = (0, vue_1.createElementVNode)("p", { class: "example-paragraph" }, " number 的 min/max/step 保留原生约束;切回 text 后继续编辑。类型切换与光标行为由底层输入处理。number 不支持文本选区,调用文本选区方法可能抛出 InvalidStateError;此入口不补做游标恢复,也不保证未提交编辑值或焦点跨类型保留。 ", -1 /* CACHED */))
]));
};
}
});
exports.default.__scopeId = "data-v-5d776f14";
},
"SlotCounter.vue": (module, exports, require) => {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const vue_1 = require("vue");
const ui_1 = require("@asam-ui/ui");
const vue_2 = require("vue");
exports.default = {
__name: 'SlotCounter',
setup(__props) {
const count = (0, vue_2.ref)(0);
return (_ctx, _cache) => {
return ((0, vue_1.openBlock)(), (0, vue_1.createBlock)((0, vue_1.unref)(ui_1.AsamButton), {
type: "default",
"native-type": "button",
onClick: _cache[0] || (_cache[0] = $event => (count.value++))
}, {
default: (0, vue_1.withCtx)(() => [
(0, vue_1.createTextVNode)("前缀计数 " + (0, vue_1.toDisplayString)(count.value), 1 /* TEXT */)
]),
_: 1 /* STABLE */
}));
};
}
};
},
};
const __dependencies = {"Demo.vue":{"./SlotCounter.vue":"SlotCounter.vue"},"SlotCounter.vue":{}};
const __cache = Object.create(null);
function __require(id) {
if (__external[id]) return __external[id];
if (__cache[id]) return __cache[id].exports;
const module = { exports: {} };
__cache[id] = module;
__modules[id](module, module.exports, (dependency) => __require(__dependencies[id][dependency] || dependency));
return module.exports;
}
const StandaloneDemo = __require('Demo.vue').default;
</script>
<style>
.example[data-v-5d776f14] {
display: grid;
gap: var(--asam-space-md);
}
.actions[data-v-5d776f14] {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: var(--asam-space-sm);
}
output[data-v-5d776f14] {
overflow-wrap: anywhere;
}
p[data-v-5d776f14]:where(.example-paragraph) {
margin-block: 16px;
line-height: 1.8;
overflow-wrap: anywhere;
}
</style>
原生委托与事件记录 ​
下方完整 TS/JS 示例记录模型及事件顺序,并可切换禁用、只读和自动校验状态。 完整说明。
原生委托与事件记录
<template>
<section class="native-comparison">
<AsamCheckboxItem v-model="disabled">禁用</AsamCheckboxItem>
<AsamCheckboxItem v-model="readonly">只读</AsamCheckboxItem>
<AsamCheckboxItem v-model="validateEvent">自动校验</AsamCheckboxItem>
<p class="example-paragraph">ASAM</p>
<AsamInput
v-model="asam"
:disabled="disabled"
:readonly="readonly"
:validate-event="validateEvent"
aria-label="ASAM 原生委托"
@update:model-value="(...args) => record('ASAM', 'update:modelValue', ...args)"
@input="(...args) => record('ASAM', 'input', ...args)"
@change="(...args) => record('ASAM', 'change', ...args)"
@blur="(...args) => record('ASAM', 'blur', ...args)"
/>
<AsamButton type="default" native-type="button" @click="events = []"
>清空事件记录</AsamButton
>
<pre>{{ JSON.stringify({ asam, events }, null, 2) }}</pre>
</section>
</template>
<script lang="ts" setup>
import { ref } from 'vue';
import { AsamCheckboxItem, AsamButton, AsamInput } from '@asam-ui/ui';
defineOptions({ name: 'AsamInputNativeDelegationExample' });
const asam = ref<string | number>('');
const disabled = ref(false);
const readonly = ref(false);
const validateEvent = ref(true);
const events = ref<{ source: string; event: string; values: unknown[] }[]>([]);
function record(source: string, event: string, ...values: unknown[]) {
events.value.push({
source,
event,
values: values.map((value) => (value instanceof Event ? value.type : value))
});
}
</script>
<style scoped>
.native-comparison {
display: grid;
gap: var(--asam-space-sm);
}
</style>
<style scoped>
p:where(.example-paragraph) {
margin-block: 16px;
line-height: 1.8;
overflow-wrap: anywhere;
}
</style>
<template>
<section class="native-comparison">
<AsamCheckboxItem v-model="disabled">禁用</AsamCheckboxItem>
<AsamCheckboxItem v-model="readonly">只读</AsamCheckboxItem>
<AsamCheckboxItem v-model="validateEvent">自动校验</AsamCheckboxItem>
<p class="example-paragraph">ASAM</p>
<AsamInput
v-model="asam"
:disabled="disabled"
:readonly="readonly"
:validate-event="validateEvent"
aria-label="ASAM 原生委托"
@update:model-value="(...args) => record('ASAM', 'update:modelValue', ...args)"
@input="(...args) => record('ASAM', 'input', ...args)"
@change="(...args) => record('ASAM', 'change', ...args)"
@blur="(...args) => record('ASAM', 'blur', ...args)"
/>
<AsamButton type="default" native-type="button" @click="events = []"
>清空事件记录</AsamButton
>
<pre>{{ JSON.stringify({ asam, events }, null, 2) }}</pre>
</section>
</template>
<script setup>
import { ref } from 'vue';
import { AsamCheckboxItem, AsamButton, AsamInput } from '@asam-ui/ui';
defineOptions({ name: 'AsamInputNativeDelegationExample' });
const asam = ref('');
const disabled = ref(false);
const readonly = ref(false);
const validateEvent = ref(true);
const events = ref([]);
function record(source, event, ...values) {
events.value.push({
source,
event,
values: values.map((value) => (value instanceof Event ? value.type : value))
});
}
</script>
<style scoped>
.native-comparison {
display: grid;
gap: var(--asam-space-sm);
}
</style>
<style scoped>
p:where(.example-paragraph) {
margin-block: 16px;
line-height: 1.8;
overflow-wrap: anywhere;
}
</style>
API
属性 AsamInputProps
| 属性名 | 说明 | 类型 | 默认值 |
|---|---|---|---|
id | 等价于原生 input id 属性 | string | undefined | — |
size | 显式控件密度;省略时继承按钮组、表单和配置提供器。 | enum"large" | "big" | "default" | "small"完整类型:AsamControlSize | undefined | — |
disabled | 是否禁用 | boolean | undefined | false |
modelValue | 输入值 | string | number | null | undefined | — |
modelModifiers | v-model 修饰符,参考 Vue 修饰符 | (AsamInputProps)["modelModifiers"] | — |
maxlength | 等价于原生 maxlength 属性 | string | number | undefined | — |
minlength | 等价于原生 minlength 属性 | string | number | undefined | — |
min | type="number" 时的原生最小值。 | (string | number) | undefined | — |
max | type="number" 时的原生最大值。 | (string | number) | undefined | — |
step | 原生步长,包括 any。 | (string | number) | undefined | — |
type | 文本输入类型;其他表单控件使用对应的独立组件。 | enum"number" | "text" | "email" | "search" | "tel" | "url"完整类型:AsamInputType | undefined | — |
autocomplete | 原生输入自动完成;联合类型包含大量字面量时可能触发 TS2590,详见 Vue 问题 10514。 | string | undefined | — |
formatter | 格式化显示内容。 | ((value: string) => string) | undefined | — |
parser | 解析显示内容。 | ((value: string) => string) | undefined | — |
placeholder | 输入框占位文本 | string | undefined | — |
form | 原生输入的表单关联。 | string | undefined | — |
readonly | 原生输入的只读状态。 | boolean | undefined | false |
clearable | 是否显示清除按钮 | boolean | undefined | false |
clearIcon | 自定义清除图标 | (AsamInputProps)["clearIcon"] | — |
showWordLimit | 字符计数。 | boolean | undefined | false |
wordLimitPosition | 字数统计的位置,仅当 show-word-limit 为 true 时生效。 | enum"outside" | "inside"完整类型:"outside" | "inside" | undefined | — |
suffixIcon | 后缀图标。 | (AsamInputProps)["suffixIcon"] | — |
prefixIcon | 前缀图标。 | (AsamInputProps)["prefixIcon"] | — |
containerRole | 容器角色;原生内部属性用于选择器组件。 | string | undefined | — |
tabindex | 等价于原生 tabindex 属性 | string | number | undefined | — |
validateEvent | 是否触发表单验证 | boolean | undefined | false |
inputStyle | 输入框或文本域元素样式。 | import("vue").StyleValue | false |
autofocus | 原生输入自动聚焦。 | boolean | undefined | false |
ariaLabel | 原生 aria-label属性 | string | undefined | — |
inputmode | 原生虚拟键盘输入模式。 | enum"text" | "email" | "search" | "tel" | "url" | "none" | "numeric" | "decimal"完整类型:"text" | "email" | "search" | "tel" | "url" | "none" | "numeric" | "decimal" | undefined | — |
name | 原生属性 | string | undefined | — |
countGraphemes | 按字素统计输入长度;设置后不使用原生 maxlength 和 minlength。 | ((value: string) => number) | undefined | — |
事件 AsamInputEmits
| 属性名 | 说明 | 类型 | 默认值 |
|---|---|---|---|
update:modelValue | — | [value: string | number] | — |
input | — | [value: string] | — |
change | — | [value: string, event?: Event | undefined] | — |
focus | — | [event: FocusEvent] | — |
blur | — | [event: FocusEvent] | — |
clear | — | [event?: MouseEvent | undefined] | — |
mouseenter | — | [event: MouseEvent] | — |
mouseleave | — | [event: MouseEvent] | — |
keydown | — | [event: Event | KeyboardEvent] | — |
compositionstart | — | [event: CompositionEvent] | — |
compositionupdate | — | [event: CompositionEvent] | — |
compositionend | — | [event: CompositionEvent] | — |
插槽 AsamInputSlots
| 属性名 | 说明 | 类型 | 默认值 |
|---|---|---|---|
prefix | — | (() => unknown) | undefined | — |
suffix | — | (() => unknown) | undefined | — |
prepend | — | (() => unknown) | undefined | — |
append | — | (() => unknown) | undefined | — |
实例方法与状态 AsamInputExpose
| 属性名 | 说明 | 类型 | 默认值 |
|---|---|---|---|
input | — | HTMLInputElement | undefined | — |
textarea | — | HTMLTextAreaElement | undefined | — |
ref | — | HTMLInputElement | HTMLTextAreaElement | undefined | — |
textareaStyle | — | import("vue").StyleValue | — |
autosize | — | (AsamInputExpose)["autosize"] | — |
isComposing | — | boolean | — |
passwordVisible | — | boolean | — |
focus | — | () => void | — |
blur | — | () => void | — |
select | — | () => void | — |
clear | — | (event?: MouseEvent) => void | — |
resizeTextarea | — | () => void | — |
模型与事件补充说明 ​
模型修饰符与提交规则 ​
trim、number、lazy 按原生模型修饰协议承接。启用 number 时 update:modelValue 可能为数字;无法转换的文本仍为字符串。input/change 保留各自事件签名,不能从更新类型中删去合法数字。
lazy 依赖实际的原生 change 提交模型,失焦本身不额外提交。未提交的编辑草稿没有独立保存:切换 type 后,后续渲染会按父级已提交的 modelValue 恢复输入显示,草稿可能因此丢失;这也可能发生在同一输入节点仍保持焦点时。需要保留该次编辑值时,先完成提交并确认父级接受,再切换类型。
用法与契约补充说明 ​
ASAM 扩展与迁移 ​
四档 size 是 ASAM 密度扩展。旧 type="password" 和 showPassword 从单行输入迁至专用 Password;旧 type="textarea"、rows、autosize、resize 迁至专用 Textarea。ariaLabel、name、autocomplete、inputmode 按实际输入场景配置;validateEvent 控制表单校验触发。
原生委托与事件记录 ​
下方完整 TS/JS 示例记录模型及事件顺序,并可切换禁用、只读和自动校验状态。省略的基础参数使用原生 defaults;显式 undefined/null/false 原样传入,合法值范围见 API。四档 size 是 ASAM 的视觉桥接;Password 额外固定 type=password,并在省略 showPassword 时启用显隐入口。
关联组件
参数与事件补充说明
参数与事件说明
id
必填:否;声明来源:ASAM 声明。
默认值与来源
未知 / 未声明固定上游源码默认表达式:undefined(2.14.7;源码事实,未作为 ASAM 运行实测)
size
必填:否;声明来源:ASAM 声明。
size 参数与事件数据
下列为声明可读视图;可导入类型以公开类型视图为准。分支条件与父属性一致。
枚举:"large" / "big" / "default" / "small"
disabled
必填:否;声明来源:ASAM 声明。
disabled 参数与事件数据
下列为声明可读视图;可导入类型以公开类型视图为准。分支条件与父属性一致。
枚举:false / true
默认值与来源
false(隐式 Boolean 默认;已安装组件)固定上游文档默认:false(2.14.7;文档事实,实际默认以 ASAM 源码 / 安装包为准)
固定上游源码默认表达式:undefined(2.14.7;源码事实,未作为 ASAM 运行实测)
modelValue
必填:否;声明来源:ASAM 声明。
默认值与来源
未知 / 未声明固定上游文档默认:未声明(2.14.7;文档事实,实际默认以 ASAM 源码 / 安装包为准)
固定上游源码默认表达式:''(2.14.7;源码事实,未作为 ASAM 运行实测)
modelModifiers
必填:否;声明来源:ASAM 声明。
modelModifiers 参数与事件数据
下列为声明可读视图;可导入类型以公开类型视图为准。分支条件与父属性一致。
modelModifiers.lazy:true | undefined— 上游声明枚举:
truemodelModifiers.number:true | undefined— 上游声明枚举:
truemodelModifiers.trim:true | undefined— 上游声明枚举:
true
默认值与来源
未知 / 未声明固定上游文档默认:未声明(2.14.7;文档事实,实际默认以 ASAM 源码 / 安装包为准)
固定上游源码工厂(未执行):() => ({})(2.14.7;源码事实,未作为 ASAM 运行实测)
maxlength
必填:否;声明来源:ASAM 声明。
默认值与来源
未知 / 未声明固定上游文档默认:未声明(2.14.7;文档事实,实际默认以 ASAM 源码 / 安装包为准)
固定上游源码未声明 default(2.14.7;源码事实,未作为 ASAM 运行实测)
minlength
必填:否;声明来源:ASAM 声明。
默认值与来源
未知 / 未声明固定上游文档默认:未声明(2.14.7;文档事实,实际默认以 ASAM 源码 / 安装包为准)
固定上游源码未声明 default(2.14.7;源码事实,未作为 ASAM 运行实测)
min
必填:否;声明来源:ASAM 声明。
max
必填:否;声明来源:ASAM 声明。
step
必填:否;声明来源:ASAM 声明。
type
必填:否;声明来源:ASAM 声明。
type 参数与事件数据
下列为声明可读视图;可导入类型以公开类型视图为准。分支条件与父属性一致。
枚举:"number" / "text" / "email" / "search" / "tel" / "url"
autocomplete
必填:否;声明来源:ASAM 声明。
默认值与来源
未知 / 未声明固定上游文档默认:off(2.14.7;文档事实,实际默认以 ASAM 源码 / 安装包为准)
固定上游源码默认表达式:'off'(2.14.7;源码事实,未作为 ASAM 运行实测)
formatter
必填:否;声明来源:ASAM 声明。
formatter 参数与事件数据
下列为声明可读视图;可导入类型以公开类型视图为准。分支条件与父属性一致。
事件参数:(value: string): string
默认值与来源
未知 / 未声明固定上游文档默认:未声明(2.14.7;文档事实,实际默认以 ASAM 源码 / 安装包为准)
固定上游源码未声明 default(2.14.7;源码事实,未作为 ASAM 运行实测)
parser
必填:否;声明来源:ASAM 声明。
parser 参数与事件数据
下列为声明可读视图;可导入类型以公开类型视图为准。分支条件与父属性一致。
事件参数:(value: string): string
默认值与来源
未知 / 未声明固定上游文档默认:未声明(2.14.7;文档事实,实际默认以 ASAM 源码 / 安装包为准)
固定上游源码未声明 default(2.14.7;源码事实,未作为 ASAM 运行实测)
placeholder
必填:否;声明来源:ASAM 声明。
默认值与来源
未知 / 未声明固定上游文档默认:未声明(2.14.7;文档事实,实际默认以 ASAM 源码 / 安装包为准)
固定上游源码未声明 default(2.14.7;源码事实,未作为 ASAM 运行实测)
form
必填:否;声明来源:ASAM 声明。
默认值与来源
未知 / 未声明固定上游文档默认:未声明(2.14.7;文档事实,实际默认以 ASAM 源码 / 安装包为准)
固定上游源码未声明 default(2.14.7;源码事实,未作为 ASAM 运行实测)
readonly
必填:否;声明来源:ASAM 声明。
readonly 参数与事件数据
下列为声明可读视图;可导入类型以公开类型视图为准。分支条件与父属性一致。
枚举:false / true
默认值与来源
false(隐式 Boolean 默认;已安装组件)固定上游文档默认:false(2.14.7;文档事实,实际默认以 ASAM 源码 / 安装包为准)
clearable
必填:否;声明来源:ASAM 声明。
clearable 参数与事件数据
下列为声明可读视图;可导入类型以公开类型视图为准。分支条件与父属性一致。
枚举:false / true
默认值与来源
false(隐式 Boolean 默认;已安装组件)固定上游文档默认:false(2.14.7;文档事实,实际默认以 ASAM 源码 / 安装包为准)
clearIcon
必填:否;声明来源:ASAM 声明。
clearIcon 参数与事件数据
下列为声明可读视图;可导入类型以公开类型视图为准。分支条件与父属性一致。
事件参数:(props: any, ctx: Parameters<Extract<NonNullable<(AsamInputProps)["clearIcon"]>, (...args: never[]) => unknown>>[1]): any
clearIcon.__isFragment:undefined— 依赖声明clearIcon.__isTeleport:undefined— 依赖声明clearIcon.__isSuspense:undefined— 依赖声明
默认值与来源
未知 / 未声明固定上游文档默认:CircleClose(2.14.7;文档事实,实际默认以 ASAM 源码 / 安装包为准)
固定上游源码默认表达式:CircleClose(2.14.7;源码事实,未作为 ASAM 运行实测)
showWordLimit
必填:否;声明来源:ASAM 声明。
showWordLimit 参数与事件数据
下列为声明可读视图;可导入类型以公开类型视图为准。分支条件与父属性一致。
枚举:false / true
默认值与来源
false(隐式 Boolean 默认;已安装组件)固定上游文档默认:false(2.14.7;文档事实,实际默认以 ASAM 源码 / 安装包为准)
wordLimitPosition
必填:否;声明来源:ASAM 声明。
wordLimitPosition 参数与事件数据
下列为声明可读视图;可导入类型以公开类型视图为准。分支条件与父属性一致。
枚举:"outside" / "inside"
默认值与来源
未知 / 未声明固定上游文档默认:"inside"(2.14.7;文档事实,实际默认以 ASAM 源码 / 安装包为准)
固定上游源码默认表达式:'inside'(2.14.7;源码事实,未作为 ASAM 运行实测)
suffixIcon
必填:否;声明来源:ASAM 声明。
suffixIcon 参数与事件数据
下列为声明可读视图;可导入类型以公开类型视图为准。分支条件与父属性一致。
事件参数:(props: any, ctx: Parameters<Extract<NonNullable<(AsamInputProps)["suffixIcon"]>, (...args: never[]) => unknown>>[1]): any
suffixIcon.__isFragment:undefined— 依赖声明suffixIcon.__isTeleport:undefined— 依赖声明suffixIcon.__isSuspense:undefined— 依赖声明
默认值与来源
未知 / 未声明固定上游文档默认:未声明(2.14.7;文档事实,实际默认以 ASAM 源码 / 安装包为准)
固定上游源码未声明 default(2.14.7;源码事实,未作为 ASAM 运行实测)
prefixIcon
必填:否;声明来源:ASAM 声明。
prefixIcon 参数与事件数据
下列为声明可读视图;可导入类型以公开类型视图为准。分支条件与父属性一致。
事件参数:(props: any, ctx: Parameters<Extract<NonNullable<(AsamInputProps)["prefixIcon"]>, (...args: never[]) => unknown>>[1]): any
prefixIcon.__isFragment:undefined— 依赖声明prefixIcon.__isTeleport:undefined— 依赖声明prefixIcon.__isSuspense:undefined— 依赖声明
默认值与来源
未知 / 未声明固定上游文档默认:未声明(2.14.7;文档事实,实际默认以 ASAM 源码 / 安装包为准)
固定上游源码未声明 default(2.14.7;源码事实,未作为 ASAM 运行实测)
containerRole
必填:否;声明来源:ASAM 声明。
默认值与来源
未知 / 未声明固定上游源码默认表达式:undefined(2.14.7;源码事实,未作为 ASAM 运行实测)
tabindex
必填:否;声明来源:ASAM 声明。
默认值与来源
未知 / 未声明固定上游文档默认:未声明(2.14.7;文档事实,实际默认以 ASAM 源码 / 安装包为准)
固定上游源码默认表达式:0(2.14.7;源码事实,未作为 ASAM 运行实测)
validateEvent
必填:否;声明来源:ASAM 声明。
validateEvent 参数与事件数据
下列为声明可读视图;可导入类型以公开类型视图为准。分支条件与父属性一致。
枚举:false / true
默认值与来源
false(隐式 Boolean 默认;已安装组件)固定上游文档默认:true(2.14.7;文档事实,实际默认以 ASAM 源码 / 安装包为准)
固定上游源码默认表达式:true(2.14.7;源码事实,未作为 ASAM 运行实测)
inputStyle
必填:否;声明来源:ASAM 声明。
inputStyle 参数与事件数据
下列为声明可读视图;可导入类型以公开类型视图为准。分支条件与父属性一致。
枚举:false
嵌套展开边界:框架 / 平台类型;完整类型见公开类型视图。
默认值与来源
false(隐式 Boolean 默认;已安装组件)固定上游文档默认:{}(2.14.7;文档事实,实际默认以 ASAM 源码 / 安装包为准)
固定上游源码工厂(未执行):() => mutable({} as const)(2.14.7;源码事实,未作为 ASAM 运行实测)
autofocus
必填:否;声明来源:ASAM 声明。
autofocus 参数与事件数据
下列为声明可读视图;可导入类型以公开类型视图为准。分支条件与父属性一致。
枚举:false / true
默认值与来源
false(隐式 Boolean 默认;已安装组件)固定上游文档默认:false(2.14.7;文档事实,实际默认以 ASAM 源码 / 安装包为准)
ariaLabel
必填:否;声明来源:ASAM 声明。
默认值与来源
未知 / 未声明固定上游文档默认:未声明(2.14.7;文档事实,实际默认以 ASAM 源码 / 安装包为准)
inputmode
必填:否;声明来源:ASAM 声明。
inputmode 参数与事件数据
下列为声明可读视图;可导入类型以公开类型视图为准。分支条件与父属性一致。
枚举:"text" / "email" / "search" / "tel" / "url" / "none" / "numeric" / "decimal"
默认值与来源
未知 / 未声明固定上游文档默认:未声明(2.14.7;文档事实,实际默认以 ASAM 源码 / 安装包为准)
固定上游源码默认表达式:undefined(2.14.7;源码事实,未作为 ASAM 运行实测)
name
必填:否;声明来源:ASAM 声明。
默认值与来源
未知 / 未声明固定上游文档默认:未声明(2.14.7;文档事实,实际默认以 ASAM 源码 / 安装包为准)
countGraphemes
必填:否;声明来源:ASAM 声明。
countGraphemes 参数与事件数据
下列为声明可读视图;可导入类型以公开类型视图为准。分支条件与父属性一致。
事件参数:(value: string): number
默认值与来源
未知 / 未声明固定上游文档默认:未声明(2.14.7;文档事实,实际默认以 ASAM 源码 / 安装包为准)
固定上游源码未声明 default(2.14.7;源码事实,未作为 ASAM 运行实测)
AsamInputProps 公开类型视图
import type { Attrs } from 'vue';
import type { AsamInputProps, AsamInputOtpProps, AsamControlSize, AsamInputType, AsamInputExpose } from '@asam-ui/ui';
type PublicMember<T, K extends PropertyKey> = T extends unknown ? K extends keyof T ? T[K] : never : never;
// AsamInputProps
type PublicContract = {
readonly "id"?: string | undefined;
readonly "size"?: AsamControlSize | undefined;
readonly "disabled"?: boolean | undefined;
readonly "modelValue"?: string | number | null | undefined;
readonly "modelModifiers"?: (AsamInputProps)["modelModifiers"];
readonly "maxlength"?: string | number | undefined;
readonly "minlength"?: string | number | undefined;
readonly "min"?: (string | number) | undefined;
readonly "max"?: (string | number) | undefined;
readonly "step"?: (string | number) | undefined;
readonly "type"?: AsamInputType | undefined;
readonly "autocomplete"?: string | undefined;
readonly "formatter"?: ((value: string) => string) | undefined;
readonly "parser"?: ((value: string) => string) | undefined;
readonly "placeholder"?: string | undefined;
readonly "form"?: string | undefined;
readonly "readonly"?: boolean | undefined;
readonly "clearable"?: boolean | undefined;
readonly "clearIcon"?: (AsamInputProps)["clearIcon"];
readonly "showWordLimit"?: boolean | undefined;
readonly "wordLimitPosition"?: "outside" | "inside" | undefined;
readonly "suffixIcon"?: (AsamInputProps)["suffixIcon"];
readonly "prefixIcon"?: (AsamInputProps)["prefixIcon"];
readonly "containerRole"?: string | undefined;
readonly "tabindex"?: string | number | undefined;
readonly "validateEvent"?: boolean | undefined;
readonly "inputStyle"?: import("vue").StyleValue;
readonly "autofocus"?: boolean | undefined;
readonly "ariaLabel"?: string | undefined;
readonly "inputmode"?: "text" | "email" | "search" | "tel" | "url" | "none" | "numeric" | "decimal" | undefined;
readonly "name"?: string | undefined;
readonly "countGraphemes"?: ((value: string) => number) | undefined;
};
参数与事件说明
update:modelValue
必填:是;声明来源:ASAM 声明。
input
必填:是;声明来源:ASAM 声明。
change
必填:是;声明来源:ASAM 声明。
focus
必填:是;声明来源:ASAM 声明。
blur
必填:是;声明来源:ASAM 声明。
clear
必填:是;声明来源:ASAM 声明。
mouseenter
必填:是;声明来源:ASAM 声明。
mouseleave
必填:是;声明来源:ASAM 声明。
keydown
必填:是;声明来源:ASAM 声明。
compositionstart
必填:是;声明来源:ASAM 声明。
compositionupdate
必填:是;声明来源:ASAM 声明。
compositionend
必填:是;声明来源:ASAM 声明。
AsamInputEmits 公开类型视图
import type { AsamInputEmits } from '@asam-ui/ui';
// AsamInputEmits
type PublicContract = {
"update:modelValue": [value: string | number];
"input": [value: string];
"change": [value: string, event?: Event | undefined];
"focus": [event: FocusEvent];
"blur": [event: FocusEvent];
"clear": [event?: MouseEvent | undefined];
"mouseenter": [event: MouseEvent];
"mouseleave": [event: MouseEvent];
"keydown": [event: Event | KeyboardEvent];
"compositionstart": [event: CompositionEvent];
"compositionupdate": [event: CompositionEvent];
"compositionend": [event: CompositionEvent];
};
参数与事件说明
prefix
必填:否;声明来源:ASAM 声明。
prefix 参数与事件数据
下列为声明可读视图;可导入类型以公开类型视图为准。分支条件与父属性一致。
事件参数:(): unknown
suffix
必填:否;声明来源:ASAM 声明。
suffix 参数与事件数据
下列为声明可读视图;可导入类型以公开类型视图为准。分支条件与父属性一致。
事件参数:(): unknown
prepend
必填:否;声明来源:ASAM 声明。
prepend 参数与事件数据
下列为声明可读视图;可导入类型以公开类型视图为准。分支条件与父属性一致。
事件参数:(): unknown
append
必填:否;声明来源:ASAM 声明。
append 参数与事件数据
下列为声明可读视图;可导入类型以公开类型视图为准。分支条件与父属性一致。
事件参数:(): unknown
AsamInputSlots 公开类型视图
import type { AsamInputSlots } from '@asam-ui/ui';
// AsamInputSlots
type PublicContract = {
"prefix"?: (() => unknown) | undefined;
"suffix"?: (() => unknown) | undefined;
"prepend"?: (() => unknown) | undefined;
"append"?: (() => unknown) | undefined;
};
响应式实例状态与基础编辑操作。
参数与事件说明
input
必填:是;声明来源:ASAM 声明。
input 参数与事件数据
下列为声明可读视图;可导入类型以公开类型视图为准。分支条件与父属性一致。
嵌套展开边界:大型实例类型;完整类型见公开类型视图。
textarea
必填:是;声明来源:ASAM 声明。
textarea 参数与事件数据
下列为声明可读视图;可导入类型以公开类型视图为准。分支条件与父属性一致。
嵌套展开边界:大型实例类型;完整类型见公开类型视图。
ref
必填:是;声明来源:ASAM 声明。
ref 参数与事件数据
下列为声明可读视图;可导入类型以公开类型视图为准。分支条件与父属性一致。
嵌套展开边界:大型实例类型;完整类型见公开类型视图。
textareaStyle
必填:是;声明来源:ASAM 声明。
textareaStyle 参数与事件数据
下列为声明可读视图;可导入类型以公开类型视图为准。分支条件与父属性一致。
枚举:false
嵌套展开边界:框架 / 平台类型;完整类型见公开类型视图。
autosize
必填:是;声明来源:ASAM 声明。
autosize 参数与事件数据
下列为声明可读视图;可导入类型以公开类型视图为准。分支条件与父属性一致。
枚举:false / true
autosize.minRows:number | undefined— 上游声明autosize.maxRows:number | undefined— 上游声明
isComposing
必填:是;声明来源:ASAM 声明。
isComposing 参数与事件数据
下列为声明可读视图;可导入类型以公开类型视图为准。分支条件与父属性一致。
枚举:false / true
passwordVisible
必填:是;声明来源:ASAM 声明。
passwordVisible 参数与事件数据
下列为声明可读视图;可导入类型以公开类型视图为准。分支条件与父属性一致。
枚举:false / true
focus
必填:是;声明来源:ASAM 声明。
focus 参数与事件数据
下列为声明可读视图;可导入类型以公开类型视图为准。分支条件与父属性一致。
事件参数:(): void
blur
必填:是;声明来源:ASAM 声明。
blur 参数与事件数据
下列为声明可读视图;可导入类型以公开类型视图为准。分支条件与父属性一致。
事件参数:(): void
select
必填:是;声明来源:ASAM 声明。
select 参数与事件数据
下列为声明可读视图;可导入类型以公开类型视图为准。分支条件与父属性一致。
事件参数:(): void
clear
必填:是;声明来源:ASAM 声明。
clear 参数与事件数据
下列为声明可读视图;可导入类型以公开类型视图为准。分支条件与父属性一致。
事件参数:(event?: MouseEvent | undefined): void
resizeTextarea
必填:是;声明来源:ASAM 声明。
resizeTextarea 参数与事件数据
下列为声明可读视图;可导入类型以公开类型视图为准。分支条件与父属性一致。
事件参数:(): void
AsamInputExpose 公开类型视图
import type { AsamInputExpose, AsamInputOtpProps } from '@asam-ui/ui';
type PublicMember<T, K extends PropertyKey> = T extends unknown ? K extends keyof T ? T[K] : never : never;
// AsamInputExpose
type PublicContract = {
readonly "input": HTMLInputElement | undefined;
readonly "textarea": HTMLTextAreaElement | undefined;
readonly "ref": HTMLInputElement | HTMLTextAreaElement | undefined;
readonly "textareaStyle": import("vue").StyleValue;
readonly "autosize": (AsamInputExpose)["autosize"];
readonly "isComposing": boolean;
readonly "passwordVisible": boolean;
"focus": () => void;
"blur": () => void;
"select": () => void;
"clear": (event?: MouseEvent) => void;
"resizeTextarea": () => void;
};