开发中遇到的问题
在开发中遇到一个这样的问题,代码不便透露,这里用简单的例子还原一下问题所在:
有三个组件,第一个是用来展示Todo列表的组件TodoComponent,Todo是个类,包含id和name属性。
@Component({ selector: 'todo-list', template: ` <p *ngFor='let item of todos'>{{ item.name }}</p> `,})export class TodoComponent{ @Input() todos: Todo[]; public getTodos():Todo[]{ return this.todos; }}
第二个组件同样是一个Todo列表展示组件TodoDataComponent ,不同的是该组件需要一个TodoComponent类型的输入,并从TodoComponent组件中获得需要展示的Todo数据。
@Component({ selector: 'app-todo-data', template: `<p *ngFor='let item of todos'>{{ item.name }}</p> <button (click)='getData()'>get data</button>`, styleUrls: ['./todo-data.component.css'], inputs: ['todoComponent'],})export class TodoDataComponent implements OnInit { todoComponent: TodoComponent; todos: Todo[] constructor() { } ngOnInit() { } getData(){ this.todos=this.todoComponent.getTodos(); }}
最后一个是应用的根组件,根组件根据loading值来确定是否加载TodoComponent组件,并展示TodoDataComponent 组件。
//app.component.htm<div> <div *ngIf='loading'> <todo-list [todos]='todos'></todo-list> <button (click)='changeall()'>next</button> </div></div><div> <app-todo-data [todoComponent]='todoComponent'></app-todo-data></div>//app.component.ts@Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'],})export class AppComponent implements OnInit { todos: Todo[]; @ViewChild(TodoComponent) todoComponent: TodoComponent; loading: boolean = true; constructor(private todoService:TodoService){ super(true); } ngOnInit(){ this.todoService.todos.subscribe(data => {this.todos=data}); this.todoService.load(0, 3); } changeall(){ this.todoService.load(3, 3); }}
这样问题就来了,TodoComponent 组件是否在页面上展示是不确定的,在上面的例子中根组件最开始没有渲染TodoComponent组件,最后根据loading的值将TodoComponent渲染出来。而TodoDataComponent 组件的显示又需要一个TodoComponent 进行初始化(跟组件通过@ViewChild(TodoComponent)
获得),这样造成在开发模式下出现以下错误:template:9:16 caused by: Expression has changed after it was checked. Previous value: 'undefined'. Current value: '[object Object]'
.
该错误仅在开发模式下会报告出来的,解决掉总是更好的选择,防止在生产环境下出现问题。
问题的原因及解决办法
这个问题是ng2中的变更检测策略造成的,ng2并没有智能到一有数据变更就能自动检测到的,执行变更检测的一些情况有:组件中的输入发生变化、组件中有事件响应、setTimeOut函数等。
新闻热点
疑难解答
图片精选