还有另一种使用指令的方法。好吧,我们的想法是,我们使用 ViewChildren 在 app.component 中获取所有包含指令的 div,然后带有指令的 div 发送事件并调用 app.component 的函数。所以 app.component 变成了
<div arrow-div (event)="handler($event)>my div</div>
<div arrow-div (event)="handler($event)>my div</div>
...
但我们可以使用“服务”让事情变得更加“透明”。
想象一下这样的服务
@Injectable({
providedIn: 'root',
})
export class KeyBoardService {
keyBoard:Subject<any>=new Subject<any>();
sendMessage(message:any)
{
this.keyBoard.next(message)
}
}
我们的指令可以在按下键箭头时调用服务“sendMessage”,并在我们的 app.component 中订阅该服务。然后我们的 app.component 有点像
<div arrow-div >my div</div>
<div arrow-div >my div</div>
<br/>
<div arrow-div >my div</div>
<div arrow-div >my div</div>
我们避免在我们的 div 中出现这种“丑陋”的 (event)="handler($event)" !!
嗯,指令很简单,使用@Hostlistener 监听key,使用renderer2 添加属性“tabindex”(要使div 可聚焦,我们需要添加tabIndex)。所以
@Directive({
selector: '[arrow-div]',
})
export class ArrowDivDirective {
constructor(private keyboardService: KeyBoardService, public element: ElementRef, private render: Renderer2) {
this.render.setAttribute(this.element.nativeElement, "tabindex", "0")
}
@HostListener('keydown', ['$event']) onKeyUp(e) {
switch (e.keyCode) {
case 38:
this.keyboardService.sendMessage({ element: this.element, action: 'UP' })
break;
case 37:
this.keyboardService.sendMessage({ element: this.element, action: 'LEFT' })
break;
case 40:
this.keyboardService.sendMessage({ element: this.element, action: 'DOWN' })
break;
case 39:
this.keyboardService.sendMessage({ element: this.element, action: 'RIGTH' })
break;
}
}
}
还有我们的 app.component.ts
export class AppComponent implements OnInit {
columns:number=2;
@ViewChildren(ArrowDivDirective) inputs:QueryList<ArrowDivDirective>
constructor(private keyboardService:KeyBoardService){}
ngOnInit()
{
this.keyboardService.keyBoard.subscribe(res=>{
this.move(res)
})
}
move(object)
{
const inputToArray=this.inputs.toArray()
let index=inputToArray.findIndex(x=>x.element==object.element);
switch (object.action)
{
case "UP":
index-=this.columns;
break;
case "DOWN":
index+=this.columns;
break;
case "LEFT":
index--;
break;
case "RIGTH":
index++;
break;
case "RIGTH":
index++;
break;
}
if (index>=0 && index<this.inputs.length)
inputToArray[index].element.nativeElement.focus();
}
}
如果我们使用列和行创建“网格”并使用向上和向下键在行之间移动,请注意我使用了变量“列”。发送“元素”避免我们必须存储“div 聚焦”
你可以在stackblitz看到一个例子