与 DOM 解耦并将功能引入指令
Decoupling from the DOM and bringing functionality into a directive
我正在尝试制定 Snap-to-Component 指令。在这一点上,我已经用应用程序组件中的逻辑进行了概念验证(可能会被 Renderer2 HostListeners 和 HostBindings 取代),看起来我必须获得 dom 属性(child1L,child1R...等)的 children 可能使用 Renderer2。我的问题是,您如何将我到目前为止所做的事情分离到一个指令或一组 parent 和 child 指令中?或者至少你会从这里往哪个方向走?我不熟悉使用 Renderer2、HostListeners 和 HostBinding,所以我想知道更有经验的人会如何做到这一点。谢谢你。这是我的 current stackblitz.
app.component.ts:
import { Component,ElementRef,ViewChild } from '@angular/core';
@Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: [ './app.component.css' ]
})
export class AppComponent {
switchDirection = "first";
head: ElementRef;
@ViewChild('child01') child01;
@ViewChild('child02') child02;
@ViewChild('child03') child03;
onScroll(event: Event) {
let viewBoundaryL = (event.target as HTMLElement).scrollLeft;
console.log("viewBoundaryL:" + viewBoundaryL);
//SNAP FROM FIRST TO SECOND CHILD
if(viewBoundaryL >= 50 && this.switchDirection === "first"){
this.child02.el.nativeElement.scrollIntoView({ behavior: 'smooth', block: "center" });
setTimeout(() => {
this.switchDirection = "second";
// console.log(this.switchDirection)
}, 300);
}
//SNAP FROM SECOND TO FIRST CHILD
if(viewBoundaryL <= 310 && this.switchDirection === "second"){
this.child01.el.nativeElement.scrollIntoView({ behavior: 'smooth', block: "center" });
setTimeout(() => {
this.switchDirection = "first";
// console.log(this.switchDirection)
}, 300);
}
//SNAP FROM SECOND TO THIRD CHILD
if(viewBoundaryL >= 370 && this.switchDirection === "second"){
this.child03.el.nativeElement.scrollIntoView({ behavior: 'smooth', block: "center" });
setTimeout(() => {
this.switchDirection = "third";
// console.log(this.switchDirection)
}, 300);
}
//SNAP FROM THIRD TO SECOND CHILD
if(viewBoundaryL <= 615 && this.switchDirection === "third"){
this.child02.el.nativeElement.scrollIntoView({ behavior: 'smooth', block: "center" });
setTimeout(() => {
this.switchDirection = "second";
// console.log(this.switchDirection)
}, 300);
}
}
}
app.component.html:
<div class="container" (scroll)="onScroll($event)" >
<child1 #child01></child1>
<child2 #child02></child2>
<child3 #child03></child3>
</div>
感谢您的见解!
您可能想要创建一个 attribute directive。
您可以使用 Angular CLI 和以下命令轻松创建 directive(您可以提供路径作为名称 core/directives/my-directive-name):
ng generate directive <name-of-directive>
然后在构造函数中,您可以添加以下内容以获取对元素的引用。
el: ElementRef
最后使用 HostListener 或任何技术绑定到滚动事件。您可以调用您的 snap to element 代码(必须更改为仅检查自身),然后该元素将检查自己是否需要启动滚动。如果它满足条件,那么它就满足。
为了进一步加分,您可以添加设置输入和捕捉元素的时间,例如,带有指令的模板将如下所示:
<div [myDirective] [scrollAt]="300"></div>
然后在指令本身中你将拥有:
@Input() scrollAt: number = 300 // sets a default incase it isn't provided;
然后您可以将此变量用于您的视图边界。
希望这对您有所帮助,或者至少让您走上正轨!
我正在尝试制定 Snap-to-Component 指令。在这一点上,我已经用应用程序组件中的逻辑进行了概念验证(可能会被 Renderer2 HostListeners 和 HostBindings 取代),看起来我必须获得 dom 属性(child1L,child1R...等)的 children 可能使用 Renderer2。我的问题是,您如何将我到目前为止所做的事情分离到一个指令或一组 parent 和 child 指令中?或者至少你会从这里往哪个方向走?我不熟悉使用 Renderer2、HostListeners 和 HostBinding,所以我想知道更有经验的人会如何做到这一点。谢谢你。这是我的 current stackblitz.
app.component.ts:
import { Component,ElementRef,ViewChild } from '@angular/core';
@Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: [ './app.component.css' ]
})
export class AppComponent {
switchDirection = "first";
head: ElementRef;
@ViewChild('child01') child01;
@ViewChild('child02') child02;
@ViewChild('child03') child03;
onScroll(event: Event) {
let viewBoundaryL = (event.target as HTMLElement).scrollLeft;
console.log("viewBoundaryL:" + viewBoundaryL);
//SNAP FROM FIRST TO SECOND CHILD
if(viewBoundaryL >= 50 && this.switchDirection === "first"){
this.child02.el.nativeElement.scrollIntoView({ behavior: 'smooth', block: "center" });
setTimeout(() => {
this.switchDirection = "second";
// console.log(this.switchDirection)
}, 300);
}
//SNAP FROM SECOND TO FIRST CHILD
if(viewBoundaryL <= 310 && this.switchDirection === "second"){
this.child01.el.nativeElement.scrollIntoView({ behavior: 'smooth', block: "center" });
setTimeout(() => {
this.switchDirection = "first";
// console.log(this.switchDirection)
}, 300);
}
//SNAP FROM SECOND TO THIRD CHILD
if(viewBoundaryL >= 370 && this.switchDirection === "second"){
this.child03.el.nativeElement.scrollIntoView({ behavior: 'smooth', block: "center" });
setTimeout(() => {
this.switchDirection = "third";
// console.log(this.switchDirection)
}, 300);
}
//SNAP FROM THIRD TO SECOND CHILD
if(viewBoundaryL <= 615 && this.switchDirection === "third"){
this.child02.el.nativeElement.scrollIntoView({ behavior: 'smooth', block: "center" });
setTimeout(() => {
this.switchDirection = "second";
// console.log(this.switchDirection)
}, 300);
}
}
}
app.component.html:
<div class="container" (scroll)="onScroll($event)" >
<child1 #child01></child1>
<child2 #child02></child2>
<child3 #child03></child3>
</div>
感谢您的见解!
您可能想要创建一个 attribute directive。
您可以使用 Angular CLI 和以下命令轻松创建 directive(您可以提供路径作为名称 core/directives/my-directive-name):
ng generate directive <name-of-directive>
然后在构造函数中,您可以添加以下内容以获取对元素的引用。
el: ElementRef
最后使用 HostListener 或任何技术绑定到滚动事件。您可以调用您的 snap to element 代码(必须更改为仅检查自身),然后该元素将检查自己是否需要启动滚动。如果它满足条件,那么它就满足。
为了进一步加分,您可以添加设置输入和捕捉元素的时间,例如,带有指令的模板将如下所示:
<div [myDirective] [scrollAt]="300"></div>
然后在指令本身中你将拥有:
@Input() scrollAt: number = 300 // sets a default incase it isn't provided;
然后您可以将此变量用于您的视图边界。
希望这对您有所帮助,或者至少让您走上正轨!