In page link reloads page

吃可爱长大的小学妹 提交于 2020-01-03 04:32:09

问题


I'm building my first Angular 2 app and I've come quite far now with a nice Webpack build system, routing, services and components in place.

I tried adding a normal in page link ([href^="#"]) in one of my components, and as long as I'm on the home page (/) it works fine, but whenever I'm on a different URL the whole app reloads to the home page.

Apparently this is a known issue (https://github.com/angular/angular/issues/6595) but I need this to work right now so I'm hoping someone can teach me how.

I'm not sure it'll help, but here's my Component's TS and 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>

As you can see it's the link "here's how it works" (or any other in page link - I have more than this one in reality) that only works (scrolls down to the linked element) when you're on the home page (/). If on any other URL, the link will reload the app.


回答1:


Unfortunately, I've also learnt the hard way trying to develop a real-world app with angular2 before its release that you really should stay as far away from the current development as possible, especially in terms of the router(s).

The third iteration of the router is currently extremely alpha and I've run across so many issues that I've had to revert its implementation which as you likely know is quite a bit of work as the API has changed considerably.

As far as your issue is concerned though, I haven't actually found that any of the routers actually implement hashes correctly and I've had to get around this with a scroll component that looks something like the below:

@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);
          }
      });
    }
  }
}

You can then add this directive to an element on the given page.

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

I hope this helps you solve your issue for the time being!




回答2:


In the current release of the router - version 3.0.0-alpha.8 - there is a way to add hash fragments to your links. However, the angular team still has some work to do to make it function properly.

On your anchor element, add a fragment attribute with the hash value.

If you want to generate a local link, just use this notation:

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

If you were at the location

www.example.org/Comp1/Comp2

before, this will change the URL to

www.example.org/Comp1/Comp2#Test

This will also work when linking to another component:

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

which will take you to

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

However...

There still seems to be a bug in angular's implementation. Although the link is generated and updated correctly in the address bar of the browser, the browser does not jump to the specified hash location. It only does that, when you move your cursor into the address bar and hit enter, which obviously does not help.

I commented again on the github post referenced by @powerbuoy and @Günter-Zöchbauer to give the Angular team a heads up on the issue.




回答3:


In case you don't want to modify anything: PLUNKER DEMO

Just put this Directive in your Component, and you're done.

@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
  }
}



回答4:


https://github.com/angular/angular/issues/6595 was fixed recently and will be included in the next release (probably today)



来源:https://stackoverflow.com/questions/38030108/in-page-link-reloads-page

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!