如何在不刷新整个页面的情况下更新组件 - Angular
How to Update a Component without refreshing full page - Angular
我的页面结构是:
<app-header></app-header>
<router-outlet></router-outlet>
<app-footer></app-footer>
如何在不刷新整个页面的情况下update/refresh app-header
组件?
我想在 header 中隐藏一个 "Sign-In" link,一旦用户成功登录。header 在所有 [=21] 中都是通用的=].
许多解决方案之一是创建一个 @Injectable()
class,其中包含您要在 header 中显示的数据。其他组件也可以访问此 class 并更改此数据,从而有效地更改 header.
另一种选择是设置 @Input()
变量和 @Output()
事件发射器,您可以使用它们来更改 header 数据。
编辑 您要求的示例:
@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';
在 header 组件中:
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');
Angular 将在检测到变量更改时自动更新组件。
因此,为了 "refresh",您要做的就是确保 header 具有对新数据的引用。这可以通过 header.component.ts
内的订阅或通过 @Input
变量...
一个例子...
main.html
<app-header [header-data]="headerData"></app-header>
main.component.ts
public headerData:int = 0;
ngOnInit(){
setInterval(()=>{this.headerData++;}, 250);
}
header.html
<p>{{data}}</p>
header.ts
@Input('header-data') data;
在上面的示例中,header 将每 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>
您可以使用 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);
}
我发现定期刷新组件是最好的方法。
在 ngOnInit 方法中 setTimeOut 函数
ngOnInit(): void {
setTimeout(() => { this.ngOnInit() }, 1000 * 10)
}
//10 is the number of seconds
您只需通知 Angular 更新组件 ChangeDetectorRef
。所以,在你的 header 组件中:
constructor(private cd: ChangeDetectorRef) {}
loggedUserEvent(user: User): void {
this.username = user.username;
this.enableDisconnectButton();
//... Add more logic to it
this.cd.detectChanges();
}
应该够了
我的页面结构是:
<app-header></app-header>
<router-outlet></router-outlet>
<app-footer></app-footer>
如何在不刷新整个页面的情况下update/refresh app-header
组件?
我想在 header 中隐藏一个 "Sign-In" link,一旦用户成功登录。header 在所有 [=21] 中都是通用的=].
许多解决方案之一是创建一个 @Injectable()
class,其中包含您要在 header 中显示的数据。其他组件也可以访问此 class 并更改此数据,从而有效地更改 header.
另一种选择是设置 @Input()
变量和 @Output()
事件发射器,您可以使用它们来更改 header 数据。
编辑 您要求的示例:
@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';
在 header 组件中:
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');
Angular 将在检测到变量更改时自动更新组件。
因此,为了 "refresh",您要做的就是确保 header 具有对新数据的引用。这可以通过 header.component.ts
内的订阅或通过 @Input
变量...
一个例子...
main.html
<app-header [header-data]="headerData"></app-header>
main.component.ts
public headerData:int = 0;
ngOnInit(){
setInterval(()=>{this.headerData++;}, 250);
}
header.html
<p>{{data}}</p>
header.ts
@Input('header-data') data;
在上面的示例中,header 将每 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>
您可以使用 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);
}
我发现定期刷新组件是最好的方法。 在 ngOnInit 方法中 setTimeOut 函数
ngOnInit(): void {
setTimeout(() => { this.ngOnInit() }, 1000 * 10)
}
//10 is the number of seconds
您只需通知 Angular 更新组件 ChangeDetectorRef
。所以,在你的 header 组件中:
constructor(private cd: ChangeDetectorRef) {}
loggedUserEvent(user: User): void {
this.username = user.username;
this.enableDisconnectButton();
//... Add more logic to it
this.cd.detectChanges();
}
应该够了