Angular Can';找不到正确的弯钩
我使用的是Angular 5.2.1。我有一个主页,它有两个组成部分:Angular Can';找不到正确的弯钩,angular,angular5,Angular,Angular5,我使用的是Angular 5.2.1。我有一个主页,它有两个组成部分: <proposal-expansion [proposallist]="proposalList" ... ></proposal-expansion> <proposal-dashboard ... ></proposal-dashboard> 在主页组件中,以下是在发出该事件时调用的函数: showRecent(event) { this.proposalList
<proposal-expansion [proposallist]="proposalList" ... ></proposal-expansion>
<proposal-dashboard ... ></proposal-dashboard>
在主页组件中,以下是在发出该事件时调用的函数:
showRecent(event) {
this.proposalList = event;
this.showDashboard = false;
this.spinnerService.spinner(false);
}
因此,此时,扩展组件从proposalList获取数据并尝试渲染。在扩展组件中呈现了许多子组件,实际显示扩展组件需要4-5秒。请记住,在这段时间内没有与服务器的交互——4-5秒都是有角度的
鉴于显示扩展组件需要很长时间,我希望显示一个微调器,以便用户知道正在发生什么。我有一个微调器服务,它通过传入true
来显示微调器,或false
来隐藏微调器。单击仪表板上的按钮后(在expandRecent()
中),我立即将true
传递给服务。这就是我遇到问题的地方
即使打开微调器是第一件事(除了console.log()之外)
,它实际上并不是首先发生的。起初,我以为微调器会立即打开和关闭。但是,我发现如果我从未关闭微调器,它仍然会等到加载扩展组件后才打开微调器。此外,我还发现如果我在单击b之前手动打开微调器然后旋转器将不会关闭,直到扩展按需要加载。因此,似乎我需要确定何时何地打开旋转器
根据角度文档,ngOnChanges
当角度(重新)设置数据绑定输入属性时响应
基于此,我在扩展组件中添加了这一点,认为只要更新了proposalList
,这将被称为:
ngOnChanges() {
this.spinnerService.spinner(true);
}
我还在expandRecent()中删除了将微调器设置为true的行
method。但是,当我完成所有这些操作时,在加载扩展组件之前,仍然没有微调器,更糟糕的是,它在ngOnChanges打开它之前关闭了微调器。因此,它在4-5秒钟内没有显示微调器,然后它启动并无限期运行
我应该使用哪些适当的生命周期挂钩,以及应该在哪些组件中使用它们,以使微调器按预期运行
谢谢
使用最新尝试更新:
我现在已经开始使用路由器和服务来实现这一点,但仍然存在同样的问题
expandRecent(): void {
console.log("expand recent");
this.spinnerService.spinner(true);
this.changeDetectorRef.detectChanges();
// essentially this just passes the data from one list to another in the service
this.proposalService.proposalShortList$.take(1).subscribe(
list => this.proposalService.setProposalList(list)
);
// this navigates to the ProposalExpansion component
this.router.navigate(['../display'], { relativeTo: this.route });
}
然后我尝试将其添加到ProposalExpansion组件中:
ngAfterViewChecked() {
this.spinnerService.spinner(false);
}
现在,当expandRecent()运行时,这就是我在控制台中看到的(数字是每个组件的ngOnInit运行时的时间戳):
基于控制台,人们可能会认为它正在工作。然而,微调器从未真正可见。但是,如果我将router.navigate
放在setTimeout
函数中,那么微调器的工作完全符合预期。(当时间设置为100 ms或更大时,setTimeout工作。它在10 ms或更小的时间内不工作。)虽然这是一个我可以使用的工作环境,但我真的很想了解正在发生的事情,而且似乎我不应该使用这种工作环境
我很想在Plunker中使用它,但在添加所有代码之前,我甚至很难让它与棱角材料一起工作,所以这将是一项重要的时间投资,我宁愿避免
以下是微调器代码:
spinner.component.html
<div *ngIf="(spinner$ | async)">
<i class="fas fa-spinner fa-pulse fa-2x fa-fw"></i>
</div>
spinner.component.ts
import { Component, OnInit } from '@angular/core';
import {Observable} from 'rxjs/Observable';
import { SpinnerService } from './spinner.service';
@Component({
selector: 'spinner',
templateUrl: './spinner.component.html',
styleUrls: ['./spinner.component.scss']
})
export class SpinnerComponent implements OnInit {
spinner$: Observable<boolean>;
constructor(private spinnerService: SpinnerService) { }
ngOnInit() {
this.spinner$ = this.spinnerService.spinner$;
}
// to show the spinner
showSpinner() {
this.spinnerService.spinner(true);
}
// to hide the spinner
hideSpinner() {
this.spinnerService.spinner(false);
}
}
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs/Observable';
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
@Injectable()
export class SpinnerService {
private spinnerSubject = new BehaviorSubject<boolean>(false);
spinner$: Observable<boolean> = this.spinnerSubject.asObservable();
constructor() {}
spinner(spin:boolean) {
console.log("Should change spinner to "+spin);
this.spinnerSubject.next(spin);
}
}
从'@angular/core'导入{Component,OnInit};
从“rxjs/Observable”导入{Observable};
从“./spinner.service”导入{SpinnerService};
@组成部分({
选择器:“微调器”,
templateUrl:'./spinner.component.html',
样式URL:['./spinner.component.scss']
})
导出类SpinnerComponent实现OnInit{
微调器$:可观察;
构造函数(专用spinnerService:spinnerService){}
恩戈尼尼特(){
this.spinner$=this.spinnerService.spinner$;
}
//展示旋转器
showSpinner(){
这个.spinnerService.spinner(true);
}
//隐藏旋转器
hideSpinner(){
此.spinnerService.spinner(false);
}
}
spinner.service.ts
import { Component, OnInit } from '@angular/core';
import {Observable} from 'rxjs/Observable';
import { SpinnerService } from './spinner.service';
@Component({
selector: 'spinner',
templateUrl: './spinner.component.html',
styleUrls: ['./spinner.component.scss']
})
export class SpinnerComponent implements OnInit {
spinner$: Observable<boolean>;
constructor(private spinnerService: SpinnerService) { }
ngOnInit() {
this.spinner$ = this.spinnerService.spinner$;
}
// to show the spinner
showSpinner() {
this.spinnerService.spinner(true);
}
// to hide the spinner
hideSpinner() {
this.spinnerService.spinner(false);
}
}
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs/Observable';
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
@Injectable()
export class SpinnerService {
private spinnerSubject = new BehaviorSubject<boolean>(false);
spinner$: Observable<boolean> = this.spinnerSubject.asObservable();
constructor() {}
spinner(spin:boolean) {
console.log("Should change spinner to "+spin);
this.spinnerSubject.next(spin);
}
}
从'@angular/core'导入{Injectable};
从“rxjs/Observable”导入{Observable};
从'rxjs/BehaviorSubject'导入{BehaviorSubject};
@可注射()
出口级喷丝板服务{
私有spinnerSubject=新行为主体(false);
spinner$:Observable=this.spinnerSubject.asObservable();
构造函数(){}
微调器(旋转:布尔值){
log(“应将微调器更改为“+spin”);
这个。喷丝头主体。下一个(旋转);
}
}
使用布管时,可以按如下方式打开/关闭微调器:
应用程序组件
import { Component } from '@angular/core';
import { Router, Event, NavigationStart, NavigationEnd, NavigationError, NavigationCancel } from '@angular/router';
@Component({
selector: 'mh-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
loading: boolean = true;
constructor(private router: Router) {
router.events.subscribe((routerEvent: Event) => {
this.checkRouterEvent(routerEvent);
});
}
checkRouterEvent(routerEvent: Event): void {
if (routerEvent instanceof NavigationStart) {
this.loading = true;
}
if (routerEvent instanceof NavigationEnd ||
routerEvent instanceof NavigationCancel ||
routerEvent instanceof NavigationError) {
this.loading = false;
}
}
}
应用程序模板
<span class="glyphicon glyphicon-refresh glyphicon-spin spinner" *ngIf="loading"></span>
<router-outlet></router-outlet>
您可以为微调器定义任何所需的图像/图形。只需根据加载标志将其打开/关闭即可。虽然这不能解释微调器无法按预期工作的原因,但它确实起到了使其按预期工作的作用。基本上,我必须将导航置于setTimeout函数中:
expandRecent(): void {
console.log("expand recent");
this.spinnerService.spinner(true);
this.proposalService.proposalShortList$.take(1).subscribe(
list => this.proposalService.setProposalList(list)
);
let myrouter = this.router;
let myroute = this.route;
setTimeout(function() {
myrouter.navigate(['../display'], { relativeTo: myroute });
},100);
}
虽然这也不能回答这个问题,但它确实为用户交互的主要问题提供了一个潜在的解决方案。根据材料文档: 延迟渲染 默认情况下,扩展面板内容将被初始化,即使 面板已关闭。请改为将初始化延迟到面板关闭 如果是开放的,则内容应作为ng模板提供:
这是扩展标题
一些延迟的内容
因此,与其尝试一次性渲染所有扩展面板
<mat-expansion-panel>
<mat-expansion-panel-header>
This is the expansion title
</mat-expansion-panel-header>
<ng-template matExpansionPanelContent>
Some deferred content
</ng-template>
</mat-expansion-panel>