Web是功能丰富的环境。我们可以使用游戏手柄导航虚拟现实,使用MIDI键盘玩合成器,只需轻按一下手指即可购买商品。所有这些令人印象深刻的功能都是由本机API提供的,本机API与它们的功能一样非常多样化。
Angular是一个出色的平台,在前端环境中具有一些最佳工具。而且,当然,有某种方式可以“以角度的方式”进行。我个人对这个框架的喜爱是,当一切都做对时,您会感到满意:整洁的代码,清晰的体系结构。让我们看看是什么使代码正确地用Angular编写。

角度方式
Angular, , , , . , , , Angular « ». : . opensource- Web APIs for Angular. — , API Angular. @ng-web-apis/intersection-observer.
, :
- Angular , JavaScript- .
- Angular , .
- 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. , :