Định tuyến Angular2 với Hashtag đến liên kết trang


120

Tôi muốn thêm một số liên kết trên trang Angular2 của mình, mà khi nhấp vào, nó sẽ chuyển đến các vị trí cụ thể trong trang đó, giống như những gì thẻ bắt đầu bằng # thông thường làm. Vì vậy, các liên kết sẽ giống như

/users/123#userInfo
/users/123#userPhoto
/users/123#userLikes

Vân vân.

Tôi không nghĩ mình cần HashLocationStrategy, vì tôi thấy ổn với cách Angular2 thông thường, nhưng nếu tôi thêm trực tiếp, liên kết sẽ thực sự chuyển đến thư mục gốc, không phải ở đâu đó trên cùng một trang. Bất kỳ hướng nào được đánh giá cao, cảm ơn.

Câu trả lời:


130

Cập nhật

Điều này hiện đã được hỗ trợ

<a [routerLink]="['somepath']" fragment="Test">Jump to 'Test' anchor </a>
this._router.navigate( ['/somepath', id ], {fragment: 'test'});

Thêm mã Bên dưới vào thành phần của bạn để cuộn

  import {ActivatedRoute} from '@angular/router'; // <-- do not forget to import

  private fragment: string;

  constructor(private route: ActivatedRoute) { }

  ngOnInit() {
    this.route.fragment.subscribe(fragment => { this.fragment = fragment; });
  }

  ngAfterViewInit(): void {
    try {
      document.querySelector('#' + this.fragment).scrollIntoView();
    } catch (e) { }
  }

Nguyên

Đây là sự cố đã biết và được theo dõi tại https://github.com/angular/angular/issues/6595


1
@invot một biến với một chuỗi (ví dụ những gì 123là trong câu hỏi) giả định rằng con đường con đường hy vọng một tham số như{ path: 'users/:id', ....}
Günter Zöchbauer

2
Nếu bạn muốn di chuyển đến neo xem bài này: github.com/angular/angular/issues/6595
Pere Trang

12
Lưu ý: điều này vẫn không cuộn
Martín Coll

2
vâng nó hoạt động với setTimeout, nếu tôi tìm thấy giải pháp tốt hơn tôi sẽ cho bạn biết
Amr Ibrahim

1
Đối với những người đang vật lộn để cuộn đến các id giống số, hãy nhớ, đó là 01hoặc 100không phải là bộ chọn CSS hợp lệ. Bạn có thể muốn thêm một chữ cái hoặc một cái gì đó để biến nó thành một bộ chọn hợp lệ. Vì vậy, bạn sẽ vẫn vượt qua 01dưới dạng một mảnh, nhưng idcần phải là một cái gì đó giống như d01vậy và do đó document.querySelector('#d'+id)sẽ phù hợp.
pop

52

Mặc dù câu trả lời của Günter là đúng, nhưng nó không bao gồm phần "nhảy tới" phần thẻ neo .

Do đó, bổ sung để:

<a [routerLink]="['somepath']" fragment="Test">Jump to 'Test' anchor </a>
this._router.navigate( ['/somepath', id ], {fragment: 'test'});

... trong thành phần (cha) nơi bạn cần hành vi "nhảy tới", hãy thêm:

import { Router, NavigationEnd } from '@angular/router';

class MyAppComponent {
  constructor(router: Router) {

    router.events.subscribe(s => {
      if (s instanceof NavigationEnd) {
        const tree = router.parseUrl(router.url);
        if (tree.fragment) {
          const element = document.querySelector("#" + tree.fragment);
          if (element) { element.scrollIntoView(true); }
        }
      }
    });

  }
}

Xin lưu ý rằng đây là một cách giải quyết ! Theo dõi vấn đề github này để cập nhật trong tương lai. Tín dụng cho Victor Savkin vì đã cung cấp giải pháp!


xin chào, tôi đang tạo một trang Câu hỏi thường gặp, nơi bạn có thể chuyển đến câu trả lời bằng cách nhấp vào một câu hỏi được xác định trong danh sách ở đầu trang. Vì vậy, người dùng đã ở trên trang hiện tại khi anh ta chuyển đến anchor. Nếu tôi muốn thuộc tính routerLink hoạt động, tôi phải cung cấp "['../faq']"giá trị này, nếu không nó sẽ cố gắng chuyển đến / faq / faq / # anchor, insteaf of / faq / # anchor. Đây có phải là cách chính xác để thực hiện hay có cách nào thanh lịch hơn để tham khảo trang hiện tại trong liên kết bộ định tuyến? Ngoài ra, document.querySelector("#" + tree.fragment);cung cấp cho tôi một lỗi bộ chọn không hợp lệ. Bạn có chắc chắn điều này là đúng Cảm ơn bạn?
Maurice

2
khi bạn nhấp lại vào cùng một liên kết, nó không hoạt động. Có ai làm cho điều này thành công nếu người dùng nhấp vào cùng một liên kết neo <a [routerLink]="['/faq']" fragment="section6">không?
Junior Mayhé

@JuniorM Bạn đã bao giờ hiểu ra điều này chưa? Tôi đang gặp phải vấn đề tương tự.
The Muffin Man

@Muffin, hãy thử một cái gì đó tương tự như thế này github.com/juniormayhe/Mailing/blob/master/Mailing.SPA/src/app/…
Junior Mayhé

1
Điều này cần tiếp xúc nhiều hơn. Đây là một câu trả lời tốt hơn IMO. Hầu hết mọi người sẽ muốn chuyển đến phần này.
iamtravisw 14/09/19

44

Xin lỗi vì đã trả lời hơi muộn; Có một chức năng được xác định trước trong Tài liệu Định tuyến Angular giúp chúng tôi định tuyến bằng thẻ bắt đầu bằng # đến trang neo, tức là anchorScrolling: 'đã bật'

Bước 1: - Đầu tiên nhập RouterModule vào tệp app.module.ts: -

imports:[ 
    BrowserModule, 
    FormsModule,
    RouterModule.forRoot(routes,{
      anchorScrolling: 'enabled'
    })
  ],

Bước 2: - Truy cập Trang HTML, Tạo điều hướng và thêm hai thuộc tính quan trọng như [routerLink]phân mảnh để khớp với Div ID tương ứng : -

<ul>
    <li> <a [routerLink] = "['/']"  fragment="home"> Home </a></li>
    <li> <a [routerLink] = "['/']"  fragment="about"> About Us </a></li>
  <li> <a [routerLink] = "['/']"  fragment="contact"> Contact Us </a></li>
</ul>

Bước 3: - Tạo một phần / div bằng cách khớp tên ID với phân đoạn : -

<section id="home" class="home-section">
      <h2>  HOME SECTION </h2>
</section>

<section id="about" class="about-section">
        <h2>  ABOUT US SECTION </h2>
</section>

<section id="contact" class="contact-section">
        <h2>  CONTACT US SECTION </h2>
</section>

Để bạn tham khảo, tôi đã thêm ví dụ bên dưới bằng cách tạo một bản demo nhỏ giúp giải quyết vấn đề của bạn.

Demo: https://routing-hashtag-page-anchors.stackblitz.io/


Cảm ơn rất nhiều vì điều này. Sạch sẽ, ngắn gọn và nó hoạt động!
Belmiris,

2
Vâng, Cảm ơn, để tự động scoll trên tải trang với góc 7, chỉ cần có để thêm scrollPositionRestoration: 'enabled',theo phương án anchorScrolling :)
Mickaël

Điều này nối băm vào cuối url của tôi đúng cách, nhưng nó không liên kết với div có cùng tên. Tôi không chắc mình đang thiếu gì. Tôi đã làm theo ba bước trên.
oaklandrichie

@oaklandrichie: Bạn có thể chia sẻ mã jsfiddle / stackblitz ở đây không. Tôi có thể giúp bạn ra
Naheed Shareef

câu trả lời này chắc chắn nên được chấp nhận, hoạt động như sự quyến rũ!
Kiss Koppány

25

Hơi muộn nhưng đây là một câu trả lời mà tôi thấy có hiệu quả:

<a [routerLink]="['/path']" fragment="test" (click)="onAnchorClick()">Anchor</a>

Và trong thành phần:

constructor( private route: ActivatedRoute, private router: Router ) {}

  onAnchorClick ( ) {
    this.route.fragment.subscribe ( f => {
      const element = document.querySelector ( "#" + f )
      if ( element ) element.scrollIntoView ( element )
    });
  }

Ở trên không tự động cuộn đến chế độ xem nếu bạn truy cập vào một trang đã có neo, vì vậy tôi đã sử dụng giải pháp ở trên trong ngInit của mình để nó cũng có thể hoạt động với điều đó:

ngOnInit() {
    this.router.events.subscribe(s => {
      if (s instanceof NavigationEnd) {
        const tree = this.router.parseUrl(this.router.url);
        if (tree.fragment) {
          const element = document.querySelector("#" + tree.fragment);
          if (element) { element.scrollIntoView(element); }
        }
      }
    });
  }

Đảm bảo nhập Bộ định tuyến, ActivateRoute và NavigationEnd vào đầu thành phần của bạn và tất cả đều tốt.

Nguồn


4
Làm việc cho tôi! Trong trường hợp bạn muốn điều hướng trong cùng một trang mà bạn đã truy cập, hãy sử dụng [routerLink] = "['.']"
Raoul

1
bạn có thể giải thích thêm? phần này document.querySelector ( "#" + f )cho tôi một lỗi vì nó mong đợi một bộ chọn, không phải một chuỗi.
Maurice

1
@Maurice cho tôi cái này hoạt động: element.scrollIntoView()(mà không cần chuyển elementđến hàm). Để làm cho nó mịn, sử dụng này: element.scrollIntoView({block: "end", behavior: "smooth"}).
Ông B.

Intellisense đây cho thấy trong vòng onAnchorClick(), chúng ta phải vượt qua một boolean để scrollIntoView: if (element) { element.scrollIntoView(true); }. Bây giờ tôi có thể nhấp hai lần vào cùng một liên kết và cuộn các tác phẩm
Junior Mayhé

18

Không có câu trả lời nào trước đây phù hợp với tôi. Trong một nỗ lực cuối cùng, tôi đã thử trong mẫu của mình:

<a (click)="onClick()">From Here</a>
<div id='foobar'>To Here</div>

Với điều này trong .ts của tôi:

onClick(){
    let x = document.querySelector("#foobar");
    if (x){
        x.scrollIntoView();
    }
}

Và nó hoạt động như mong đợi đối với các liên kết nội bộ. Điều này thực sự không sử dụng thẻ liên kết nên nó sẽ không chạm vào URL.


1
đơn giản và dễ dàng
Wasif

6

Các giải pháp ở trên không hiệu quả với tôi ... Giải pháp này đã làm được điều đó:

Đầu tiên, chuẩn bị MyAppComponentcho việc cuộn tự động trong ngAfterViewChecked () ...

import { Component, OnInit, AfterViewChecked } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { Subscription } from 'rxjs';

@Component( {
   [...]
} )
export class MyAppComponent implements OnInit, AfterViewChecked {

  private scrollExecuted: boolean = false;

  constructor( private activatedRoute: ActivatedRoute ) {}

  ngAfterViewChecked() {

    if ( !this.scrollExecuted ) {
      let routeFragmentSubscription: Subscription;

      // Automatic scroll
      routeFragmentSubscription =
        this.activatedRoute.fragment
          .subscribe( fragment => {
            if ( fragment ) {
              let element = document.getElementById( fragment );
              if ( element ) {
                element.scrollIntoView();

                this.scrollExecuted = true;

                // Free resources
                setTimeout(
                  () => {
                    console.log( 'routeFragmentSubscription unsubscribe' );
                    routeFragmentSubscription.unsubscribe();
                }, 1000 );

              }
            }
          } );
    }

  }

}

Sau đó, điều hướng đến my-app-routegửi prodIDthẻ bắt đầu bằng #

import { Component } from '@angular/core';
import { Router } from '@angular/router';

@Component( {
   [...]
} )
export class MyOtherComponent {

  constructor( private router: Router ) {}

  gotoHashtag( prodID: string ) {
    this.router.navigate( [ '/my-app-route' ], { fragment: prodID } );
  }

}

Xuống bỏ phiếu mà không bình luận hoặc giải thích ... nó không phải là một thực hành tốt ...
JavierFuentes

Điều này đã làm việc cho tôi! Tại sao lại sử dụng ngAfterViewChecked thay vì ngInit?
Antoine Boisier-Michaud

Cảm ơn @ AntoineBoisier-Michaud đã phản hồi tích cực. ngInit không phải lúc nào cũng kích hoạt mà tôi cần trong dự án của mình ... ngAfterViewChecked thực hiện được. Bạn có thể ủng hộ giải pháp này được không? Cảm ơn.
JavierFuentes

6

Tất cả các câu trả lời khác sẽ hoạt động trên phiên bản Angular <6.1. Nhưng nếu bạn có phiên bản mới nhất thì bạn sẽ không cần phải thực hiện những thao tác hack xấu xí này vì Angular đã khắc phục sự cố.

đây là liên kết đến vấn đề

Tất cả những gì bạn cần làm là đặt scrollOffsettùy chọn của đối số thứ hai của RouterModule.forRootphương thức.

@NgModule({
  imports: [
    RouterModule.forRoot(routes, {
      scrollPositionRestoration: 'enabled',
      anchorScrolling: 'enabled',
      scrollOffset: [0, 64] // [x, y]
    })
  ],
  exports: [RouterModule]
})
export class AppRoutingModule {}

2
điều này sẽ hoạt động cho các liên kết bên ngoài? nói từ một trang web khác, tôi nhấp vào www.abc.com # sectionToScrollTo
Sushmit Sagar

anchorScrolling không hoạt động, nếu bạn thực hiện sử dụng rộng rãi * ngIf, vì nó nhảy đến đầu :-(
Jojo.Lechelt

Vấn đề duy nhất mà tôi gặp phải với điều này là thời gian - nó có xu hướng nhảy đến mỏ neo trước khi kiểu dáng của phần tử nào đó hiển thị đầy đủ, khiến vị trí bị tắt. Sẽ rất tốt nếu bạn có thể thêm một thời gian trễ :)
Charly

5

Sử dụng cái này cho mô-đun bộ định tuyến trong app-routing.module.ts:

@NgModule({
  imports: [RouterModule.forRoot(routes, {
    useHash: true,
    scrollPositionRestoration: 'enabled',
    anchorScrolling: 'enabled',
    scrollOffset: [0, 64]
  })],
  exports: [RouterModule]
})

Điều này sẽ có trong HTML của bạn:

<a href="#/users/123#userInfo">

4

Trong tệp html:

<a [fragment]="test1" [routerLink]="['./']">Go to Test 1 section</a>

<section id="test1">...</section>
<section id="test2">...</section>

Trong tệp ts:

export class PageComponent implements AfterViewInit, OnDestroy {

  private destroy$$ = new Subject();
  private fragment$$ = new BehaviorSubject<string | null>(null);
  private fragment$ = this.fragment$$.asObservable();

  constructor(private route: ActivatedRoute) {
    this.route.fragment.pipe(takeUntil(this.destroy$$)).subscribe(fragment => {
      this.fragment$$.next(fragment);
    });
  }

  public ngAfterViewInit(): void {
    this.fragment$.pipe(takeUntil(this.destroy$$)).subscribe(fragment => {
      if (!!fragment) {
        document.querySelector('#' + fragment).scrollIntoView();
      }
    });
  }

  public ngOnDestroy(): void {
    this.destroy$$.next();
    this.destroy$$.complete();
  }
}

Có thể dễ dàng đưa querySelector vào một chỉ thị có tên là scrolllTo. Url sẽ là <a scrollTo="test1" [routerLink]="['./']"> Chuyển đến phần Kiểm tra 1 </a>
John Peters

3

Vì thuộc tính phân mảnh vẫn không cung cấp cuộn neo, nên giải pháp này đã giải quyết vấn đề cho tôi:

<div [routerLink]="['somepath']" fragment="Test">
  <a href="#Test">Jump to 'Test' anchor </a>
</div>

3

Thêm vào câu trả lời của Kalyoyan , đăng ký này được gắn với bộ định tuyến và sẽ tồn tại cho đến khi trang được làm mới hoàn toàn. Khi đăng ký các sự kiện bộ định tuyến trong một thành phần, hãy nhớ hủy đăng ký trong ngOnDestroy:

import { OnDestroy } from '@angular/core';
import { Router, NavigationEnd } from '@angular/router';
import { Subscription } from "rxjs/Rx";

class MyAppComponent implements OnDestroy {

  private subscription: Subscription;

  constructor(router: Router) {
    this.subscription = router.events.subscribe(s => {
      if (s instanceof NavigationEnd) {
        const tree = router.parseUrl(router.url);
        if (tree.fragment) {
          const element = document.querySelector("#" + tree.fragment);
          if (element) { element.scrollIntoView(element); }
        }
      }
    });
  }

  public ngOnDestroy() {
    this.subscription.unsubscribe();
  }
}

Tôi nghĩ rằng đăng ký cho các sự kiện tuyến đường đã tự động bị chia nhỏ.

3

Tôi vừa nhận được giải pháp này hoạt động trên trang web của riêng mình, vì vậy tôi nghĩ rằng nó sẽ đáng để đăng giải pháp của tôi ở đây.

<a [routerLink]="baseUrlGoesHere" fragment="nameOfYourAnchorGoesHere">Link Text!</a>

<a name="nameOfYourAnchorGoesHere"></a>
<div>They're trying to anchor to me!</div>

Và sau đó trong thành phần của bạn, hãy đảm bảo bạn bao gồm điều này:

 import { ActivatedRoute } from '@angular/router';

 constructor(private route: ActivatedRoute) { 
     this.route.fragment.subscribe ( f => {
         const element = document.querySelector ( "#" + f )
         if ( element ) element.scrollIntoView ( element )
     });
 }

Tôi nghĩ rằng tốt hơn là viết chỉ element.scrollIntoView()hoặc element.scrollIntoView(true). Phiên bản của bạn đã không biên dịch cho tôi (có thể do nghiêm ngặtNullChecks?).
David L.

3

Sau khi đọc tất cả các giải pháp, tôi tìm kiếm một thành phần và tôi đã tìm thấy một thành phần thực hiện chính xác những gì câu hỏi ban đầu yêu cầu: cuộn đến liên kết neo. https://www.npmjs.com/package/ng2-scroll-to

Khi bạn cài đặt nó, bạn sử dụng cú pháp như:

// app.awesome.component.ts
@Component({
   ...
   template: `...
        <a scrollTo href="#main-section">Scroll to main section</a>
        <button scrollTo scrollTargetSelector="#test-section">Scroll to test section</a>
        <button scrollTo scrollableElementSelector="#container" scrollYTarget="0">Go top</a>
        <!-- Further content here -->
        <div id="container">
            <section id="main-section">Bla bla bla</section>
            <section id="test-section">Bla bla bla</section>
        <div>
   ...`,
})
export class AwesomeComponent {
}

Nó đã làm việc thực sự tốt cho tôi.


Sử dụng bánh xe, không phát minh ra nó một lần nữa;)
Yogen Rai

Bạn đã xem mã đằng sau thành phần đó chưa? Nó trông rất mong manh - dự án cũng có 14 vấn đề mở - bao gồm những thứ như phần tử không tồn tại, nhắm mục tiêu rỗng, không cuộn đến phần tử, các vấn đề hỗ trợ trình duyệt.
Drenai

không hoạt động khi bạn có con (con có các thực thể cố định và / hoặc tên liên kết) trong thành phần mẹ, nó chỉ làm mới trang
Sasha Bond

3

Một giải pháp đơn giản phù hợp với các trang không có bất kỳ tham số truy vấn nào, đó là trình duyệt quay lại / chuyển tiếp, bộ định tuyến và liên kết sâu.

<a (click)="jumpToId('anchor1')">Go To Anchor 1</a>


ngOnInit() {

    // If your page is dynamic
    this.yourService.getWhatever()
        .then(
            data => {
            this.componentData = data;
            setTimeout(() => this.jumpToId( window.location.hash.substr(1) ), 100);
        }
    );

    // If your page is static
    // this.jumpToId( window.location.hash.substr(1) )
}

jumpToId( fragment ) {

    // Use the browser to navigate
    window.location.hash = fragment;

    // But also scroll when routing / deep-linking to dynamic page
    // or re-clicking same anchor
    if (fragment) {
        const element = document.querySelector('#' + fragment);
        if (element) element.scrollIntoView();
    }
}

Thời gian chờ chỉ đơn giản là để cho phép trang tải bất kỳ dữ liệu động nào được "bảo vệ" bởi * ngIf. Điều này cũng có thể được sử dụng để cuộn lên đầu trang khi thay đổi tuyến đường - chỉ cần cung cấp một thẻ neo trên cùng mặc định.


2

nếu việc thêm các id phần tử đó vào url không thành vấn đề, bạn nên xem xét liên kết này:

Angular 2 - Liên kết cố định đến phần tử trên trang hiện tại

// html
// add (click) event on element
<a (click)="scroll({{any-element-id}})">Scroll</a>

// in ts file, do this
scroll(sectionId) {
let element = document.getElementById(sectionId);

  if(element) {
    element.scrollIntoView(); // scroll to a particular element
  }
 }


1

Đây là một giải pháp khác với việc tham khảo câu trả lời của JavierFuentes:

<a [routerLink]="['self-route', id]" fragment="some-element" (click)="gotoHashtag('some-element')">Jump to Element</a>

trong kịch bản:

import {ActivatedRoute} from "@angular/router";
import {Subscription} from "rxjs/Subscription";

export class Links {
    private scrollExecuted: boolean = false;

    constructor(private route: ActivatedRoute) {} 

    ngAfterViewChecked() {
            if (!this.scrollExecuted) {
              let routeFragmentSubscription: Subscription;
              routeFragmentSubscription = this.route.fragment.subscribe(fragment => {
                if (fragment) {
                  let element = document.getElementById(fragment);
                  if (element) {
                    element.scrollIntoView();
                    this.scrollExecuted = true;
                    // Free resources
                    setTimeout(
                      () => {
                        console.log('routeFragmentSubscription unsubscribe');
                        routeFragmentSubscription.unsubscribe();
                      }, 0);
                  }
                }
              });
            }
          }

        gotoHashtag(fragment: string) {
            const element = document.querySelector("#" + fragment);
            if (element) element.scrollIntoView(element);
        }
}

Điều này cho phép người dùng cuộn trực tiếp đến phần tử, nếu người dùng trực tiếp đến trang có thẻ bắt đầu bằng # trong url.

Nhưng trong trường hợp này, tôi đã đăng ký Fragment tuyến đường trong ngAfterViewCheckednhưng ngAfterViewChecked()được gọi liên tục mỗi lần ngDoCheckvà nó không cho phép người dùng cuộn trở lại đầu trang, vì vậy routeFragmentSubscription.unsubscribeđược gọi sau khoảng thời gian chờ 0 mili sau khi chế độ xem được cuộn đến phần tử.

Ngoài ra, gotoHashtagphương pháp được xác định để cuộn đến phần tử khi người dùng nhấp cụ thể vào thẻ liên kết.

Cập nhật:

Nếu url có chuỗi truy vấn, [routerLink]="['self-route', id]"trong neo sẽ không bảo toàn các chuỗi truy vấn. Tôi đã thử làm theo cách giải quyết tương tự:

<a (click)="gotoHashtag('some-element')">Jump to Element</a>

constructor( private route: ActivatedRoute,
              private _router:Router) {
}
...
...

gotoHashtag(fragment: string) {
    let url = '';
    let urlWithSegments = this._router.url.split('#');

    if(urlWithSegments.length){
      url = urlWithSegments[0];
    }

    window.location.hash = fragment;
    const element = document.querySelector("#" + fragment);
    if (element) element.scrollIntoView(element);
}

1

Cái này làm việc cho tôi !! Đối với thẻ liên kết động này, bạn cần đợi chúng hiển thị

HTML:

<div #ngForComments *ngFor="let cm of Comments">
    <a id="Comment_{{cm.id}}" fragment="Comment_{{cm.id}}" (click)="jumpToId()">{{cm.namae}} Reply</a> Blah Blah
</div>

Tệp ts của tôi:

private fragment: string;
@ViewChildren('ngForComments') AnchorComments: QueryList<any>;

ngOnInit() {
      this.route.fragment.subscribe(fragment => { this.fragment = fragment; 
   });
}
ngAfterViewInit() {
    this.AnchorComments.changes.subscribe(t => {
      this.ngForRendred();
    })
}

ngForRendred() {
    this.jumpToId()
}

jumpToId() { 
    let x = document.querySelector("#" + this.fragment);
    console.log(x)
    if (x){
        x.scrollIntoView();
    }
}

Đừng quên nhập cái đó ViewChildren, QueryListv.v. và thêm một số hàm tạo ActivatedRoute!!


1

Không giống như câu trả lời khác tôi muốn bổ sung thêm cũng focus()cùng với scrollIntoView(). Ngoài ra, tôi đang sử dụng setTimeoutvì nó nhảy lên đầu khi thay đổi URL. Không chắc lý do cho điều đó là gì nhưng có vẻ như đây setTimeoutlà cách giải quyết.

Gốc:

<a [routerLink] fragment="some-id" (click)="scrollIntoView('some-id')">Jump</a>

Nơi Đến:

<a id="some-id" tabindex="-1"></a>

Chữ viết:

scrollIntoView(anchorHash) {
    setTimeout(() => {
        const anchor = document.getElementById(anchorHash);
        if (anchor) {
            anchor.focus();
            anchor.scrollIntoView();
        }
    });
}

1

Tôi gặp vấn đề tương tự. Giải pháp: sử dụng View port Scroller https://angular.io/api/common/ViewportScroller#scrolltoanchor

- mã app-routing.module.ts:

import { PageComponent } from './page/page.component';

const routes: Routes = [
   path: 'page', component: PageComponent },
   path: 'page/:id', component: PageComponent }
];

- HTML thành phần

  <a (click) = "scrollTo('typeExec')">
    <mat-icon>lens</mat-icon>
  </a>

- Mã của thành phần:

    import { Component } from '@angular/core';
    import { ViewportScroller } from '@angular/common';


    export class ParametrageComponent {

      constructor(private viewScroller: ViewportScroller) {}

      scrollTo(tag : string)
      {
        this.viewScroller.scrollToAnchor(tag);
      }

    }

0

Tôi vừa thử nghiệm plugin rất hữu ích có sẵn trong nmp - ngx-scroll-to , rất phù hợp với tôi. Tuy nhiên nó được thiết kế cho Angular 4+, nhưng có thể ai đó sẽ thấy câu trả lời này hữu ích.


0

Tôi đã thử hầu hết các giải pháp này nhưng gặp sự cố khi rời đi và quay lại với một phân đoạn khác, nó sẽ không hoạt động, vì vậy tôi đã làm một điều gì đó khác một chút để hoạt động 100% và loại bỏ hàm băm xấu xí trong URL.

tl; dr đây là một cách tốt hơn những gì tôi đã thấy cho đến nay.

import { Component, OnInit, AfterViewChecked, OnDestroy } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { Subscription } from 'rxjs/Subscription';

@Component({
    selector: 'app-hero',
    templateUrl: './hero.component.html',
    styleUrls: ['./hero.component.scss']
})
export class HeroComponent implements OnInit, AfterViewChecked, OnDestroy {
    private fragment: string;
    fragSub: Subscription;

    constructor(private route: ActivatedRoute) { }

    ngOnInit() {
        this.fragSub = this.route.fragment.subscribe( fragment => { this.fragment = fragment; })
    }

    ngAfterViewChecked(): void {
        try {
            document.querySelector('#' + this.fragment).scrollIntoView({behavior: 'smooth'});
            window.location.hash = "";
          } catch (e) { }
    }

    ngOnDestroy() {
        this.fragSub.unsubscribe();
    }
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.