尝试链接到当前页面内的某个部分时,不是有效的选择器错误

时间:2018-06-24 13:01:47

标签: angular routing angular2-routing anchor

我正在制作一个FAQ页面,该页面的顶部所有问题均以超链接的形式出现。当您单击超链接时,您将直接转到页面上可以阅读问题答案的部分。为此,我尝试使用Kaloyan在此处Angular2 Routing with Hashtag to page anchor提供的解决方案。 该解决方案在代码行

对我不利
  const element = document.querySelector("#" + tree.fragment);

这将显示错误ERROR DOMException: Failed to execute 'querySelector' on 'Document': '#1' is not a valid selector.。我能理解为什么会收到此错误,因为它正在寻找选择器,并且得到的输入是#fragment。但是我提到的stackoverflow线程中的每个人都说它有效,所以也许我做错了。当我用getElementById(tree.fragment)替换querySelector时,我不再遇到错误,但是当我单击任一链接时页面不会跳到该部分。有人可以告诉我我做错了什么部分,或者我错过了在提到的线程的解决方案中实现的那部分?谢谢。

这里是我的代码:

组件代码:

import { Component, OnInit } from '@angular/core';
import { FaqItem } from './faq-item.model';
import { Router, NavigationEnd } from '@angular/router';

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

  faqItems: FaqItem[] = EXAMPLE_DATA;



  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);
          // const element = document.getElementById(tree.fragment);
          if (element) { element.scrollIntoView(true); }
        }
      }
    });

  }

  ngOnInit() {
  }

}

const EXAMPLE_DATA: FaqItem[] = [
  {id: 1, question: 'How do i use the seedcalendar app?', answer: 'please check the getting started tutorial for this'},
  {id: 1, question: 'How do i use the seedcalendar app?', answer: 'please check the getting started tutorial for this'},
  {id: 1, question: 'How do i use the seedcalendar app?', answer: 'please check the getting started tutorial for this'},
  {id: 1, question: 'How do i use the seedcalendar app?', answer: 'please check the getting started tutorial for this'},
  {id: 1, question: 'How do i use the seedcalendar app?', answer: 'please check the getting started tutorial for this'},
  {id: 1, question: 'How do i use the seedcalendar app?', answer: 'please check the getting started tutorial for this'},
  {id: 1, question: 'How do i use the seedcalendar app?', answer: 'please check the getting started tutorial for this'},
  {id: 1, question: 'How do i use the seedcalendar app?', answer: 'please check the getting started tutorial for this'},
  {id: 1, question: 'How do i use the seedcalendar app?', answer: 'please check the getting started tutorial for this'},
  {id: 1, question: 'How do i use the seedcalendar app?', answer: 'please check the getting started tutorial for this'},
  {id: 1, question: 'How do i use the seedcalendar app?', answer: 'please check the getting started tutorial for this'},
  {id: 1, question: 'How do i use the seedcalendar app?', answer: 'please check the getting started tutorial for this'},
  {id: 1, question: 'How do i use the seedcalendar app?', answer: 'please check the getting started tutorial for this'},
  {id: 1, question: 'How do i use the seedcalendar app?', answer: 'please check the getting started tutorial for this'},
  {id: 1, question: 'How do i use the seedcalendar app?', answer: 'please check the getting started tutorial for this'},
  {id: 1, question: 'How do i use the seedcalendar app?', answer: 'please check the getting started tutorial for this'},
  {id: 1, question: 'How do i use the seedcalendar app?', answer: 'please check the getting started tutorial for this'},
  {id: 1, question: 'How do i use the seedcalendar app?', answer: 'please check the getting started tutorial for this'},
    {id: 1, question: 'How do i use the seedcalendar app?', answer: 'please check the getting started tutorial for this'},  {id: 1, question: 'How do i use the seedcalendar app?', answer: 'please check the getting started tutorial for this'},
    {id: 1, question: 'How do i use the seedcalendar app?', answer: 'please check the getting started tutorial for this'},
    {id: 1, question: 'How do i use the seedcalendar app?', answer: 'please check the getting started tutorial for this'},
    {id: 1, question: 'How do i use the seedcalendar app?', answer: 'please check the getting started tutorial for this'},
    {id: 1, question: 'How do i use the seedcalendar app?', answer: 'please check the getting started tutorial for this'},
    {id: 1, question: 'How do i use the seedcalendar app?', answer: 'please check the getting started tutorial for this'},
    {id: 1, question: 'How do i use the seedcalendar app?', answer: 'please check the getting started tutorial for this'},
    {id: 1, question: 'How do i use the seedcalendar app?', answer: 'please check the getting started tutorial for this'},
    {id: 1, question: 'How do i use the seedcalendar app?', answer: 'please check the getting started tutorial for this'},
    {id: 1, question: 'How do i use the seedcalendar app?', answer: 'please check the getting started tutorial for this'},
    {id: 1, question: 'How do i use the seedcalendar app?', answer: 'please check the getting started tutorial for this'},
    {id: 1, question: 'How do i use the seedcalendar app?', answer: 'please check the getting started tutorial for this'},
    {id: 1, question: 'How do i use the seedcalendar app?', answer: 'please check the getting started tutorial for this'},
    {id: 1, question: 'How do i use the seedcalendar app?', answer: 'please check the getting started tutorial for this'},
    {id: 1, question: 'How do i use the seedcalendar app?', answer: 'please check the getting started tutorial for this'},
    {id: 1, question: 'How do i use the seedcalendar app?', answer: 'please check the getting started tutorial for this'},
    {id: 1, question: 'How do i use the seedcalendar app?', answer: 'please check the getting started tutorial for this'},
    {id: 1, question: 'How do i use the seedcalendar app?', answer: 'please check the getting started tutorial for this'},
    {id: 1, question: 'How do i use the seedcalendar app?', answer: 'please check the getting started tutorial for this'},
    {id: 1, question: 'How do i use the seedcalendar app?', answer: 'please check the getting started tutorial for this'},
    {id: 1, question: 'How do i use the seedcalendar app?', answer: 'please check the getting started tutorial for this'},

    {id: 1, question: 'How do i use the seedcalendar app?', answer: 'please check the getting started tutorial for this'},
    {id: 1, question: 'How do i use the seedcalendar app?', answer: 'please check the getting started tutorial for this'},
    {id: 1, question: 'How do i use the seedcalendar app?', answer: 'please check the getting started tutorial for this'},  {id: 1, question: 'How do i use the seedcalendar app?', answer: 'please check the getting started tutorial for this'},
    {id: 1, question: 'How do i use the seedcalendar app?', answer: 'please check the getting started tutorial for this'},
    {id: 1, question: 'How do i use the seedcalendar app?', answer: 'please check the getting started tutorial for this'},
    {id: 1, question: 'How do i use the seedcalendar app?', answer: 'please check the getting started tutorial for this'},
    {id: 1, question: 'How do i use the seedcalendar app?', answer: 'please check the getting started tutorial for this'},
    {id: 1, question: 'How do i use the seedcalendar app?', answer: 'please check the getting started tutorial for this'},

]
export class FaqItem {
    id: number;
    question: string;
    answer: string;
}

HTML代码:

<section id="top">
  <ol>
    <li *ngFor="let item of faqItems; let i=index">
        <a [routerLink]="['.']" fragment={{i}}>{{item.question}}</a>
    </li>
  </ol>
<dl>
  <app-faq-item *ngFor="let item of faqItems; let i=index" 
  [question]="item.question" [answer]="item.answer" [attr.id]="i">
</app-faq-item>
</dl>
</section>

1 个答案:

答案 0 :(得分:1)

我了解使用fragment进行锚定链接的方式(可能是错误的)是在路线之间导航时会使用它们,并且您希望在导航到该页面后将用户带到页面上的某个点

您的问题似乎表明您希望单击页面上的链接并将用户滚动到相应部分。

如果这是正确的,则可以使用@ViewChildren


添加templateRef(#answers):

<app-faq-item #answers *ngFor="let item of faqItems; let i=index" [...] [...]>

和一个问题的点击处理程序:

<a href="javascript:;" (click)="scrollTo(i)">{{item.question}}</a>

在您的组件中,使用ViewChildren获取当前元素:

export class FaqComponent implements OnInit {

  faqItems: FaqItem[] = EXAMPLE_DATA;
  @ViewChildren('answers', { read: ViewContainerRef }) answers;

  scrollTo(index: number) {
    const element = this.answers.toArray()[index].element.nativeElement;
    element.scrollIntoView({
      behavior:"smooth",
      block: "start", 
      inline: "nearest"
    });
  }

这里是Demo