【问题标题】:In page link reloads page在页面链接重新加载页面
【发布时间】:2016-10-28 01:25:59
【问题描述】:

我正在构建我的第一个 Angular 2 应用程序,现在我已经有了一个不错的 Webpack 构建系统、路由、服务和组件。

我尝试在我的一个组件中添加一个正常的页面链接 ([href^="#"]),只要我在主页 (/) 上它就可以正常工作,但是每当我在不同的整个应用重新加载到主页的 URL。

显然这是一个已知问题 (https://github.com/angular/angular/issues/6595),但我现在需要它来工作,所以我希望有人能教我如何操作。

我不确定它是否有帮助,但这是我的组件的 TS 和 HTML:

import { Component } from '@angular/core';
import { ROUTER_DIRECTIVES } from '@angular/router-deprecated';

@Component({
    selector: 'home',
    template: require('./home.component.html'),
    directives: [ROUTER_DIRECTIVES]
})
export class HomeComponent {

}

<section id="home" class="section section--full-height">

    <h2>Title of the home page</h2>

    <nav>
        <a [routerLink]="['Search']" class="button button--wide">Search</a>
        <a [routerLink]="['Search']">Quick try</a>
    </nav>

    <footer>
        <a href="#home-2" class="icon-down icon--below">Heres how it works</a>
    </footer>

</section>

<section id="home-2" class="section section--full-height">

    <h2>Lorem ipsum dolor</h2>

    <img src="http://placehold.it/200x300">

</section>

如您所见,只有当您在主页 (/)。如果在任何其他 URL 上,该链接将重新加载应用程序。

【问题讨论】:

  • 您可以发布您正在使用的 url 或您为此编写的 JavaScript 的 sn-p 吗?
  • @AlvaroJoao 不确定它是否会有所帮助,但已经完成

标签: javascript html angular routing


【解决方案1】:

https://github.com/angular/angular/issues/6595 最近已修复,将包含在下一个版本中(可能是今天)

【讨论】:

    【解决方案2】:

    不幸的是,在 angular2 发布之前,我也学到了尝试使用 angular2 开发真实应用程序的艰难方法,你真的应该尽可能远离当前的开发,尤其是在路由器方面.

    路由器的第三次迭代目前非常 alpha,我遇到了很多问题,我不得不恢复它的实现,正如你可能知道的那样,由于 API 发生了很大变化,这需要做很多工作。

    就您的问题而言,我实际上并没有发现任何路由器实际上正确实现了哈希,我不得不使用如下所示的滚动组件来解决这个问题:

    @Directive({
      selector: '[scroll-to-target-on-event]'
    })
    export class ScrollToTargetOnEventDirective {
    
      @Input('scroll-to-target-on-event') configs:Array<{target:Element, event:string}>;
    
      constructor(private _element:ElementRef) {
      }
    
      ngOnInit() {
    
        for (let config of this.configs) {
          this._element.nativeElement.addEventListener(config.event, () => {
              // Get the position of the target relative to the entire page. getBoundingClientRect is relative to the
              // viewport so to get relative to the entire page we subtract the body (as we're looking to use scrollpos)
              var targetYPos = config.target.getBoundingClientRect().top - document.body.getBoundingClientRect().top;
    
              // If the target position is below the bottom of the viewport then scroll to it. (This should actually
              // check above as well, haven't implemented it though)
              if (targetYPos > (document.documentElement.scrollTop || document.body.scrollTop) + (document.documentElement.clientHeight|| window.innerHeight)) {
                window.scrollTo(0, config.target.getBoundingClientRect().top - document.body.getBoundingClientRect().top);
              }
          });
        }
      }
    }
    

    然后您可以将此指令添加到给定页面上的元素。

    <a href="" [scroll-to-target-on-event]="[{target: '#id-of-target-element', event:'click'}]">Link</a>
    

    我希望这可以帮助您暂时解决您的问题!

    【讨论】:

    • 谢谢。然而,滚动到元素实际上只是我想要实现的一半。自从 :target 来到 CSS 之后,我就用它来切换从滑出菜单到弹出窗口的任何内容的可见性。希望他们能解决这个问题以便发布。我现在实际上切换到 Aurelia。它的路由器至少可以工作。我仍然不能使用 :target ,因为 pushState 和 :target 没有重新渲染的 webkit 错误。我会为你提供解决一半问题的方法而表扬你。
    • 干杯!已经引入的众多路由器有点像过山车。我还得去看看 Aurelia。
    【解决方案3】:

    如果您不想修改任何内容:PLUNKER DEMO

    只需将此指令放入您的组件中,就完成了。

    @Directive({
      selector: 'a[href^=#]',
      inputs: ['href'],
      host: {
        "(click)": "linkClicked($event)"
      }
    })
    export class InPageLinks {
      href: string;
    
      linkClicked(e){ // handles click event, only prevents the links with a # in the beginning
    
          e.preventDefault();
          this.scrollToID(this.href);
      }
    
      scrollToID(id){ // scrolls to the given id
        let target = document.querySelector(id);
    
        document.body.scrollTop = target.offsetTop;  
        // current scroll-target is body, you can take another input if you want
      }
    }
    

    【讨论】:

    • 它可以工作,但我需要元素顶部与窗口顶部对齐。为此,我使用 target.scrollIntoView();
    【解决方案4】:

    在路由器的当前版本 - 版本3.0.0-alpha.8 - 有一种方法可以将哈希片段添加到您的链接。但是,Angular 团队仍然需要做一些工作才能使其正常运行。

    在您的锚元素上,添加带有哈希值的fragment 属性。

    如果要生成本地链接,只需使用此表示法:

    <a [routerLink]="['./']" fragment="Test">Jump to 'Test' anchor </a>
    

    如果你在那个位置

    www.example.org/Comp1/Comp2
    

    之前,这会将 URL 更改为

    www.example.org/Comp1/Comp2#Test
    

    这也适用于链接到另一个组件时:

    <a [routerLink]="['Comp3']" fragment="Test">Jump to 'Test' anchor </a>
    

    它会带你去

    www.example.org/Comp1/Comp2/Comp3#Test
    

    但是……

    在 Angular 的实现中似乎仍然存在错误。尽管在浏览器的地址栏中正确生成和更新了链接,但浏览器并没有跳转到指定的哈希位置。只有当您将光标移动到地址栏并按回车时,它才会这样做,这显然没有帮助。

    我再次评论了 @powerbuoy 和 @Günter-Zöchbauer 引用的 github 帖子,以便让 Angular 团队提前了解这个问题。

    【讨论】:

    • 谢谢,这看起来像我所追求的,除了它不能按应有的方式工作:P 我假设在 CSS 中使用 :target 也不起作用?不过,我已经把功劳归功于伊恩。
    • 我知道,对吧?是的,这对我来说绝对没问题。他给了你一个行之有效的解决方案,所以他值得称赞:)
    最近更新 更多