使用场景 ​
使已挂载容器中的可聚焦子元素循环接收 Tab 和 Shift+Tab。
挂载焦点循环并释放 ​
启用后焦点进入第一个按钮,Tab 在两个按钮间循环;关闭容器恢复入口按钮。
挂载焦点循环并释放
<template>
<AsamButton type="default" ref="opener" native-type="button" @click="enable"
>启用焦点循环</AsamButton
>
<div
v-if="open"
v-asam-trap-focus
v-bind="{ 'data-focus-generation': generation, class: 'panel' }"
>
<AsamButton type="default" ref="first" native-type="button">第一个按钮</AsamButton>
<AsamButton type="default" native-type="button" @click="disable">结束焦点循环</AsamButton>
</div>
</template>
<script lang="ts" setup>
defineOptions({ name: 'AsamTrapFocusBasicDemo' });
import { ref, nextTick } from 'vue';
import { AsamButton, type AsamButtonExpose, AsamTrapFocus as vAsamTrapFocus } from '@asam-ui/ui';
const open = ref(false);
const generation = ref(0);
const first = ref<AsamButtonExpose>();
const opener = ref<AsamButtonExpose>();
const enable = async () => {
open.value = true;
await nextTick();
generation.value++;
await nextTick();
first.value?.ref?.focus();
};
const disable = async () => {
open.value = false;
await nextTick();
opener.value?.ref?.focus();
};
</script>
<style scoped>
.actions {
display: flex;
flex-wrap: wrap;
gap: var(--asam-space-md);
align-items: center;
}
.panel {
padding: var(--asam-space-lg);
border: 1px solid var(--asam-color-border);
border-radius: var(--asam-radius-control);
}
</style>
<template>
<AsamButton type="default" ref="opener" native-type="button" @click="enable"
>启用焦点循环</AsamButton
>
<div
v-if="open"
v-asam-trap-focus
v-bind="{ 'data-focus-generation': generation, class: 'panel' }"
>
<AsamButton type="default" ref="first" native-type="button">第一个按钮</AsamButton>
<AsamButton type="default" native-type="button" @click="disable">结束焦点循环</AsamButton>
</div>
</template>
<script setup>
defineOptions({ name: 'AsamTrapFocusBasicDemo' });
import { ref, nextTick } from 'vue';
import { AsamButton, AsamTrapFocus as vAsamTrapFocus } from '@asam-ui/ui';
const open = ref(false);
const generation = ref(0);
const first = ref();
const opener = ref();
const enable = async () => {
open.value = true;
await nextTick();
generation.value++;
await nextTick();
first.value?.ref?.focus();
};
const disable = async () => {
open.value = false;
await nextTick();
opener.value?.ref?.focus();
};
</script>
<style scoped>
.actions {
display: flex;
flex-wrap: wrap;
gap: var(--asam-space-md);
align-items: center;
}
.panel {
padding: var(--asam-space-lg);
border: 1px solid var(--asam-color-border);
border-radius: var(--asam-radius-control);
}
</style>
使用约定 ​
指令绑定值不决定启用/禁用,卸载容器才释放监听。先挂载容器,再由宿主选择初始焦点;关闭后宿主恢复焦点。它不创建遮罩、对话框语义或自动关闭行为。 动态挂载的可见按钮须在容器更新后重新收集:本例先等待挂载,再更新容器的响应式标记,随后 nextTick 聚焦。首次未更新的动态容器不能假定已完成焦点收集。
组合职责与生命周期 ​
指令在宿主内部的可聚焦节点之间循环 Tab 与 Shift+Tab,更新宿主内容时重取可聚焦节点,卸载后释放登记。指令不负责弹层显隐、Escape 关闭、返回焦点或锁屏,这些由 Dialog/Drawer 或业务宿主组织。
API
指令 AsamTrapFocus
| 属性名 | 说明 | 类型 | 默认值 |
|---|---|---|---|
created | — | DirectiveHook<HTMLElement, null, unknown, string, unknown> | undefined | — |
beforeMount | — | DirectiveHook<HTMLElement, null, unknown, string, unknown> | undefined | — |
mounted | — | DirectiveHook<HTMLElement, null, unknown, string, unknown> | undefined | — |
beforeUpdate | — | DirectiveHook<HTMLElement, VNode<any, HTMLElement, { [key: string]: any; }>, unknown, string, unknown> | undefined | — |
updated | — | DirectiveHook<HTMLElement, VNode<any, HTMLElement, { [key: string]: any; }>, unknown, string, unknown> | undefined | — |
beforeUnmount | — | DirectiveHook<HTMLElement, null, unknown, string, unknown> | undefined | — |
unmounted | — | DirectiveHook<HTMLElement, null, unknown, string, unknown> | undefined | — |
getSSRProps | — | (typeof AsamTrapFocus)["getSSRProps"] | — |
deep | — | boolean | undefined | — |
install | — | (app: App) => void | — |
类型 AsamTrapFocusBinding
类型 AsamTrapFocusDirective
| 属性名 | 说明 | 类型 | 默认值 |
|---|---|---|---|
created | — | DirectiveHook<HTMLElement, null, unknown, string, unknown> | undefined | — |
beforeMount | — | DirectiveHook<HTMLElement, null, unknown, string, unknown> | undefined | — |
mounted | — | DirectiveHook<HTMLElement, null, unknown, string, unknown> | undefined | — |
beforeUpdate | — | DirectiveHook<HTMLElement, VNode<any, HTMLElement, { [key: string]: any; }>, unknown, string, unknown> | undefined | — |
updated | — | DirectiveHook<HTMLElement, VNode<any, HTMLElement, { [key: string]: any; }>, unknown, string, unknown> | undefined | — |
beforeUnmount | — | DirectiveHook<HTMLElement, null, unknown, string, unknown> | undefined | — |
unmounted | — | DirectiveHook<HTMLElement, null, unknown, string, unknown> | undefined | — |
getSSRProps | — | (AsamTrapFocusDirective)["getSSRProps"] | — |
deep | — | boolean | undefined | — |
install | — | (app: App) => void | — |
关联组件
参数与事件补充说明
参数与事件说明
created
必填:否;声明来源:依赖声明。
created 参数与事件数据
下列为声明可读视图;可导入类型以公开类型视图为准。分支条件与父属性一致。
事件参数:(el: HTMLElement, binding: DirectiveBinding<unknown, string, unknown>, vnode: VNode<any, HTMLElement, { [key: string]: any; }>, prevVNode: null): void
beforeMount
必填:否;声明来源:依赖声明。
beforeMount 参数与事件数据
下列为声明可读视图;可导入类型以公开类型视图为准。分支条件与父属性一致。
事件参数:(el: HTMLElement, binding: DirectiveBinding<unknown, string, unknown>, vnode: VNode<any, HTMLElement, { [key: string]: any; }>, prevVNode: null): void
mounted
必填:否;声明来源:依赖声明。
mounted 参数与事件数据
下列为声明可读视图;可导入类型以公开类型视图为准。分支条件与父属性一致。
事件参数:(el: HTMLElement, binding: DirectiveBinding<unknown, string, unknown>, vnode: VNode<any, HTMLElement, { [key: string]: any; }>, prevVNode: null): void
beforeUpdate
必填:否;声明来源:依赖声明。
beforeUpdate 参数与事件数据
下列为声明可读视图;可导入类型以公开类型视图为准。分支条件与父属性一致。
事件参数:(el: HTMLElement, binding: DirectiveBinding<unknown, string, unknown>, vnode: VNode<any, HTMLElement, { [key: string]: any; }>, prevVNode: VNode<any, HTMLElement, { [key: string]: any; }>): void
updated
必填:否;声明来源:依赖声明。
updated 参数与事件数据
下列为声明可读视图;可导入类型以公开类型视图为准。分支条件与父属性一致。
事件参数:(el: HTMLElement, binding: DirectiveBinding<unknown, string, unknown>, vnode: VNode<any, HTMLElement, { [key: string]: any; }>, prevVNode: VNode<any, HTMLElement, { [key: string]: any; }>): void
beforeUnmount
必填:否;声明来源:依赖声明。
beforeUnmount 参数与事件数据
下列为声明可读视图;可导入类型以公开类型视图为准。分支条件与父属性一致。
事件参数:(el: HTMLElement, binding: DirectiveBinding<unknown, string, unknown>, vnode: VNode<any, HTMLElement, { [key: string]: any; }>, prevVNode: null): void
unmounted
必填:否;声明来源:依赖声明。
unmounted 参数与事件数据
下列为声明可读视图;可导入类型以公开类型视图为准。分支条件与父属性一致。
事件参数:(el: HTMLElement, binding: DirectiveBinding<unknown, string, unknown>, vnode: VNode<any, HTMLElement, { [key: string]: any; }>, prevVNode: null): void
getSSRProps
必填:否;声明来源:依赖声明。
getSSRProps 参数与事件数据
下列为声明可读视图;可导入类型以公开类型视图为准。分支条件与父属性一致。
事件参数:(binding: DirectiveBinding<unknown, string, unknown>, vnode: VNode<RendererNode, RendererElement, { [key: string]: any; }>): ReturnType<Extract<NonNullable<(typeof AsamTrapFocus)["getSSRProps"]>, (...args: never[]) => unknown>>
deep
必填:否;声明来源:依赖声明。
deep 参数与事件数据
下列为声明可读视图;可导入类型以公开类型视图为准。分支条件与父属性一致。
枚举:false / true
install
必填:是;声明来源:ASAM 声明。
install 参数与事件数据
下列为声明可读视图;可导入类型以公开类型视图为准。分支条件与父属性一致。
事件参数:(app: App<any>): void
AsamTrapFocus 公开类型视图
import type { DirectiveHook, DirectiveBinding, VNode, RendererNode, RendererElement, App } from 'vue';
import type { AsamTrapFocusDirective } from '@asam-ui/ui';
import { AsamTrapFocus } from '@asam-ui/ui';
// AsamTrapFocus
type PublicContract = {
"created"?: DirectiveHook<HTMLElement, null, unknown, string, unknown> | undefined;
"beforeMount"?: DirectiveHook<HTMLElement, null, unknown, string, unknown> | undefined;
"mounted"?: DirectiveHook<HTMLElement, null, unknown, string, unknown> | undefined;
"beforeUpdate"?: DirectiveHook<HTMLElement, VNode<any, HTMLElement, { [key: string]: any; }>, unknown, string, unknown> | undefined;
"updated"?: DirectiveHook<HTMLElement, VNode<any, HTMLElement, { [key: string]: any; }>, unknown, string, unknown> | undefined;
"beforeUnmount"?: DirectiveHook<HTMLElement, null, unknown, string, unknown> | undefined;
"unmounted"?: DirectiveHook<HTMLElement, null, unknown, string, unknown> | undefined;
"getSSRProps"?: (typeof AsamTrapFocus)["getSSRProps"];
"deep"?: boolean | undefined;
"install": (app: App) => void;
};
挂载后,使用 Tab 或 Shift+Tab 在可聚焦子元素间循环移动焦点。
AsamTrapFocusBinding 公开类型视图
import type { AsamTrapFocusBinding } from '@asam-ui/ui';
// AsamTrapFocusBinding
type PublicContract = AsamTrapFocusBinding;
参数与事件说明
created
必填:否;声明来源:依赖声明。
created 参数与事件数据
下列为声明可读视图;可导入类型以公开类型视图为准。分支条件与父属性一致。
事件参数:(el: HTMLElement, binding: DirectiveBinding<unknown, string, unknown>, vnode: VNode<any, HTMLElement, { [key: string]: any; }>, prevVNode: null): void
beforeMount
必填:否;声明来源:依赖声明。
beforeMount 参数与事件数据
下列为声明可读视图;可导入类型以公开类型视图为准。分支条件与父属性一致。
事件参数:(el: HTMLElement, binding: DirectiveBinding<unknown, string, unknown>, vnode: VNode<any, HTMLElement, { [key: string]: any; }>, prevVNode: null): void
mounted
必填:否;声明来源:依赖声明。
mounted 参数与事件数据
下列为声明可读视图;可导入类型以公开类型视图为准。分支条件与父属性一致。
事件参数:(el: HTMLElement, binding: DirectiveBinding<unknown, string, unknown>, vnode: VNode<any, HTMLElement, { [key: string]: any; }>, prevVNode: null): void
beforeUpdate
必填:否;声明来源:依赖声明。
beforeUpdate 参数与事件数据
下列为声明可读视图;可导入类型以公开类型视图为准。分支条件与父属性一致。
事件参数:(el: HTMLElement, binding: DirectiveBinding<unknown, string, unknown>, vnode: VNode<any, HTMLElement, { [key: string]: any; }>, prevVNode: VNode<any, HTMLElement, { [key: string]: any; }>): void
updated
必填:否;声明来源:依赖声明。
updated 参数与事件数据
下列为声明可读视图;可导入类型以公开类型视图为准。分支条件与父属性一致。
事件参数:(el: HTMLElement, binding: DirectiveBinding<unknown, string, unknown>, vnode: VNode<any, HTMLElement, { [key: string]: any; }>, prevVNode: VNode<any, HTMLElement, { [key: string]: any; }>): void
beforeUnmount
必填:否;声明来源:依赖声明。
beforeUnmount 参数与事件数据
下列为声明可读视图;可导入类型以公开类型视图为准。分支条件与父属性一致。
事件参数:(el: HTMLElement, binding: DirectiveBinding<unknown, string, unknown>, vnode: VNode<any, HTMLElement, { [key: string]: any; }>, prevVNode: null): void
unmounted
必填:否;声明来源:依赖声明。
unmounted 参数与事件数据
下列为声明可读视图;可导入类型以公开类型视图为准。分支条件与父属性一致。
事件参数:(el: HTMLElement, binding: DirectiveBinding<unknown, string, unknown>, vnode: VNode<any, HTMLElement, { [key: string]: any; }>, prevVNode: null): void
getSSRProps
必填:否;声明来源:依赖声明。
getSSRProps 参数与事件数据
下列为声明可读视图;可导入类型以公开类型视图为准。分支条件与父属性一致。
事件参数:(binding: DirectiveBinding<unknown, string, unknown>, vnode: VNode<RendererNode, RendererElement, { [key: string]: any; }>): ReturnType<Extract<NonNullable<(AsamTrapFocusDirective)["getSSRProps"]>, (...args: never[]) => unknown>>
deep
必填:否;声明来源:依赖声明。
deep 参数与事件数据
下列为声明可读视图;可导入类型以公开类型视图为准。分支条件与父属性一致。
枚举:false / true
install
必填:是;声明来源:ASAM 声明。
install 参数与事件数据
下列为声明可读视图;可导入类型以公开类型视图为准。分支条件与父属性一致。
事件参数:(app: App<any>): void
AsamTrapFocusDirective 公开类型视图
import type { DirectiveHook, DirectiveBinding, VNode, RendererNode, RendererElement, App } from 'vue';
import type { AsamTrapFocusDirective } from '@asam-ui/ui';
// AsamTrapFocusDirective
type PublicContract = {
"created"?: DirectiveHook<HTMLElement, null, unknown, string, unknown> | undefined;
"beforeMount"?: DirectiveHook<HTMLElement, null, unknown, string, unknown> | undefined;
"mounted"?: DirectiveHook<HTMLElement, null, unknown, string, unknown> | undefined;
"beforeUpdate"?: DirectiveHook<HTMLElement, VNode<any, HTMLElement, { [key: string]: any; }>, unknown, string, unknown> | undefined;
"updated"?: DirectiveHook<HTMLElement, VNode<any, HTMLElement, { [key: string]: any; }>, unknown, string, unknown> | undefined;
"beforeUnmount"?: DirectiveHook<HTMLElement, null, unknown, string, unknown> | undefined;
"unmounted"?: DirectiveHook<HTMLElement, null, unknown, string, unknown> | undefined;
"getSSRProps"?: (AsamTrapFocusDirective)["getSSRProps"];
"deep"?: boolean | undefined;
"install": (app: App) => void;
};