Angular中Input传入回调切换组件可见性失效问题排查
问题产生原因
核心问题是函数执行时的this上下文丢失:
ES6类的方法默认没有绑定自身实例上下文,当你直接把父组件的closePopup方法作为@Input值传给子组件时,方法脱离了父组件类实例的上下文。子组件触发这个回调时,closePopup内部的this不会指向父组件实例:开启严格模式时this为undefined,非严格模式下this会指向全局window对象。
你在回调里执行this.isPopupOpen = false时,修改的根本不是父组件实例上被*ngIf绑定的那个isPopupOpen属性,而是全局对象/其他上下文上的同名属性,虽然控制台能打印出你刚赋值的false,但父组件实例上的isPopupOpen始终为true,Angular变更检测检测不到绑定值的变化,自然不会按*ngIf逻辑移除弹窗。
修复方案
任选以下一种方案即可解决问题,优先推荐符合Angular设计规范的方案4:
- 方案1:传参时手动绑定父组件上下文,固定this指向
修改父组件模板传值代码:<e2-fullscreen-popup [title]="'top promotions'" [closeCallback]="closePopup.bind(this)" > - 方案2:传参时用箭头函数包裹调用,利用箭头函数继承上层this的特性固定指向
修改父组件模板传值代码:<e2-fullscreen-popup [title]="'top promotions'" [closeCallback]="() => closePopup()" > - 方案3:从根源改写父组件方法为箭头函数属性,初始化时就固定this指向
修改父组件类中的方法定义:closePopup = () => { this.isPopupOpen = false; console.log('this.isPopupOpen',this.isPopupOpen); } - 方案4(官方推荐规范写法):放弃Input传回调的通信方式,改用
@Output()事件触发通信,从设计上避免this指向问题- 修改子组件代码,替换原有的回调Input:
// 移除原@Input() closeCallback定义,替换为Output事件 @Output() close = new EventEmitter<void>(); close() { this.close.emit(); } - 子组件模板无需改动,修改父组件模板绑定方式:
<e2-fullscreen-popup [title]="'top promotions'" (close)="closePopup()" >
- 修改子组件代码,替换原有的回调Input:
内容的提问来源于stack exchange,提问作者João Pedro
相关产品推荐
相关产品推荐

