Angular中@ContentChild结合Directive获取实例为undefined的问题
我帮你排查了一下,你遇到的问题核心原因其实很直接:你投影到<field-validation>里的<input>元素,根本没有应用FocusDirective指令,所以@ContentChild(FocusDirective)自然找不到对应的实例,只能返回undefined。
具体来说,你需要做这几步修正:
1. 给input元素添加指令的选择器属性
假设你的FocusDirective定义时的选择器是类似[appFocus](比如指令代码里写了@Directive({ selector: '[appFocus]' })),那你必须在父应用的input上加上这个属性,Angular才会把指令绑定到这个input上:
<form [formGroup]="testForm"> <field-validation> <!-- 加上指令的选择器属性 appFocus --> <input type="text" placeholder="0.00" appFocus> </field-validation> <div> <button type="submit">FAKE SUBMIT</button> </div> </form>
2. 确保指令已在模块中正确声明/导入
另外要确认FocusDirective已经在你的Angular模块(比如AppModule)的declarations数组中声明了,或者如果是在共享模块里,要确保共享模块导出了这个指令,并且当前模块导入了共享模块。如果指令没被Angular识别,即使加了选择器也不会生效。
3. 关于生命周期的补充
你已经在ngAfterContentInit里打印实例,这是正确的时机——因为@ContentChild的实例会在AfterContentInit钩子触发时才被初始化完成,ngOnInit里确实可能还拿不到,不过这不是你这次问题的核心,核心还是指令没应用到input上。
举个完整的FocusDirective示例供参考:
import { Directive, Output, EventEmitter, HostListener } from '@angular/core'; @Directive({ selector: '[appFocus]' // 这里的选择器要和input上的属性对应 }) export class FocusDirective { @Output() focusChange = new EventEmitter<boolean>(); @HostListener('focus') onFocus() { this.focusChange.emit(true); } @HostListener('blur') onBlur() { this.focusChange.emit(false); } }
这样修改后,你在FieldValidationComponent的ngAfterContentInit里就能正常获取到FocusDirective的实例了,后续也可以订阅它的focusChange事件做相应处理。
内容的提问来源于stack exchange,提问作者nopuck4you

