Angular 实现Bootstrap ScrollSpy控件

  Bootstap是基于JQuery开发,Angular中不支持Bootstrap相关事件逻辑。本文基于Typecript开发了一个Angular可用的ScrollSpy控件。Scrollspy控件主要实现了左侧导航以及右侧正文之间的联动和切换。所以,

  此组件主要解决两个问题:

  (1)点击左侧导航列表,右侧正文能够跟随切换的焦点定位到具体的段落,即添加导航点击事件

  (2)右侧正文滚动时,左侧导航列表可以根据正文滚动的位置自动定位到,该段落所属的目录索引上。即添加正文滚动事件。

  1. 代码结构

 

1.组件代码

滚动监听指令:

  监听滚动事件,并且获取当前滚动焦点的元素值(element)然后切换当前导航树位置(postion),触发positionchange事件函数。

//scrollspy.direct.ts
import { Directive, Injectable, Input, EventEmitter, Output, ElementRef, HostListener } from '@angular/core';

@Directive({
    selector: '[NgScrollSpy]'
})
export class NgScrollSpyDirective {
   
    @Output() public positonChange = new EventEmitter<string>();
    private currentposition: string;
    private Tags = ['DIV'];

    constructor(private _el: ElementRef) {}

    @HostListener('scroll', ['$event'])  //监听正文滚动事件
    onScroll(event: any) {
        let position: string;
        const children = this._el.nativeElement.children;
        const scrollTop = event.target.scrollTop;
        const parentOffset = event.target.offsetTop;
        for (let i = 0; i < children.length; i++) {
            const element = children[i];
            if (this.Tags.some(tag => tag === element.tagName)) {
                if ((element.offsetTop - parentOffset) <= scrollTop) {
                    position = element.id;
                }
            }
        }
        if (position !== this.currentposition) {
            this.currentposition = position;
            this.positonChange.emit(this.currentposition);
        }
    }

}

  通过scrollTo(position :string)函数获取左侧导航树点击位置,并操作DOM定位到对应位置。

  通过onPositionChange(position: string)函数获取右侧正文的滚动位置。

//ngscrollspy.component.ts
import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'app-ngscrollspy',
  templateUrl: './ngscrollspy.component.html',
  styleUrls: ['./ngscrollspy.component.css']
})
export class NgscrollspyComponent implements OnInit {

  constructor() { }

  ngOnInit() {
  }

  currentPostion = 'Phase1';

  // 正文滚动事件 设置当前滚动位置,供NgScrollSpyDirective使用
  onPositionChange(position: string) {
    this.currentPostion = position;
  }

  // 导航点击事件  查找目录节点别切换到节点
  scrollTo(position :string) {
    document.querySelector('#' + position)
    .scrollIntoView();
  }
}

html

//ngscrollspy.component.html
<div class="container">
  <div class="row">
      <div class="col-xl-6 col-lg-6 col-md-6 col-sm-6">
        <h2>导航</h2>
        <div (click)="scrollTo('phase1')">段落1
          <ng-container *ngIf="currentPostion==='phase1'">++</ng-container>
        </div>
        <div (click)="scrollTo('phase2')">段落2
          <ng-container *ngIf="currentPostion==='phase2'">++</ng-container>
        </div>
        <div (click)="scrollTo('phase3')">段落3
          <ng-container *ngIf="currentPostion==='phase3'">++</ng-container>
        </div>
        <div (click)="scrollTo('phase4')">段落4
          <ng-container *ngIf="currentPostion==='phase4'">++</ng-container>
        </div>
      </div>
      <div class="col-xl-6 col-lg-6 col-md-6 col-sm-6">
        <div id="phases" NgScrollSpy (positonChange)="onPositionChange($event)" style="height:150px;overflow-y: scroll;">
          <div id="phase1">
            <h2 style="margin:0">段落 1</h2>
            <PhaseText></PhaseText>
          </div>
          <div id="phase2">
            <h1>段落 2</h1>
            <PhaseText></PhaseText>
          </div>
          <div id="phase3">
            <h1>段落 3</h1>
            <PhaseText></PhaseText>
          </div>
          <div id="phase4">
            <h1>段落 4</h1>
            <PhaseText></PhaseText>
          </div>
        </div>
      </div>
  </div>
</div>

详细代码可以访问github仓库

https://github.com/OshimaYong/AngularDemo

posted @ 2018-12-29 17:30  沉默的雪糕  阅读(482)  评论(0编辑  收藏  举报