组件在 NgOnInit 完成之前渲染?
Posted
技术标签:
【中文标题】组件在 NgOnInit 完成之前渲染?【英文标题】:Component renders before NgOnInit finishes? 【发布时间】:2018-09-19 18:54:38 【问题描述】:我有一个组件,它对调用 api 的服务执行一些调用。组件在这些调用完成之前呈现,导致页面为空。
这是来自组件的代码:
import Component, OnInit, OnDestroy from '@angular/core';
import AuthService from '../services/auth.service';
import AssignmentService from '../services/assignment.service';
import Assignment from '../models/Assignment';
import Request from '../models/Request';
import MeService from '../services/me.service';
import * as MicrosoftGraph from '@microsoft/microsoft-graph-types';
import Router from '@angular/router';
import NavbarService from '../services/navbar.service';
@Component(
selector: 'app-newrequest',
templateUrl: './newrequest.component.html',
providers: [AssignmentService]
)
export class NewrequestComponent implements OnInit
me: MicrosoftGraph.User;
assignments: Assignment[];
requests: Request[] = [];
ready = false;
constructor(private meService: MeService,
private authService: AuthService,
private assignmentService: AssignmentService,
private router: Router,
public nav: NavbarService)
ngOnInit()
this.nav.show();
this.nav.element = 'newrequests';
if (localStorage.getItem('loggedin') === 'yes')
this.meService.getMe().subscribe(data =>
this.me = data;
,
error =>
console.log(error);
,
() => this.assignmentService.getAssignments().subscribe(data =>
this.assignments = data;
,
error =>
console.log(error);
,
() =>
this.setRequests();
));
else
this.router.navigate(['']);
onLogout()
this.authService.logout();
onLogin()
this.authService.login();
private setRequests()
this.assignments.forEach(item =>
if (this.me.mail.toLowerCase() === item.lecturer.toLowerCase())
this.parseRequests(item.request, item.name);
);
this.ready = true;
private parseRequests(toSplit, name)
const split = toSplit.split(',');
split.forEach(item =>
this.requests.push(new Request(item, name));
);
这是页面中的代码:
<app-navbar-component></app-navbar-component>
<div *ngIf="ready">
<div *ngFor="let request of requests">
<p class="lead">request.user</p>
</div>
</div>
这是我的服务中的功能:
getAssignments()
return this.http.get(this.BASE_API_URL + '/assignments').catch(this.onError);
我没有收到任何错误。请求已加载(通过 console.log 检查)。唯一的问题是页面在数据加载完成之前呈现。
有什么想法吗?
提前致谢!
【问题讨论】:
是的,没错。 HTTP 请求是异步的,因此它不会等到完成。 我该如何规避这个问题?我认为 *ngIf 会工作...... 规避什么?请求最终完成时是否呈现数据? 如果你不想在收到数据之前渲染页面,你可以使用router resolve guard。 请求完成后组件不渲染。 【参考方案1】:是的,由于服务调用是异步的,调用订阅时数据不会立即到达。
但是在您的代码中,一旦数据到达,您并没有将 ready 变量设置为 true。所以你在页面上看不到任何数据。获取数据后设置为true
this.me = data;
this.ready =true;
或通过安全导航操作符处理。
【讨论】:
感谢您的帮助。我认为你监督了准备好的部分。我在 setRequests() 函数中将 ready 设置为 true。 是的。我注意到,当我在您提到的地方设置为 true 时,它在组件中变为 true。然而,这还为时过早。它使用的数据到那时还没有加载。我需要作业数据。 在subscribe里面调用setrequests 不幸的是没有改变任何东西 我确定你的方法 parseRequest 有问题。只需检查您的数组是否有数据【参考方案2】:您是否尝试过使用解析?
创建一个解析器,命名为 assignments-details.resolver.ts
import Injectable from '@angular/core';
import Resolve, ActivatedRouteSnapshot, RouterStateSnapshot from '@angular/router';
import MeService from '../services/me.service';
@Injectable()
export class AssignmentsDetailsResolver implements Resolve<any>
constructor(api: MeService)
resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot)
return this.api.getAssignments();
然后在你的路由配置中这样做
path: 'your_path',
component: NewrequestComponent,
resolve: AssignmentsDetails: AssignmentsDetailsResolver
然后确保在您的 NewrequestComponent 上导入 ActivatedRoute
import ActivatedRoute from '@angular/router'
在你的构造函数中这样称呼它
constructor(private meService: MeService,
private authService: AuthService,
private assignmentService: AssignmentService,
private router: Router,
public nav: NavbarService,
private activateRoute: ActivatedRoute)
this.activateRoute.data.subscribe((response) =>
//to get the response
console.log(response.AssignmentsDetails);
);
还要确保在模块的 provider 属性中注册“AssignmentsDetailsResolver”。
希望对你有所帮助。
【讨论】:
这里的resolve方法就是这个问题的准确答案。以上是关于组件在 NgOnInit 完成之前渲染?的主要内容,如果未能解决你的问题,请参考以下文章