рд╣рдо рдХреЛрдгреАрдп рдореЗрдВ рдШрдЯрдирд╛рдУрдВ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдкрдВрдк рдХрд░рддреЗ рд╣реИрдВ

рдПрдХ рдмрд╛рд░, рдореИрдВрдиреЗ рдПрдВрдЧреБрд▓рд░ рдореЗрдВ EventManager рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдиреЗ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдПрдХ рд▓реЗрдЦ рд▓рд┐рдЦрд╛ ред рдЗрд╕рдореЗрдВ, рдореИрдВрдиреЗ рдЗрд╕ рдмрд╛рд░реЗ рдореЗрдВ рдмрд╛рдд рдХреА рдХрд┐ рдХреИрд╕реЗ рдЖрдк рдИрд╡реЗрдВрдЯ рд╕рджрд╕реНрдпрддрд╛ рдХреЗ рд▓рд┐рдП рд╕рд╛рдорд╛рдиреНрдп рд╡рд╛рдХреНрдпрд╡рд┐рдиреНрдпрд╛рд╕ рдХреЛ рдмрдЪрд╛ рд╕рдХрддреЗ рд╣реИрдВ, рдЬрдмрдХрд┐ рдЕрдХреНрд╕рд░ рдФрд░ рд╕рдВрд╡реЗрджрдирд╢реАрд▓ рдШрдЯрдирд╛рдУрдВ рдкрд░ рдкрд░рд┐рд╡рд░реНрддрдиреЛрдВ рдХреА рдЬрд╛рдБрдЪ рдХреЗ рдЕрдирд╛рд╡рд╢реНрдпрдХ рдЯреНрд░рд┐рдЧрд░ рд╕реЗ рдмрдЪрддреЗ рд╣реИрдВред


рд╣рд╛рд▓рд╛рдБрдХрд┐, рдореИрдВрдиреЗ рдЬрд┐рд╕ рд╡рд┐рдзрд┐ рдХрд╛ рд╡рд░реНрдгрди рдХрд┐рдпрд╛ рд╣реИ рд╡рд╣ рдмреЛрдЭрд┐рд▓ рдФрд░ рд╕рдордЭрдиреЗ рдореЗрдВ рдХрдард┐рди рд╣реИред рдпрд╣ рд╕рдЬреНрдЬрд╛рдХрд╛рд░реЛрдВ рдкрд░ рдлрд╝рд┐рд▓реНрдЯрд░рд┐рдВрдЧ рдХреЛ рдлрд┐рд░ рд╕реЗ рд▓рд┐рдЦрдиреЗ рдХрд╛ рд╕рдордп рд╣реИред



рд╕рдВрдХреНрд╖рд┐рдкреНрдд рд░рд┐рдкреНрд▓реЗ


рдЙрди рд▓реЛрдЧреЛрдВ рдХреЗ рд▓рд┐рдП рдЬреЛ рдкрд┐рдЫрд▓реЗ рд▓реЗрдЦ рдХреЛ рдирд╣реАрдВ рдкрдврд╝рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ, рд╕рдорд╕реНрдпрд╛ рдХрд╛ рд╕рд╛рд░рд╛рдВрд╢:


  1. рдХреЛрдгреАрдп рдЯреЗрдореНрдкрд▓реЗрдЯ ( (eventName)) рдФрд░ рд╕рдЬреНрдЬрд╛рдХрд╛рд░реЛрдВ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ ( ) рдореЗрдВ рдШрдЯрдирд╛рдУрдВ рдХреА рдШреЛрд╖рдгрд╛ рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИ @HostListener(тАШeventNameтАЩ)ред
  2. рдПрдХ рдкрд░рд┐рд╡рд░реНрддрди рд╕рддреНрдпрд╛рдкрди рд░рдгрдиреАрддрд┐ рдХреЗ рд╕рд╛рде, OnPushрдпрджрд┐ рдХреЛрдИ рдШрдЯрдирд╛ рдШрдЯрддреА рд╣реИ, рддреЛ рдПрдВрдЧреБрд▓рд░ рдПрдХ рдорд╛рдиреНрдпрддрд╛ рдЪрд▓рд╛рдПрдЧрд╛ред
  3. рдЬреИрд╕реЗ рдШрдЯрдирд╛рдХреНрд░рдо scroll, mousemove, dragрдмрд╣реБрдд рдмрд╛рд░ рд╢реБрд░реВ рд╣реЛ рдЧрдпрд╛ред рд╡реНрдпрд╡рд╣рд╛рд░ рдореЗрдВ, рдЖрдкрдХреЛ рдХреЗрд╡рд▓ рдЙрдирдореЗрдВ рд╕реЗ рдХреБрдЫ рдХрд╛ рдЬрд╡рд╛рдм рджреЗрдирд╛ рд╣реЛрдЧрд╛ (рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдЬрдм рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдиреЗ рдХрдВрдЯреЗрдирд░ рдХреЛ рдЕрдВрдд рддрдХ рд╕реНрдХреНрд░реЙрд▓ рдХрд┐рдпрд╛ рдерд╛ - рдирдП рддрддреНрд╡ рд▓реЛрдб рдХрд░реЗрдВ)ред
  4. EventManagerрдкреНрд░рджрд╛рди рдХрд┐рдП рдЧрдП EventManagerPluginрдПрд╕ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдХреЛрдгреАрдп рдШрдЯрдирд╛ рдкреНрд░рд╕рдВрд╕реНрдХрд░рдг рдХреЛ рд╕рдВрднрд╛рд▓рддрд╛ рд╣реИ ред
  5. Angular , .

. . .



Angular (keydown.ctrl.enter ).


, EventManager. . Angular , EVENT_MANAGER_PLUGINS . , , . addEventListener , , , , , . .


preventDefault stopPropagation. , , , :


@Injectable()
export class StopEventPlugin {
  supports(event: string): boolean {
    return event.split('.').includes('stop');
  }

  addEventListener(
    element: HTMLElement, 
    event: string, 
    handler: Function
  ): Function {
    const wrapped = (event: Event) => {
      event.stopPropagation();
      handler(event);
    };

    return this.manager.addEventListener(
      element,
      event
        .split('.')
        .filter(v => v !== 'stop')
        .join('.'),
      wrapped,
    );
  }
}

. , :


  1. Angular, .
  2. .
  3. .

, NgZone :


@Injectable()
export class SilentEventPlugin {
  supports(event: string): boolean {
    return event.split('.').includes('silent');
  }

  addEventListener(
    element: HTMLElement,
    event: string,
    handler: Function
  ): Function {
    return this.manager.getZone().runOutsideAngular(() =>
      this.manager.addEventListener(
        element,
        event
          .split('.')
          .filter(v => v !== 'silent')
          .join('.'),
        handler,
      ),
    );
  }
}

, .



, -. /, this.


, , . тАФ - , , . $event @HostListener. :


export function shouldCall<T>(
  predicate: Predicate<T>
): MethodDecorator {
  return (_target, _key, desc: PropertyDescriptor) => {
    const {value} = desc;

    desc.value = function(this: T, ...args: any[]) {
      if (predicate.apply(this, args)) {
        value.apply(this, args);
      }
    };
  };
}

. тАФ - Angular, .


Angular 10 Ivy , markDirty(this). , - NgZone. . , . , NgZone , :


@Injectable()
export class ZoneEventPlugin {
  supports(event: string): boolean {
    return event.split('.').includes('init');
  }

  addEventListener(
    _element: HTMLElement,
    _event: string, 
    handler: Function
  ): Function {
    const zone = this.manager.getZone();
    const subscription = zone.onStable.subscribe(() => {
      subscription.unsubscribe();
      handler(zone);
    });

    return () => {};
  }
}

тАФ .init , ( , ). @HostListener(тАШprop.initтАЩ, [тАШ$eventтАЩ]) :


export function shouldCall<T>(
  predicate: Predicate<T>
): MethodDecorator {
  return (_, key, desc: PropertyDescriptor) => {
    const {value} = desc;

    desc.value = function() {
      const zone = arguments[0] as NgZone;

      Object.defineProperty(this, key, {
        value(this: T, ...args: any[]) {
          if (predicate.apply(this, args)) {
            zone.run(() => {
              value.apply(this, args);
            });
          }
        },
      });
    };
  };
}

, . , . Ivy.




, , :
https://stackblitz.com/edit/angular-event-filter-decorator


, , , . , , . async Observable :


<p *ngFor="let item of service.items$ | async">{{item}}</p>

, :


export function scrolledToBottom(
   {scrollTop, scrollHeight, clientHeight}: HTMLElement
): boolean {
  return scrollTop >= scrollHeight - clientHeight - 20;
}

@Component({
  selector: 'awesome-component',
  templateUrl: './awesome-component.component.html',
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class AwesomeComponent {
  constructor(@Inject(Service) readonly service: Service) {}

  @HostListener('scroll.silent', ['$event.currentTarget'])
  @HostListener('init.onScroll', ['$event'])
  @shouldCall(scrolledToBottom)
  onScroll() {
    this.service.loadMore();
  }
}

. :
https://stackblitz.com/edit/angular-event-filters-scroll


, . CustomEvent, . .


(1 gzip) open-source- @tinkoff/ng-event-filters. Angular 10 2.0.0, markDirty(this), Angular 4.



npm-


-, open source, ? Angular Open-source Library Starter, . CI, , , CHANGELOG, .

All Articles