【问题标题】:Decoupling from the DOM and bringing functionality into a directive与 DOM 解耦并将功能引入指令
【发布时间】:2018-07-05 18:58:48
【问题描述】:

我正在尝试制定 Snap-to-Component 指令。在这一点上,我已经使用应用程序组件中的逻辑进行了概念验证(可能会被 Renderer2 HostListeners 和 HostBindings 替换),看起来我必须获取 dom 属性(child1L、child1R ......等.) 的孩子可能正在使用 Renderer2。我的问题是你如何将我到目前为止所做的事情分解为一个指令或一组父子指令?或者至少你会从这里往哪个方向走?我是使用 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>

感谢您的见解!

【问题讨论】:

    标签: angular typescript angular-directive


    【解决方案1】:

    您可能想要创建一个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;
    

    然后你可以使用这个变量作为你的视图边界。

    希望这会有所帮助,或者至少能让您走上正轨!

    【讨论】:

    • 好的,非常感谢您的指导!因此,如果指令是在带有滚动事件的元素的子元素上,我可以像你所说的那样做主机监听器,但我将如何动态引用子元素的兄弟姐妹?使用 renderer2 nextsibling(找不到教程)?设想这样的事情,但想知道我如何抓住它的兄弟姐妹...
    • 该指令将在每个孩子身上,因此它将完全自行处理。 Hostlistener 将在指令本身内。除非我遗漏了什么你为什么要获取其兄弟姐妹的参考?
    • // hostlistener scrollPosition // onscroll。如果滚动位置在 this.child.boundary 之外,则滚动到下一个兄弟
    • 你需要引用才能使用 scrollIntoView(el.reference) 对吗?
    • 是的,但是每个元素上的指令都会引用自身,您可以将文档的主机侦听器放在指令中。可以在多个区域中使用它,您也可以在子级的父级中拥有主机侦听器,然后拥有它,更新一个变量,然后使用 @Input() 将变量传递给指令,如果您更新了stackblitz 有指令我很乐意更新它并向你展示我的意思:)
    猜你喜欢
    • 2018-12-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-09
    • 2016-10-24
    • 1970-01-01
    • 2023-03-15
    • 2014-05-08
    相关资源
    最近更新 更多