簡體   English   中英

如何在不刷新整個頁面的情況下更新組件 - Angular

[英]How to Update a Component without refreshing full page - Angular

我的頁面結構是:

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

如何在不刷新整個頁面的情況下更新/刷新app-header組件?

一旦用戶成功登錄,我想在 header 中隱藏一個“登錄”鏈接。header 在所有組件/路由中都很常見。

您可以使用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

接下來,在您的<app-header>和您執行登錄操作的組件中導入DataSharingService <app-header>訂閱對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;
        });
    }
}

在您的<app-header> 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);
}

許多解決方案之一是創建一個@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');

為了定期刷新組件,我發現這是最好的方法。 在 ngOnInit 方法中 setTimeOut 函數

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

Angular 會在檢測到變量變化時自動更新組件。

因此,您要“刷新”所需要做的就是確保標頭具有對新數據的引用。 這可能是通過內訂閱header.component.ts或通過@Input變量...


一個例子...

主文件

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

main.component.ts

public headerData:int = 0;

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

標題.html

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

頭文件

@Input('header-data') data;

在上面的例子中,頭部將每 250 毫秒接收一次新數據,從而更新組件。


有關 Angular 的生命周期鈎子的更多信息,請參閱: https : //angular.io/guide/lifecycle-hooks

更新組件

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

您只需要通知 Angular 使用ChangeDetectorRef更新組件。 因此,在您的標頭組件中:

constructor(private cd: ChangeDetectorRef) {}

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

  //... Add more logic to it

  this.cd.detectChanges();
}

那應該夠了

以前的所有答案都很好。 但只是為了一些變化,這里有一個不同的解決方案:

第 1 步 - 使用新的事件發射器將 Output 添加到子 component.ts 文件。

第 2 步 - 當您在子組件中執行所需的操作時發出 output

第 3 步 - 將 output 附加到父組件中的子選擇器。html

第 4 步 - 在您的父組件中添加必要的 function 以更改數據。

完整代碼如下所示:

 // --- child.ts --- import { Component, OnInit,Input,Output,EventEmitter } from '@angular/core'; @Output() refreshData = new EventEmitter<{ update: boolean }>(); // note: the 'update' variable isn't needed in the code I've given you, but I've included it in case you want to know how to pass data in the event emitter @Input() myData: boolean | undefined; signInOut(){ this.refreshData.emit({update:true}) } // --- child.html --- <div>Signed in = {{myData}}</div> <button (click) = signInOut()>Click me to sign in or out and refresh the data</button> // --- parent.html --- <child-selector [myData] = "isSignedIn" (refreshData) = dataChange($event)></child-selector> // --- parent.ts --- isSignedIn = false dataChange(eventData: { update: boolean }){ console.log('test') this.isSignedIn =.this.isSignedIn }

希望這可以幫助!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM