组件关系 ​
使用场景 ​
为 Select 的默认插槽建立带标题的选项组。disabled 禁用组内所有选项,default 插槽放 Option。
分组与显示内容 ​
Select 使用 valueMode=native 消费原始 Option。默认插槽内容负责菜单展示,label 保持简洁的选中回显。
分组与显示内容
<template>
<div class="example">
<AsamSelect
v-model="value"
v-bind="{
'value-mode': 'native',
clearable: true,
filterable: true,
'aria-label': '团队'
}"
>
<AsamOptionGroup label="可用团队">
<AsamOption label="设计" value="design">
<span> 设计团队 · 视觉 </span>
</AsamOption>
<AsamOption label="开发" value="dev">
<span> 开发团队 · 工程 </span>
</AsamOption>
</AsamOptionGroup>
<AsamOptionGroup label="停用团队" disabled>
<AsamOption label="停用" value="off" />
</AsamOptionGroup>
</AsamSelect>
<output>原始值:{{ value }}</output>
</div>
</template>
<script lang="ts" setup>
defineOptions({ name: 'AsamOptionGroupBasicExample' });
import { ref } from 'vue';
import { AsamSelect, AsamOption, AsamOptionGroup } from '@asam-ui/ui';
const value = ref<string | null>('design');
</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);
}
.density-grid {
display: grid;
gap: var(--asam-space-md, 16px);
grid-template-columns: repeat(auto-fit, minmax(min(100%, 260px), 1fr));
}
section {
display: grid;
gap: var(--asam-space-sm, 8px);
min-width: 0;
}
output {
overflow-wrap: anywhere;
color: var(--asam-color-text-secondary);
}
</style>
<template>
<div class="example">
<AsamSelect
v-model="value"
v-bind="{
'value-mode': 'native',
clearable: true,
filterable: true,
'aria-label': '团队'
}"
>
<AsamOptionGroup label="可用团队">
<AsamOption label="设计" value="design">
<span> 设计团队 · 视觉 </span>
</AsamOption>
<AsamOption label="开发" value="dev">
<span> 开发团队 · 工程 </span>
</AsamOption>
</AsamOptionGroup>
<AsamOptionGroup label="停用团队" disabled>
<AsamOption label="停用" value="off" />
</AsamOptionGroup>
</AsamSelect>
<output>原始值:{{ value }}</output>
</div>
</template>
<script setup>
defineOptions({ name: 'AsamOptionGroupBasicExample' });
import { ref } from 'vue';
import { AsamSelect, AsamOption, AsamOptionGroup } from '@asam-ui/ui';
const value = ref('design');
</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);
}
.density-grid {
display: grid;
gap: var(--asam-space-md, 16px);
grid-template-columns: repeat(auto-fit, minmax(min(100%, 260px), 1fr));
}
section {
display: grid;
gap: var(--asam-space-sm, 8px);
min-width: 0;
}
output {
overflow-wrap: anywhere;
color: var(--asam-color-text-secondary);
}
</style>
原始对象与唯一键 ​
原始对象值通过 Select.valueKey 定位;这与 ASAM valueMode=object 的规范化 option 模型不同。多文件 data 保持实际业务对象完整。
原始对象与唯一键
<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 data_js_1: any = require("./data.js");
exports.default = (0, vue_1.defineComponent)({
...{ name: 'AsamOptionGroupObjectsExample' },
__name: 'Demo',
setup(__props?: any) {
const value: any = (0, vue_3.ref)(data_js_1.teams[0]);
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.AsamSelect), {
modelValue: value.value,
"onUpdate:modelValue": _cache[0] || (_cache[0] = ($event?: any) => ((value).value = $event)),
"value-mode": "native",
"value-key": "id"
}, {
default: (0, vue_2.withCtx)(() => [
(0, vue_2.createVNode)((0, vue_2.unref)(ui_1.AsamOptionGroup), { label: "对象选项" }, {
default: (0, vue_2.withCtx)(() => [
((0, vue_2.openBlock)(true), (0, vue_2.createElementBlock)(vue_2.Fragment, null, (0, vue_2.renderList)((0, vue_2.unref)(data_js_1.teams), (item?: any) => {
return ((0, vue_2.openBlock)(), (0, vue_2.createBlock)((0, vue_2.unref)(ui_1.AsamOption), (0, vue_2.mergeProps)({
key: item.id
}, { ref_for: true }, { label: item.name, value: item }), null, 16 /* FULL_PROPS */));
}), 128 /* KEYED_FRAGMENT */))
]),
_: 1 /* STABLE */
})
]),
_: 1 /* STABLE */
}, 8 /* PROPS */, ["modelValue"]),
(0, vue_2.createElementVNode)("output", null, "对象:" + (0, vue_2.toDisplayString)(value.value), 1 /* TEXT */)
]));
};
}
});
exports.default.__scopeId = "data-v-52192c8c";
},
"data.ts": (module: any, exports: any, require: any) => {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.teams = void 0;
exports.teams = [
{ id: 'design', name: '设计' },
{ id: 'dev', name: '开发' }
];
},
};
const __dependencies: any = {"Demo.vue":{"./data.js":"data.ts"},"data.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-52192c8c] {
display: grid;
gap: var(--asam-space-md, 16px);
min-width: 0;
}
.row[data-v-52192c8c] {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: var(--asam-space-sm, 8px);
}
.density-grid[data-v-52192c8c] {
display: grid;
gap: var(--asam-space-md, 16px);
grid-template-columns: repeat(auto-fit, minmax(min(100%, 260px), 1fr));
}
section[data-v-52192c8c] {
display: grid;
gap: var(--asam-space-sm, 8px);
min-width: 0;
}
output[data-v-52192c8c] {
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 data_js_1 = require("./data.js");
exports.default = Object.assign({ name: 'AsamOptionGroupObjectsExample' }, {
__name: 'Demo',
setup(__props) {
const value = (0, vue_2.ref)(data_js_1.teams[0]);
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.AsamSelect), {
modelValue: value.value,
"onUpdate:modelValue": _cache[0] || (_cache[0] = $event => ((value).value = $event)),
"value-mode": "native",
"value-key": "id"
}, {
default: (0, vue_1.withCtx)(() => [
(0, vue_1.createVNode)((0, vue_1.unref)(ui_1.AsamOptionGroup), { label: "对象选项" }, {
default: (0, vue_1.withCtx)(() => [
((0, vue_1.openBlock)(true), (0, vue_1.createElementBlock)(vue_1.Fragment, null, (0, vue_1.renderList)((0, vue_1.unref)(data_js_1.teams), (item) => {
return ((0, vue_1.openBlock)(), (0, vue_1.createBlock)((0, vue_1.unref)(ui_1.AsamOption), (0, vue_1.mergeProps)({
key: item.id
}, { ref_for: true }, { label: item.name, value: item }), null, 16 /* FULL_PROPS */));
}), 128 /* KEYED_FRAGMENT */))
]),
_: 1 /* STABLE */
})
]),
_: 1 /* STABLE */
}, 8 /* PROPS */, ["modelValue"]),
(0, vue_1.createElementVNode)("output", null, "对象:" + (0, vue_1.toDisplayString)(value.value), 1 /* TEXT */)
]));
};
}
});
exports.default.__scopeId = "data-v-6b5dedb6";
},
"data.js": (module, exports, require) => {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.teams = void 0;
exports.teams = [
{ id: 'design', name: '设计' },
{ id: 'dev', name: '开发' }
];
},
};
const __dependencies = {"Demo.vue":{"./data.js":"data.js"},"data.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-6b5dedb6] {
display: grid;
gap: var(--asam-space-md, 16px);
min-width: 0;
}
.row[data-v-6b5dedb6] {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: var(--asam-space-sm, 8px);
}
.density-grid[data-v-6b5dedb6] {
display: grid;
gap: var(--asam-space-md, 16px);
grid-template-columns: repeat(auto-fit, minmax(min(100%, 260px), 1fr));
}
section[data-v-6b5dedb6] {
display: grid;
gap: var(--asam-space-sm, 8px);
min-width: 0;
}
output[data-v-6b5dedb6] {
overflow-wrap: anywhere;
color: var(--asam-color-text-secondary);
}
</style>
四档尺寸与上下文继承 ​
四个实例分别显式使用 large、big、default、small。下面省略 size 的实例随 ConfigProvider 响应切换;显式 size 覆盖祖先。面板本身没有 size 契约的入口不附加虚构尺寸属性。
四档尺寸与上下文继承
<template>
<div class="example">
<div class="density-grid">
<section data-density="large">
<strong> large </strong>
<AsamSelect size="large" model-value="design" value-mode="native">
<AsamOptionGroup label="团队">
<AsamOption label="设计" value="design" />
<AsamOption label="开发" value="dev" />
</AsamOptionGroup>
</AsamSelect>
</section>
<section data-density="big">
<strong> big </strong>
<AsamSelect size="big" model-value="design" value-mode="native">
<AsamOptionGroup label="团队">
<AsamOption label="设计" value="design" />
<AsamOption label="开发" value="dev" />
</AsamOptionGroup>
</AsamSelect>
</section>
<section data-density="default">
<strong> default </strong>
<AsamSelect size="default" model-value="design" value-mode="native">
<AsamOptionGroup label="团队">
<AsamOption label="设计" value="design" />
<AsamOption label="开发" value="dev" />
</AsamOptionGroup>
</AsamSelect>
</section>
<section data-density="small">
<strong> small </strong>
<AsamSelect size="small" model-value="design" value-mode="native">
<AsamOptionGroup label="团队">
<AsamOption label="设计" value="design" />
<AsamOption label="开发" value="dev" />
</AsamOptionGroup>
</AsamSelect>
</section>
</div>
<AsamConfigProvider :size="density">
<section data-density="inherited">
<AsamSelect model-value="design" value-mode="native">
<AsamOptionGroup label="团队">
<AsamOption label="设计" value="design" />
<AsamOption label="开发" value="dev" />
</AsamOptionGroup>
</AsamSelect>
</section>
</AsamConfigProvider>
<div class="row">
<AsamButton type="default" @click="density = 'small'"> 继承 small </AsamButton>
<AsamButton type="default" @click="density = 'big'"> 继承 big </AsamButton>
</div>
<output>配置提供器:{{ density }}</output>
</div>
</template>
<script lang="ts" setup>
defineOptions({ name: 'AsamOptionGroupSizesExample' });
import { ref } from 'vue';
import {
AsamSelect,
AsamOption,
AsamOptionGroup,
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);
}
.density-grid {
display: grid;
gap: var(--asam-space-md, 16px);
grid-template-columns: repeat(auto-fit, minmax(min(100%, 260px), 1fr));
}
section {
display: grid;
gap: var(--asam-space-sm, 8px);
min-width: 0;
}
output {
overflow-wrap: anywhere;
color: var(--asam-color-text-secondary);
}
</style>
<template>
<div class="example">
<div class="density-grid">
<section data-density="large">
<strong> large </strong>
<AsamSelect size="large" model-value="design" value-mode="native">
<AsamOptionGroup label="团队">
<AsamOption label="设计" value="design" />
<AsamOption label="开发" value="dev" />
</AsamOptionGroup>
</AsamSelect>
</section>
<section data-density="big">
<strong> big </strong>
<AsamSelect size="big" model-value="design" value-mode="native">
<AsamOptionGroup label="团队">
<AsamOption label="设计" value="design" />
<AsamOption label="开发" value="dev" />
</AsamOptionGroup>
</AsamSelect>
</section>
<section data-density="default">
<strong> default </strong>
<AsamSelect size="default" model-value="design" value-mode="native">
<AsamOptionGroup label="团队">
<AsamOption label="设计" value="design" />
<AsamOption label="开发" value="dev" />
</AsamOptionGroup>
</AsamSelect>
</section>
<section data-density="small">
<strong> small </strong>
<AsamSelect size="small" model-value="design" value-mode="native">
<AsamOptionGroup label="团队">
<AsamOption label="设计" value="design" />
<AsamOption label="开发" value="dev" />
</AsamOptionGroup>
</AsamSelect>
</section>
</div>
<AsamConfigProvider :size="density">
<section data-density="inherited">
<AsamSelect model-value="design" value-mode="native">
<AsamOptionGroup label="团队">
<AsamOption label="设计" value="design" />
<AsamOption label="开发" value="dev" />
</AsamOptionGroup>
</AsamSelect>
</section>
</AsamConfigProvider>
<div class="row">
<AsamButton type="default" @click="density = 'small'"> 继承 small </AsamButton>
<AsamButton type="default" @click="density = 'big'"> 继承 big </AsamButton>
</div>
<output>配置提供器:{{ density }}</output>
</div>
</template>
<script setup>
defineOptions({ name: 'AsamOptionGroupSizesExample' });
import { ref } from 'vue';
import {
AsamSelect,
AsamOption,
AsamOptionGroup,
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);
}
.density-grid {
display: grid;
gap: var(--asam-space-md, 16px);
grid-template-columns: repeat(auto-fit, minmax(min(100%, 260px), 1fr));
}
section {
display: grid;
gap: var(--asam-space-sm, 8px);
min-width: 0;
}
output {
overflow-wrap: anywhere;
color: var(--asam-color-text-secondary);
}
</style>
ASAM 扩展与迁移 ​
Option/OptionGroup 没有独立 size 属性,菜单密度由外层 Select 的四档 size 与弹层上下文决定。当前仅有 default 插槽,没有独立事件或实例方法;选择变化监听 Select.change。
API 阅读方式 ​
下方 Props、Events、Slots、Exposes 按当前实际公开类型与运行默认值生成。组合属性按分支生效,不能任意混搭值模式。标为“未知 / 未声明”的默认值不代表 false 或空值。源码区域提供对应语言的独立 Demo.vue,可直接复制或下载;本地辅助组件、数据和素材已内联到当前文件。
API
属性 AsamOptionGroupProps
| 属性名 | 说明 | 类型 | 默认值 |
|---|---|---|---|
label | 选项的标签,若不设置则默认与value相同 | string | undefined | — |
disabled | 是否禁用该选项 | boolean | undefined | false |
插槽 AsamOptionGroupSlots
| 属性名 | 说明 | 类型 | 默认值 |
|---|---|---|---|
default | — | (() => unknown) | undefined | — |
实例方法与状态 AsamOptionGroupExpose
关联组件
参数与事件补充说明
参数与事件说明
label
必填:否;声明来源:ASAM 声明。
disabled
必填:否;声明来源:ASAM 声明。
disabled 参数与事件数据
下列为声明可读视图;可导入类型以公开类型视图为准。分支条件与父属性一致。
枚举:false / true
默认值与来源
false(隐式 Boolean 默认;已安装组件)AsamOptionGroupProps 公开类型视图
import type { AsamOptionGroupProps } from '@asam-ui/ui';
// AsamOptionGroupProps
type PublicContract = {
"label"?: string | undefined;
"disabled"?: boolean | undefined;
};
参数与事件说明
default
必填:否;声明来源:ASAM 声明。
default 参数与事件数据
下列为声明可读视图;可导入类型以公开类型视图为准。分支条件与父属性一致。
事件参数:(): unknown
AsamOptionGroupSlots 公开类型视图
import type { AsamOptionGroupSlots } from '@asam-ui/ui';
// AsamOptionGroupSlots
type PublicContract = {
"default"?: (() => unknown) | undefined;
};
AsamOptionGroupExpose 公开类型视图
import type { AsamOptionGroupExpose } from '@asam-ui/ui';
// AsamOptionGroupExpose
type PublicContract = {
[key: string]: never;
};