Comment écrire de bonnes bibliothèques pour Angular

Le Web est un environnement riche en fonctionnalités. Nous pouvons naviguer dans la réalité virtuelle avec une manette de jeu, jouer au synthétiseur avec un clavier MIDI, acheter des marchandises avec une seule touche de notre doigt. Toutes ces capacités impressionnantes sont fournies par des API natives, qui, tout comme leurs fonctionnalités, sont extrêmement diverses.



Angular est une excellente plate-forme avec certains des meilleurs outils de l'environnement frontal. Et, bien sûr, il existe une certaine manière de le faire "de manière angulaire". Ce que j'aime personnellement dans ce framework, c'est le sentiment de satisfaction que vous ressentez lorsque tout est bien fait: code soigné, architecture claire. Jetons un coup d'œil à ce qui rend le code correctement écrit en Angular.





La voie angulaire



Angular, , , , . , , , Angular « ». : . opensource- Web APIs for Angular. — , API Angular. @ng-web-apis/intersection-observer.



, :



  1. Angular , JavaScript- .
  2. Angular , .
  3. Angular Observable, API .


.



vs



, , IntersectionObserver:



const callback = entries => { ... };
const options = {
   root: document.querySelector('#scrollArea'),
   rootMargin: '10px',
   threshold: 1
};
const observer = new IntersectionObserver(callback, options);

observer.observe(document.querySelector('#target'));




API



, , . Angular :



<div
   waIntersectionObserver
   waIntersectionThreshold="1"
   waIntersectionRootMargin="10px"
   (waIntersectionObservee)="onIntersection($event)"
>
   I'm being observed
</div>


Angular Payment Request API. , .

2 : , — . . . -, . observe/unobserve.



IntersectionObserver Map . , , :



@Directive({
   selector: '[waIntersectionObserver]',
})
export class IntersectionObserverDirective extends IntersectionObserver
   implements OnDestroy {
   private readonly callbacks = new Map<Element, IntersectionObserverCallback>();

   constructor(
       @Optional() @Inject(INTERSECTION_ROOT) root: ElementRef<Element> | null,
       @Attribute('waIntersectionRootMargin') rootMargin: string | null,
       @Attribute('waIntersectionThreshold') threshold: string | null,
   ) {
       super(
           entries => {
               this.callbacks.forEach((callback, element) => {
                   const filtered = entries.filter(({target}) => target === element);

                   return filtered.length && callback(filtered, this);
               });
           },
           {
               root: root && root.nativeElement,
               rootMargin: rootMargin || ROOT_MARGIN_DEFAULT,
               threshold: threshold
                 ? threshold.split(',').map(parseFloat)
                 : THRESHOLD_DEFAULT,
           },
       );
   }

   observe(target: Element, callback: IntersectionObserverCallback = () => {}) {
       super.observe(target);
       this.callbacks.set(target, callback);
   }

   unobserve(target: Element) {
       super.unobserve(target);
       this.callbacks.delete(target);
   }

   ngOnDestroy() {
       this.disconnect();
   }
}


— .



Dependency Injection



DI Angular , . . , , . , , . :



@Directive({
   selector: '[waIntersectionRoot]',
   providers: [
       {
           provide: INTERSECTION_ROOT,
           useExisting: ElementRef,
       },
   ],
})
export class IntersectionRootDirective {}


:



<div waIntersectionRoot>
   ...
   <div
       waIntersectionObserver
       waIntersectionThreshold="1"
       waIntersectionRootMargin="10px"
       (waIntersectionObservee)="onIntersection($event)"
   >
       I'm being observed
   </div>
   ...
</div>


DI , , Web Audio API Angular.

— . . , - -, .



DI IntersectionObserver RxJS Observable, .



Observables



API , Angular RxJs . Observable, , — . - IntersectionObserver, Observable. , :



@Injectable()
export class IntersectionObserveeService extends Observable<IntersectionObserverEntry[]> {
   constructor(
       @Inject(ElementRef) {nativeElement}: ElementRef<Element>,
       @Inject(IntersectionObserverDirective)
       observer: IntersectionObserverDirective,
   ) {
       super(subscriber => {
           observer.observe(nativeElement, entries => {
               subscriber.next(entries);
           });

           return () => {
               observer.unobserve(nativeElement);
           };
       });
   }
}




Observable, IntersectionObserver. Angular, new-.



Observable- Geolocation API Resize Observer API, .

Output. EventEmitter, Observable , , :



@Directive({
   selector: '[waIntersectionObservee]',
   outputs: ['waIntersectionObservee'],
   providers: [IntersectionObserveeService],
})
export class IntersectionObserveeDirective {
   constructor(
       @Inject(IntersectionObserveeService)
       readonly waIntersectionObservee: Observable<IntersectionObserverEntry[]>,
   ) {}
}


, RxJs-, map, filter, switchMap, .





, IntersectionObserver Observable. DI . 1 .gzip Github npm.



, , . , . , , Internet Explorer.



, . , API Angular. - , Canvas MIDI-, — .



GDG DevParty Russia, API Angular. , :






All Articles