Wie man gute Bibliotheken für Angular schreibt

Das Web ist eine funktionsreiche Umgebung. Wir können mit einem Gamepad durch die virtuelle Realität navigieren, Synthesizer mit einem MIDI-Keyboard spielen und Waren mit nur einem Fingerdruck kaufen. All diese beeindruckenden Funktionen werden von nativen APIs bereitgestellt, die ebenso wie ihre Funktionen äußerst vielfältig sind.



Angular ist eine hervorragende Plattform mit einigen der besten Tools in der Front-End-Umgebung. Und natürlich gibt es eine bestimmte Möglichkeit, dies "Angular" zu tun. Was ich persönlich an diesem Framework liebe, ist das Gefühl der Zufriedenheit, das man bekommt, wenn alles richtig gemacht wird: ordentlicher Code, klare Architektur. Werfen wir einen Blick darauf, wie der Code in Angular richtig geschrieben wird.





Der eckige Weg



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