? ? ? ?cdk ally里面提供的功能運(yùn)用場(chǎng)景是 select, menu 這種有 list options 的組件, 負(fù)責(zé)處理鍵盤(pán)上下按鈕時(shí) option active 的邏輯。cdk Accessibility 部分官方文檔連接https://material.angular.io/cdk/a11y/overview稽荧。
? ? ? ?和cdk里面其他功能模塊一樣橘茉,cdk ally使用之前也要provider導(dǎo)入A11yModule模塊。
import {A11yModule} from '@angular/cdk/a11y';
一 ListKeyManager
? ? ? ?ListKeyManager主要做的事情就是去管理一堆的list 里面哪個(gè)item處于active狀態(tài)(active代表一種狀態(tài)姨丈,比如處于活動(dòng)轉(zhuǎn)換畅卓,獲取焦點(diǎn)狀態(tài)等等)。而且ListKeyManager管理的item必須實(shí)現(xiàn)ListKeyManagerOption接口蟋恬。換句話說(shuō)ListKeyManager用于管理一系列l(wèi)ist的item,這些item就是ListKeyManagerOption翁潘。通過(guò)ListKeyManager來(lái)控制那個(gè)ListKeyManagerOption對(duì)應(yīng)的item處于active狀態(tài)。所以咱們先看下ListKeyManagerOption和ListKeyManager里面一些常見(jiàn)的方法歼争,如下:
1.1 ListKeyManager常用方法
? ? ? ?講ListKeyManager方法的時(shí)候咱們順帶講下ListKeyManagerOption里面的方法
1.1.1 ListKeyManagerOption常用方法介紹
export interface ListKeyManagerOption {
/** 當(dāng)前item是否disabled. */
disabled?: boolean;
/** 獲取當(dāng)前item對(duì)應(yīng)的label,配合ListKeyManager里面withTypeAhead函數(shù)的使用
* 適用于輸入框的情況拜马,比如輸入框下面有一些list item。當(dāng)輸入框輸入字符的時(shí)候list item 里面的active
* item 和輸入的文字匹配
*/
getLabel?(): string;
}
1.1.2 ListKeyManager常用方法介紹
export declare class ListKeyManager<T extends ListKeyManagerOption> {
/**
* tab 按鍵的時(shí)候觸發(fā)的
*/
tabOut: Subject<void>;
/** 當(dāng)ListKeyManager里面的list item ,active item 改變的時(shí)候觸發(fā)*/
change: Subject<number>;
/**
* 設(shè)置那些ListKeyManager管理的list里在移動(dòng)(比如tab 按鍵切換)過(guò)程中那些item需要跳過(guò)沐绒。
*/
skipPredicate(predicate: (item: T) => boolean): this;
/**
* 設(shè)置是否循環(huán)移動(dòng)(當(dāng)active item是最好一個(gè)的時(shí)候俩莽,繼續(xù)下一個(gè)跳到第一個(gè))
*/
withWrap(shouldWrap?: boolean): this;
/**
* active item 移動(dòng)方向垂直(對(duì)應(yīng)鍵盤(pán)方向鍵的 上下按鍵)
*/
withVerticalOrientation(enabled?: boolean): this;
/**
* active item 移動(dòng)方向水平(對(duì)應(yīng)鍵盤(pán)方向鍵的 左右按鍵)
*/
withHorizontalOrientation(direction: 'ltr' | 'rtl' | null): this;
/**
* 用來(lái)處理組合按鍵的情況,比如 altr + 方向鍵的時(shí)候乔遮。同樣達(dá)到方向按鍵的效果
*/
withAllowedModifierKeys(keys: ListKeyManagerModifierKey[]): this;
/**
* 設(shè)置typeahead 模式 配合ListKeyManagerOption的getLabel()函數(shù)使用扮超,一般用于配合有輸入框的情況下使用,比如輸入框輸入一個(gè)字符蹋肮,active item 會(huì)自動(dòng)設(shè)置到包含這個(gè)字符item
*/
withTypeAhead(debounceInterval?: number): this;
/**
* 設(shè)置 active item 對(duì)應(yīng)的index
*/
setActiveItem(index: number): void;
/**
* 設(shè)置 active item 對(duì)應(yīng)的item
*/
setActiveItem(item: T): void;
/**
* 設(shè)置按鍵
*/
onKeydown(event: KeyboardEvent): void;
/** 當(dāng)前active item 對(duì)應(yīng)的事件 */
readonly activeItemIndex: number | null;
/** 當(dāng)前active item 對(duì)應(yīng)的item */
readonly activeItem: T | null;
/** 設(shè)置第一個(gè)位置的item 為active item(當(dāng)然了如果第一個(gè)item 是disable,則設(shè)置第二個(gè)) */
setFirstItemActive(): void;
/** 設(shè)置最后一個(gè)位置的item 為 active item */
setLastItemActive(): void;
/** 設(shè)置下一個(gè)item 為active item */
setNextItemActive(): void;
/** 設(shè)置上一個(gè)item 為active item */
setPreviousItemActive(): void;
/**
* 設(shè)置active item,但是不產(chǎn)生其他的效果
*/
updateActiveItem(index: number): void;
/**
* 設(shè)置active item,但是不產(chǎn)生其他的效果
*/
updateActiveItem(item: T): void;
}
1.2 ListKeyManager的使用
? ? ? ?接下來(lái)咱們通過(guò)ListKeyManager的兩個(gè)具體繼承類(lèi)ActiveDescendantKeyManager和FocusKeyManager來(lái)說(shuō)明ListKeyManager的具體使用出刷。其實(shí)ActiveDescendantKeyManager里面管理的item必須實(shí)現(xiàn)Highlightable接口、FocusKeyManager里面管理的item必須實(shí)現(xiàn)FocusableOption坯辩。
1.2.1 ActiveDescendantKeyManager的使用
? ? ? ?ActiveDescendantKeyManager里面管理的list item 必須實(shí)現(xiàn)Highlightable接口馁龟。
ActiveDescendantKeyManager繼承了ListKeyManager類(lèi),Highlightable實(shí)現(xiàn)了ListKeyManagerOption接口
? ? ? ?ActiveDescendantKeyManager使用場(chǎng)景:如果想ListKeyManager管理的list里面active的item標(biāo)記為活動(dòng)狀態(tài)濒翻,其他的標(biāo)記為非活動(dòng)狀態(tài)情況下使用屁柏。而且每個(gè)item都必須實(shí)現(xiàn)Highlightable接口啦膜。接下來(lái)咱們通過(guò)一個(gè)具體的實(shí)例來(lái)簡(jiǎn)單的說(shuō)明下。
咱們自定義一個(gè)item組件ItemActiveOptionComponent淌喻,這個(gè)組件實(shí)現(xiàn)Highlightable接口僧家。組件里面做的事情也很簡(jiǎn)單就是去改變active item的class樣式。
import {Component, HostBinding, Input} from '@angular/core';
import {Highlightable} from "@angular/cdk/a11y";
@Component({
selector: 'app-item-active-option',
template: `
<div [class.disabled]="disabled">
<ng-content></ng-content>
</div>
`,
styles: [`
.active {
background-color: lightblue;
color: #fff;
}
.disabled {
opacity: 0.3;
}
`]
})
export class ItemActiveOptionComponent implements Highlightable {
@Input() item;
@Input() disabled = false;
private _isActive = false;
@HostBinding('class.active') get isActive() {
return this._isActive;
}
/**
* 設(shè)置 active對(duì)應(yīng)的class
*/
setActiveStyles() {
this._isActive = true;
}
/**
* 設(shè)置非active對(duì)應(yīng)的class
*/
setInactiveStyles() {
this._isActive = false;
}
getLabel() {
return this.item.name;
}
}
cdk-active-descendant.component.less文件裸删,組件對(duì)應(yīng)樣式
.form-control {
display: block;
width: 100%;
height: calc(2.25rem + 2px);
padding: .375rem .75rem;
font-size: 1rem;
line-height: 1.5;
color: #495057;
background-color: #fff;
background-clip: padding-box;
border: 1px solid #ced4da;
border-radius: .25rem;
transition: border-color .15s ease-in-out, box-shadow .15s ease-in-out;
}
.form-control:focus {
color: #495057;
background-color: #fff;
border-color: #80bdff;
outline: 0;
box-shadow: 0 0 0 0.2rem rgba(0,123,255,.25);
}
.list-group-item:first-child {
margin-top: 1rem;
border-top-left-radius: .25rem;
border-top-right-radius: .25rem;
}
.list-group-item {
position: relative;
display: block;
padding: .75rem 1.25rem;
margin-bottom: -1px;
background-color: #fff;
border: 1px solid rgba(0, 0, 0, .125);
}
.list-group-item:last-child {
margin-bottom: 0;
border-bottom-right-radius: .25rem;
border-bottom-left-radius: .25rem;
}
.list-group-item.active {
z-index: 2;
color: #fff;
background-color: #007bff;
border-color: #007bff;
}
ActiveDescendantKeyManager的使用八拱,咱們放在這個(gè)組件里面實(shí)現(xiàn)。ActiveDescendantKeyManager里面管理的item就是咱們上面自定義的ItemActiveOptionComponent涯塔。具體的實(shí)現(xiàn)可以看下代碼肌稻。
import {AfterViewInit, Component, QueryList, ViewChildren} from '@angular/core';
import {ItemActiveOptionComponent} from "./active-item-option/item-active-option.component";
import {ActiveDescendantKeyManager} from "@angular/cdk/a11y";
@Component({
selector: 'app-cdk-active-descendant',
template: `
<!-- 輸入框 -->
<div class="form-group">
<input class="form-control" placeholder="Search..." (keyup)="onKeyDown($event)" #input>
</div>
<section class="list-group">
<!-- ActiveDescendantKeyManager要管理的item -->
<app-item-active-option *ngFor="let user of users | filter: 'name' : input.value; index as index"
[item]="user" class="list-group-item">
{{user.name}}
</app-item-active-option>
</section>
`,
styleUrls: ['cdk-active-descendant.component.less']
})
export class CdkActiveDescendantComponent implements AfterViewInit {
/**
* 找到所有的item(ListKeyManagerOption - Highlightable)
*/
@ViewChildren(ItemActiveOptionComponent) items: QueryList<ItemActiveOptionComponent>;
// list item source list
users = [
{
"id": "5b902934d965e7501f4e1c6f",
"name": "Caroline Hodges"
},
{
"id": "5b9029348f7eed8b6f5f02db",
"name": "Delores Rivas"
},
{
"id": "5b9029346f48c8407c64d0d5",
"name": "Darlene Franklin"
},
{
"id": "5b9029341eff315fa87f9e21",
"name": "Alfreda Love"
},
{
"id": "5b9029342e8917c6ccdb9865",
"name": "Marcy Ratliff"
},
{
"id": "5b9029349dbb48013460e01f",
"name": "Beulah Nielsen"
},
{
"id": "5b902934f4f1586e5e72d74a",
"name": "Morton Kerr"
},
{
"id": "5b9029347918bb204bf7014e",
"name": "Autumn Tillman"
},
{
"id": "5b902934b86f80e1fc60c626",
"name": "Diane Bennett"
},
{
"id": "5b9029348999f59215020349",
"name": "June Eaton"
}
];
private keyManager: ActiveDescendantKeyManager<ItemActiveOptionComponent>;
ngAfterViewInit() {
// new ActiveDescendantKeyManager
this.keyManager = new ActiveDescendantKeyManager(this.items)
.withWrap() // 循環(huán)
.withTypeAhead(); // 支持搜索
}
onKeyDown(event) {
// 傳遞事件進(jìn)去
this.keyManager.onKeydown(event);
}
}
1.2.2 FocusKeyManager的使用
? ? ? ?FocusKeyManager里面管理的item必須實(shí)現(xiàn)FocusableOption接口。
FocusKeyManager繼承了ListKeyManager類(lèi)匕荸,F(xiàn)ocusableOption實(shí)現(xiàn)了ListKeyManagerOption接口
? ? ? ?FocusKeyManager使用場(chǎng)景:如果想ListKeyManager管理的list里面active item想直接接受到瀏覽器的焦點(diǎn)focus的時(shí)候使用爹谭。每個(gè)item都必須實(shí)現(xiàn)FocusableOption接口。
自定義一個(gè)組件ItemFocusOptionComponent,并且這個(gè)組件實(shí)現(xiàn)了FocusableOption接口榛搔,F(xiàn)ocusableOption接口的focus()方法里面設(shè)置當(dāng)前item獲取焦點(diǎn)诺凡。
import {Component, ElementRef, HostBinding, Input} from '@angular/core';
import {FocusableOption, FocusOrigin} from "@angular/cdk/a11y";
@Component({
selector: 'app-item-focus-option',
template: `
<ng-content></ng-content>
`,
styles: [
`:host:focus {
background: lightblue;
color: #fff;
}`
]
})
export class ItemFocusOptionComponent implements FocusableOption {
@Input() item;
/**
* 屏蔽掉默認(rèn)的鍵盤(pán)事件,js里面自己控制鍵盤(pán)事件
*/
@HostBinding('tabindex') tabindex = '-1';
constructor(private host: ElementRef) {
}
getLabel() {
return this.item.name;
}
/**
* 設(shè)置獲取焦點(diǎn)
*/
focus(origin?: FocusOrigin): void {
this.host.nativeElement.focus();
}
}
cdk-focus.component.less 樣式文件
.form-control {
display: block;
width: 100%;
height: calc(2.25rem + 2px);
padding: .375rem .75rem;
font-size: 1rem;
line-height: 1.5;
color: #495057;
background-color: #fff;
background-clip: padding-box;
border: 1px solid #ced4da;
border-radius: .25rem;
transition: border-color .15s ease-in-out, box-shadow .15s ease-in-out;
}
.form-control:focus {
color: #495057;
background-color: #fff;
border-color: #80bdff;
outline: 0;
box-shadow: 0 0 0 0.2rem rgba(0,123,255,.25);
}
.list-group-item:first-child {
margin-top: 1rem;
border-top-left-radius: .25rem;
border-top-right-radius: .25rem;
}
.list-group-item {
position: relative;
display: block;
padding: .75rem 1.25rem;
margin-bottom: -1px;
background-color: #fff;
border: 1px solid rgba(0, 0, 0, .125);
}
.list-group-item:last-child {
margin-bottom: 0;
border-bottom-right-radius: .25rem;
border-bottom-left-radius: .25rem;
}
.list-group-item.focus {
z-index: 2;
color: #fff;
background-color: #007bff;
border-color: #007bff;
}
FocusKeyManager的具體使用
import {AfterViewInit, Component, QueryList, ViewChildren} from '@angular/core';
import {FocusableOption, FocusKeyManager} from "@angular/cdk/a11y";
import {ItemFocusOptionComponent} from "./focus-item-option/item-focus-option.component";
@Component({
selector: 'app-cdk-focus',
template: `
<section class="list-group" (keyup)="onKeyDown($event)">
<app-item-focus-option *ngFor="let user of users; index as index"
[item]="user" class="list-group-item"
(click)="selectItem(index)">
{{user.name}}
</app-item-focus-option>
</section>
`,
styleUrls: ['./cdk-focus.component.less']
})
export class CdkFocusComponent implements AfterViewInit {
// 獲取搜有實(shí)現(xiàn)了FocusableOption接口的item
@ViewChildren(ItemFocusOptionComponent) items: QueryList<ItemFocusOptionComponent>;
// list source
users = [
{
"id": "5b902934d965e7501f4e1c6f",
"name": "Caroline Hodges"
},
{
"id": "5b9029348f7eed8b6f5f02db",
"name": "Delores Rivas"
},
{
"id": "5b9029346f48c8407c64d0d5",
"name": "Darlene Franklin"
},
{
"id": "5b9029341eff315fa87f9e21",
"name": "Alfreda Love"
},
{
"id": "5b9029342e8917c6ccdb9865",
"name": "Marcy Ratliff"
},
{
"id": "5b9029349dbb48013460e01f",
"name": "Beulah Nielsen"
},
{
"id": "5b902934f4f1586e5e72d74a",
"name": "Morton Kerr"
},
{
"id": "5b9029347918bb204bf7014e",
"name": "Autumn Tillman"
},
{
"id": "5b902934b86f80e1fc60c626",
"name": "Diane Bennett"
},
{
"id": "5b9029348999f59215020349",
"name": "June Eaton"
}
];
private keyManager: FocusKeyManager<ItemFocusOptionComponent>;
ngAfterViewInit() {
// 創(chuàng)建FocusKeyManager對(duì)象
this.keyManager = new FocusKeyManager(this.items)
.withWrap()
.withTypeAhead();
}
/**
* 傳遞按鍵事件
* @param event
*/
onKeyDown(event) {
this.keyManager.onKeydown(event);
}
/**
* 點(diǎn)擊選中
* @param index
*/
selectItem(index: number) {
this.keyManager.setActiveItem(index);
}
}
二 FocusTrap
? ? ? ?FocusTrap是cdk ally模塊里面提供的一個(gè)指令践惑。用于捕獲元素中的Tab鍵焦點(diǎn)腹泌。同時(shí)控制焦點(diǎn)的范圍,Tab切換焦點(diǎn)的時(shí)候不會(huì)跳出這個(gè)區(qū)域。舉個(gè)例子比如有一個(gè)視圖元素添加了FocusTrap指令尔觉,這個(gè)視圖元素里面有三個(gè)input凉袱。這樣Tab鍵切換焦點(diǎn)的時(shí)候焦點(diǎn)會(huì)在這三個(gè)input之間切換。
? ? ? ?Selector: [cdkTrapFocus]
? ? ? ?Exported as: cdkTrapFocus
? ? ? ?還有幾個(gè)其他的指令可以配合FocusTrap指令來(lái)使用:cdkFocusRegionStart侦铜、cdkFocusRegionEnd专甩、cdkFocusInitial。咱們上面不是說(shuō)了FocusTrap指令會(huì)控制焦點(diǎn)的范圍泵额。cdkFocusRegionStart和cdkFocusRegionEnd指令有可以進(jìn)一步的控制焦點(diǎn)的范圍
- cdkFocusRegionStart:FocusTrap范圍的起點(diǎn)
- cdkFocusRegionEnd:FocusTrap范圍的終點(diǎn)
- cdkFocusInitial:區(qū)間出現(xiàn)時(shí)配深,一開(kāi)始獲取focus的item。
2.1 FocusTrap指令屬性介紹
FocusTrap屬性 | 類(lèi)型 | 解釋 |
---|---|---|
autoCapture: boolean | @Input('cdkTrapFocusAutoCapture') | 初始化的時(shí)候元素是否自動(dòng)獲取焦點(diǎn) |
enabled: boolean | @Input('cdkTrapFocus') | false Tab切換焦點(diǎn)的時(shí)候會(huì)跑到外面去嫁盲,true Tab切換焦點(diǎn)的時(shí)候焦點(diǎn)不會(huì)跑到外面去 |
2.2 FocusTrap指令使用
import {Component} from '@angular/core';
@Component({
selector: 'app-cdk-accessibility',
template: `
<!-- FocusTrap的使用篓叶,- 控制焦點(diǎn)的范圍,tab切換焦點(diǎn)的時(shí)候不會(huì)跳出這個(gè)區(qū)域 -->
<div cdkTrapFocus style="border: solid 1px #ccc; padding: 10px">
<!-- Tab and Shift + Tab will not leave this element. -->
<input placeholder="Email">
<input type="password" placeholder="Password" style="margin-left: 10px">
<button type="submit" style="margin-left: 10px">Submit</button>
</div>
`
})
export class CdkAccessibilityComponent {
}
2.3 cdkFocusRegionStart cdkFocusRegionEnd cdkFocusInitial的使用
? ? ? ?cdkFocusRegionStart和cdkFocusRegionEnd的使用應(yīng)該很好理解。就是用來(lái)控制范圍的羞秤。關(guān)鍵是cdkFocusInitial的使用缸托,cdkFocusInitial必須要配合cdkTrapFocus指令的cdkTrapFocusAutoCapture=true使用。而且我試了下cdkFocusInitial一開(kāi)始是沒(méi)有效果瘾蛋,沒(méi)都是隱藏顯示的時(shí)候才有效果俐镐,才獲取到焦點(diǎn)。
import {Component} from '@angular/core';
@Component({
selector: 'app-cdk-accessibility',
template: `
<div *ngIf="displayFocusTrap" cdkTrapFocus cdkTrapFocusAutoCapture="true"
style="border: solid 1px #ccc; padding: 10px; margin-top: 10px">
<input value="1">
<input style="margin-left: 10px" value="2" cdkFocusRegionStart>
<input style="margin-left: 10px" value="3" cdkFocusInitial>
<input style="margin-left: 10px" value="4" cdkFocusRegionEnd>
</div>
<button (click)="displayFocusTrap=!displayFocusTrap">顯示</button>
`
})
export class CdkAccessibilityComponent {
displayFocusTrap = false;
}
三 FocusMonitor
? ? ? ?FocusMonitor是cdk ally里面提供的一個(gè)Service哺哼。用于監(jiān)控焦點(diǎn)佩抹。FocusMonitor里面常用方法如下
export declare class FocusMonitor implements OnDestroy {
/**
* 監(jiān)聽(tīng)元素的焦點(diǎn)獲取
*/
monitor(element: HTMLElement, checkChildren?: boolean): Observable<FocusOrigin>;
monitor(element: ElementRef<HTMLElement>, checkChildren?: boolean): Observable<FocusOrigin>;
/**
* 停止監(jiān)聽(tīng)元素的焦點(diǎn)獲取
*/
stopMonitoring(element: HTMLElement): void;
stopMonitoring(element: ElementRef<HTMLElement>): void;
/**
* 設(shè)置元素獲取焦點(diǎn)
* @param element 元素
* @param origin 設(shè)置的焦點(diǎn)是通過(guò)哪個(gè)來(lái)的 'touch' | 'mouse' | 'keyboard' | 'program' | null
* @param options 用于配置focus行為的選項(xiàng).
*/
focusVia(element: HTMLElement, origin: FocusOrigin, options?: FocusOptions): void;
focusVia(element: ElementRef<HTMLElement>, origin: FocusOrigin, options?: FocusOptions): void;
}
3.1 FocusMonitor的使用
? ? ? ?一個(gè)簡(jiǎn)單的例子叼风,咱們僅僅是在元素獲取焦點(diǎn)的時(shí)候做一個(gè)簡(jiǎn)單的打印。
import {AfterViewInit, Component, ElementRef, OnDestroy} from '@angular/core';
import {FocusMonitor} from "@angular/cdk/a11y";
@Component({
selector: 'app-cdk-focus-monitor',
template: `
<div cdkTrapFocus style="border: solid 1px #ccc; padding: 10px; margin-top: 10px">
<input value="FocusMonitor item 1">
<input style="margin-left: 10px" value="FocusMonitor item 2">
<input style="margin-left: 10px" value="FocusMonitor item 3">
<input style="margin-left: 10px" value="FocusMonitor item 4">
</div>
`
})
export class CdkFocusMonitorComponent implements AfterViewInit, OnDestroy {
constructor(private _elementRef: ElementRef,
private _focusMonitor: FocusMonitor) {
}
ngAfterViewInit() {
/**
* 這里我們只是做了一個(gè)簡(jiǎn)單的打印
*/
this._focusMonitor.monitor(this._elementRef.nativeElement, true).subscribe(mode => {
console.log('元素獲取到焦點(diǎn) focused 來(lái)源 ' + mode);
});
}
ngOnDestroy() {
this._focusMonitor.stopMonitoring(this._elementRef.nativeElement);
}
}
四 FocusTrapFactory
? ? ? ?FocusTrapFactory也是cdk ally里面提供的一個(gè)Service棍苹。他的功能就是用來(lái)給元素添加cdkFocusTrap指令无宿。FocusTrapFactory常用函數(shù)就一個(gè),如下
export declare class FocusTrapFactory {
/**
* 給指定的元素添加cdkFocusTrap指令枢里,deferCaptureElements參數(shù)正好對(duì)應(yīng)cdkFocusTrap指令
* @Input('cdkTrapFocusAutoCapture')功能
*/
create(element: HTMLElement, deferCaptureElements?: boolean): FocusTrap;
}
4.1 FocusTrapFactory使用
? ? ? ?通過(guò)FocusTrapFactory的crete函數(shù)達(dá)到cdkFocusTrap指令的效果孽鸡。
import {AfterViewInit, Component, ElementRef} from '@angular/core';
import {FocusTrap, FocusTrapFactory} from "@angular/cdk/a11y";
@Component({
selector: 'app-cdk-focus-trap-factory',
template: `
<div style="border: solid 1px #ccc; padding: 10px; margin-top: 10px">
<input value="FocusTrapFactory item 1">
<input style="margin-left: 10px" value="FocusTrapFactory item 2">
<input style="margin-left: 10px" value="FocusTrapFactory item 3">
<input style="margin-left: 10px" value="FocusTrapFactory item 4">
</div>
`
})
export class CdkFocusTrapFactoryComponent implements AfterViewInit {
private _focusTrap: FocusTrap;
constructor(private _elementRef: ElementRef,
private _focusTrapFactory: FocusTrapFactory) {
}
ngAfterViewInit() {
this._focusTrap = this._focusTrapFactory.create(this._elementRef.nativeElement);
}
}
五 InteractivityChecker
? ? ? ?InteractivityChecker是一個(gè)Service,用于檢查元素的一些狀態(tài)栏豺。常見(jiàn)方法如下彬碱。
export declare class InteractivityChecker {
/**
* 元素是否 disabled.
*/
isDisabled(element: HTMLElement): boolean;
/**
* 元素是否visible
*
* This will capture states like `display: none` and `visibility: hidden`, but not things like
* being clipped by an `overflow: hidden` parent or being outside the viewport.
*
* @returns Whether the element is visible.
*/
isVisible(element: HTMLElement): boolean;
/**
* 元素是否接受Tab按鍵,不如Tab按鍵切換焦點(diǎn)
*/
isTabbable(element: HTMLElement): boolean;
/**
* 元素是否可以獲取焦點(diǎn)
*/
isFocusable(element: HTMLElement): boolean;
}
5.1 InteractivityChecker使用
? ? ? ?舉一個(gè)非常簡(jiǎn)單的例子奥洼,打印出button的各種狀態(tài)巷疼。
import {Component, ElementRef, OnInit, ViewChild} from '@angular/core';
import {InteractivityChecker} from "@angular/cdk/a11y";
@Component({
selector: 'app-cdk-interactivity-checker',
template: `
<button #interactivityCheckerButton>InteractivityChecker測(cè)試</button>
<p>上面button是否disable: {{disable}}</p>
<p>上面button是否visible: {{visible}}</p>
<p>上面button是否可以tabable: {{tabable}}</p>
<p>上面button是否可以focusable: {{focusable}}</p>
`
})
export class CdkInteractivityCheckerComponent implements OnInit {
@ViewChild('interactivityCheckerButton') button: ElementRef;
disable: boolean;
visible: boolean;
tabable: boolean;
focusable: boolean;
constructor(private _interactivityChecker: InteractivityChecker) {
}
ngOnInit() {
this.disable = this._interactivityChecker.isDisabled(this.button.nativeElement);
this.visible = this._interactivityChecker.isVisible(this.button.nativeElement);
this.tabable = this._interactivityChecker.isTabbable(this.button.nativeElement);
this.focusable = this._interactivityChecker.isFocusable(this.button.nativeElement);
}
}
六 LiveAnnouncer
? ? ? ?LiveAnnouncer也是一個(gè)Service。用于在屏幕上發(fā)布一個(gè)消息灵奖。把消息顯示在屏幕上皮迟。關(guān)于這一部分的內(nèi)容估計(jì)的去看下W3C關(guān)于WAI-ARIA的使用。我們就舉一個(gè)簡(jiǎn)單的例子桑寨。
import {Component} from '@angular/core';
import {LiveAnnouncer} from "@angular/cdk/a11y";
@Component({
selector: 'app-cdk-live-announcer',
template: `
`
})
export class CdkLiveAnnouncerComponent {
index = 1;
/**
* 會(huì)在屏幕上輸出Hey Google,三秒之后又會(huì)換成Hey Google 2
*/
constructor(private liveAnnouncer: LiveAnnouncer) {
liveAnnouncer.announce("Hey Google");
setTimeout(() => {
this.timerTask();
}, 3000);
}
timerTask() {
this.index = this.index + 1;
this.liveAnnouncer.announce("Hey Google " + this.index.toString(), "off");
}
}
? ? ? ?關(guān)于cdk ally咱們就扯這么多忿檩,希望能對(duì)大家有點(diǎn)幫助尉尾。當(dāng)然了里面很有很多其他的類(lèi)咱們沒(méi)有介紹到。大家在時(shí)機(jī)使用的時(shí)候可以對(duì)照官方文檔看下 https://material.angular.io/cdk/a11y/overview燥透。 文章中涉及到的例子連接地址 https://github.com/tuacy/angular-cdk-study