【问题标题】:How to Update a Component without refreshing full page - Angular如何在不刷新整页的情况下更新组件 - Angular
【发布时间】:2018-02-13 07:54:23
【问题描述】:

我的页面结构是:

<app-header></app-header>
<router-outlet></router-outlet>
<app-footer></app-footer>

如何在不刷新整个页面的情况下更新/刷新app-header 组件?

一旦用户成功登录,我想在标题中隐藏“登录”链接。标题在所有组件/路由中都是通用的。

【问题讨论】:

  • @Rohan 你能帮我做 Angular 2 SEO
  • 我已经发布了答案,你可以使用 ngIf 和 service 来加载你的 header。

标签: javascript angular refresh angular-components


【解决方案1】:

您可以使用 BehaviorSubject 在整个应用程序的不同组件之间进行通信。您可以定义一个包含 BehaviorSubject 的数据共享服务,您可以订阅和发出更改。

定义数据共享服务

import { Injectable } from '@angular/core';
import { BehaviorSubject } from 'rxjs';

@Injectable()
export class DataSharingService {
    public isUserLoggedIn: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);
}

在您的 AppModule 提供者条目中添加 DataSharingService

接下来,在您的&lt;app-header&gt; 和您执行登录操作的组件中导入DataSharingService。在&lt;app-header&gt; 订阅对isUserLoggedIn 主题的更改:

import { DataSharingService } from './data-sharing.service';

export class AppHeaderComponent { 
    // Define a variable to use for showing/hiding the Login button
    isUserLoggedIn: boolean;

    constructor(private dataSharingService: DataSharingService) {

        // Subscribe here, this will automatically update 
        // "isUserLoggedIn" whenever a change to the subject is made.
        this.dataSharingService.isUserLoggedIn.subscribe( value => {
            this.isUserLoggedIn = value;
        });
    }
}

在您的&lt;app-header&gt; html 模板中,您需要添加*ngIf 条件,例如:

<button *ngIf="!isUserLoggedIn">Login</button> 
<button *ngIf="isUserLoggedIn">Sign Out</button>

最后,您只需要在用户登录后发出事件,例如:

someMethodThatPerformsUserLogin() {
    // Some code 
    // .....
    // After the user has logged in, emit the behavior subject changes.
    this.dataSharingService.isUserLoggedIn.next(true);
}

【讨论】:

  • 谢谢@Faisal U 拯救了我的一天 :)
  • 您可以将令牌保存在本地存储中,然后将CanActivate Guard 添加到您的登录组件路由中。在警卫中,检查令牌是否存在,然后将用户带到所需的路线。
  • 非常感谢@Faisal 它运行良好,我也想要
  • 这将在页面刷新时产生问题。默认情况下,每次页面刷新时都会为 false。
  • 因此,如果您再次阅读评论,我的意思是在页面刷新时默认不采用 false,而是应该从内存中读取
【解决方案2】:

要定期刷新组件,我发现这是最好的方法。 在 ngOnInit 方法中的 setTimeOut 函数

ngOnInit(): void {
  setTimeout(() => { this.ngOnInit() }, 1000 * 10)
}
//10 is the number of seconds

【讨论】:

  • 刷新任意组件的正确代码。
【解决方案3】:

许多解决方案之一是创建一个@Injectable() 类,该类包含您要在标题中显示的数据。其他组件也可以访问此类并更改此数据,从而有效地更改标头。

另一个选项是设置@Input() 变量和@Output() EventEmitters,您可以使用它们来更改标头数据。

编辑您要求的示例:

@Injectable()
export class HeaderService {
    private _data;
    set data(value) {
        this._data = value;
    }
    get data() {
        return this._data;
    }
}

在其他组件中:

constructor(private headerService: HeaderService) {}

// Somewhere
this.headerService.data = 'abc';

在标题组件中:

let headerData;

constructor(private headerService: HeaderService) {
    this.headerData = this.headerService.data;
}

我还没有真正尝试过这个。如果 get/set 不起作用,您可以将其更改为使用 Subject();

// Simple Subject() example:
let subject = new Subject();
this.subject.subscribe(response => {
  console.log(response); // Logs 'hello'
});
this.subject.next('hello');

【讨论】:

  • 这没关系,但我如何在登录后更改登录链接标题中的登录链接隐藏...问题是登录页面和所有其他页面的标题很常见
【解决方案4】:

Angular 会在检测到变量更改时自动更新组件。

因此,要“刷新”它,您所要做的就是确保标头具有对新数据的引用。这可以通过header.component.ts 中的订阅或通过@Input 变量...


一个例子...

ma​​in.html

<app-header [header-data]="headerData"></app-header>

ma​​in.component.ts

public headerData:int = 0;

ngOnInit(){
    setInterval(()=>{this.headerData++;}, 250);
}

header.html

<p>{{data}}</p>

header.ts

@Input('header-data') data;

在上面的例子中,header 会每 250ms 接收一次新数据,从而更新组件。


有关 Angular 的生命周期钩子的更多信息,请参阅:https://angular.io/guide/lifecycle-hooks

【讨论】:

  • 这没关系,但我如何在登录后更改登录链接标题中的登录链接隐藏...问题是登录页面和所有其他页面的标题很常见
  • @Aravinthan 我建议使用可以订阅或监听事件的服务。例如,当用户登录时,该服务可以触发一个事件,监听到 header.component.. 然后onChange 生命周期钩子将触发并且标头将更新。
【解决方案5】:

更新组件

 @Injectable()
    export class LoginService{
    private isUserLoggedIn: boolean = false;

    public setLoggedInUser(flag) { // you need set header flag true false from other components on basis of your requirements, header component will be visible as per this flag then
    this.isUserLoggedIn= flag;
    }


public getUserLoggedIn(): boolean {
return this.isUserLoggedIn;
}

Login Component ts
            Login Component{
             constructor(public service: LoginService){}

public login(){
service.setLoggedInUser(true);
}
            }
Inside Header component

 Header Component ts
        HeaderComponent {
         constructor(public service: LoginService){}

         public getUserLoggedIn(): boolean { return this.service.getUserLoggedIn()}
        }

template of header component: Check for user sign in here

<button *ngIf="getUserLoggedIn()">Sign Out</button>
<button *ngIf="!getUserLoggedIn()">Sign In</button>

您可以使用许多方法,例如使用 ngIf 显示隐藏

App Component ts
AppComponent {
 public showHeader: boolean = true;
}
App Component html
<div *ngIf='showHeader'> // you show hide on basis of this ngIf and header component always get visible with it's lifecycle hook ngOnInit() called all the time when it get visible
<app-header></app-header>
</div>
<router-outlet></router-outlet>
<app-footer></app-footer>

你也可以使用服务

@Injectable()
export class AppService {
private showHeader: boolean = false;

public setHeader(flag) { // you need set header flag true false from other components on basis of your requirements, header component will be visible as per this flag then
this.showHeader = flag;
}

public getHeader(): boolean {
return this.showHeader;
}
}

App Component.ts
    AppComponent {
     constructor(public service: AppService){}
    }

App Component.html
    <div *ngIf='service.showHeader'> // you show hide on basis of this ngIf and header component always get visible with it's lifecycle hook ngOnInit() called all the time when it get visible
    <app-header></app-header>
    </div>
    <router-outlet></router-outlet>
    <app-footer></app-footer>

【讨论】:

  • 不,它不需要刷新你的页面,你只需要设置标志 true 和 false 并且标题将相应地显示隐藏。请尝试确保这会起作用。
  • 这将隐藏整个标题,而不是 OP 在问题中提出的问题。
  • 请看他的第一条评论。
  • 我已经根据 cmets 编辑了他的问题,请阅读。您的解决方案适用于整个标题,但不适用于 OP 的要求。此外,还有更好的方法来实现他的目标。
  • 顺便说一句,OP 的意思是“原始海报”:D
【解决方案6】:

你只需要通知 Angular 用 ChangeDetectorRef 更新组件。因此,在您的标头组件中:

constructor(private cd: ChangeDetectorRef) {}

loggedUserEvent(user: User): void {
  this.username = user.username; 
  this.enableDisconnectButton();

  //... Add more logic to it

  this.cd.detectChanges();
}

应该够了

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-08-29
    • 2011-06-15
    • 2020-11-14
    • 1970-01-01
    • 2015-11-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多