美文网首页Angular框架专题
Angular框架的事件冒泡(Event Modifiers)以

Angular框架的事件冒泡(Event Modifiers)以

作者: 听书先生 | 来源:发表于2021-11-29 23:03 被阅读0次

    Dom元素会通过一些事件通过Dom的层级结构进行传播,这种传播的过程叫做事件冒泡,事件冒泡是指的最内层的事件类型触发导致了父级的Dom触发了相同的事件类型事件,由内到外的一个过程,而由外到内指的是事件捕获。

    import { Component } from "@angular/core";
    
    @Component({
      selector:'my-component',
      template:`
       <div (click)="handleClick()">
          <button >点击</button>
       </div> 
      `
    })
    
    export class AppComponent {
      handleClick() {
        console.log('触发了点击事件...');
      }
    }
    

    上述表示div的盒子添加点击事件后被执行。

    angular中组件使用事件冒泡

    在angular中,我们能使用@Output装饰器和EventEmitter自定义事件,它不同于Dom事件,因为它不支持事件冒泡。
    比如我们先自定义一个组件:

    import { Component } from '@angular/core';
    
    @Component({
        selector: 'test-com',
        template: `
        <div>
          <button>Click</button>
        </div>
      `
    })
    export class TestComComponent { }
    

    在主程序中使用自定义的组件作为子组件进行使用。

    import { Component } from '@angular/core';
    
    @Component({
      selector: 'my-app',
      template: `
        <div>
          <test-com (click)="handleClick()"></test-com>
        </div>
      `
    })
    export class AppComponent {
      handleClick() {
        console.log('Click');
      }
    }
    

    这种情况下可以看到依旧是正常输出的,表示我们在触发点击事件时,触发的是添加在子组件上的click事件,但是如果此时我们的子组件中也有click点击事件呢?
    修改上面的自定义组件的代码:

    import { Component, Output, EventEmitter } from '@angular/core';
    
    @Component({
        selector: 'test-com',
        template: `
        <div>
          <button (click)="handleClick('child')">Click child</button>
        </div>
      `
    })
    export class TestComComponent { 
        @Output() click = new EventEmitter();
    
        handleClick(button: string) {
            this.click.next(button);
        }
    }
    
    import { Component } from '@angular/core';
    
    @Component({
      selector: 'my-app',
      template: `
        <div>
          <test-com (click)="handleClick($event)"></test-com>
        </div>
      `
    })
    export class AppComponent {
      handleClick(event: any) {
        console.log(event);
      }
    }
    

    当点击Click child时,Angular内部会处理自定义事件和DOM事件,当Click事件触发后,handleClick方法接收的参数是MouseEvent对象。
    那么可以直接在点击事件时添加stopPropagation()方法

    import { Component, Output, EventEmitter } from '@angular/core';
    
    @Component({
        selector: 'test-com',
        template: `
        <div>
          <button (click)="handleClick('child')">Click child</button>
        </div>
      `
    })
    export class TestComComponent { 
        @Output() click = new EventEmitter();
    
        handleClick(event: Event, button: string) {
            event.stopPropagation();
            this.click.next(button);
        }
    }
    

    DOM元素的冒泡机制,允许父元素去监听子元素触发的事件,在Angular框架中,虽然可以直接使用stopPropagation直接解决问题,但是实际开发中,并不建议这么操作。

    Event Modifiers

    在dom元素中,两种情形需要注意的点,一种是会触发默认事件,则使用preventDefault()取消事件的所有默认行为,一种是事件冒泡,使用stopPropagation()阻止当前事件在Dom上的冒泡。
    在Angular中阻止事件冒泡的写法大致有几种:

    <div>
      <button (click)="$event.stopPropagation(); doSomething()">Click me</button>
    </div>
    
    @Component({
      selector: 'exe-app',
      template: `
          <div>
            <button (click)="doSomething($event)">Click me</button>
          </div>`
    })
    export class AboutComponent {
      doSomething($event: Event) {
        $event.stopPropagation();
      }
    }
    

    在Angular框架中,我们可以自定义指令声明阻止事件冒泡

    import { Directive, Output, EventEmitter, Renderer2, ElementRef } from '@angular/core';
    
    @Directive({
        selector: '[click.stop]'
    })
    export class StopPropagationDirective {
        @Output("click.stop") stopPropEvent = new EventEmitter();
        unsubscribe: () => void;
    
        constructor(
            private renderer: Renderer2,
            private element: ElementRef) {
        }
    
        ngOnInit() {
            this.unsubscribe = this.renderer.listen(
                this.element.nativeElement, 'click', event => {
                    event.stopPropagation();
                    this.stopPropEvent.emit(event);
                });
        }
    
        ngOnDestroy() {
            this.unsubscribe();
        }
    }
    

    因此,在子组件中使用click事件时,只需要(click.stop)="handleClick()"则可以阻止事件的冒泡,更适合多人开发,避免了遇到一次就使用一次stopPropagation

    <button (click.stop)="handleClick()">点击</button>
    

    需要注意的是:自定义指令文件创建好后,需要在你使用到的module.ts下声明一下。

    import { Directive, ElementRef, HostListener } from '@angular/core';
    
    @Directive({
      selector: '[appMyDirective]'
    })
    export class MyDirectiveDirective {
    
      constructor(public elementRef: ElementRef) { }
      @HostListener('keyup', ['$event.target'])
      keyupFun(evt:any) {
        if (evt.value) {
          console.log(this.elementRef);
          this.elementRef.nativeElement.value = evt.value.trim();
        }
      }
    
    }
    
    

    创建好之后,在module.ts声明

    import { MyDirectiveDirective } from "../../../my-directive.directive";
    
    @NgModule({
      declarations: [
        ...
        StopPropagationDirective,
        MyDirectiveDirective
      ]
    })
    
    image.png

    相关文章

      网友评论

        本文标题:Angular框架的事件冒泡(Event Modifiers)以

        本文链接:https://www.haomeiwen.com/subject/tahrxrtx.html