Angular中Constructor 和 ngOnInit 的本质区别
在Medium看到一篇Angular的文章,深入对比了 Constructor 和 ngOnInit 的不同,受益匪浅,于是搬过来让更多的前端小伙伴看到,翻译不得当之处还请斧正。 有关JS和TS语言的区别让我们从语言本身最明显的区别开始。在一个类中, class MyComponent { ngOnInit() { } otherNameForNgOnInit() { } } 在一个组件类中引不引入这个方法完全取决于你。编译过程中Angular编译器会检查组件是否引入了这个方法,然后用合适的标记去标记这个类: export const enum NodeFlags { ... OnInit = 1 << 16, 在变更检测过程中,在组件实例内,这个标记会被用来决定是否调用 if (def.flags & NodeFlags.OnInit && ...) { componentClassInstance.ngOnInit(); } 相反,constructor是个不同的东西。在一个TypeScript类实例化过程中,无论写不写constructor,它都会被调用。这就是为什么一个TypeScript类的constructor会被转译成一个 JavaScript constructor function: class MyComponent { constructor() { console.log('Hello'); } } 转译成 function MyComponent() { console.log('Hello'); } 在创建类实例时这个函数会被用 const componentInstance = new MyComponent( 所以,如果你在类中省略constructor,这个类会被转译成一个空函数: function MyComponent() {} 这就是为什么我说在类中无论写不写constructor,它都会被调用。 有关组件初始化进程的区别从组件初始化阶段的角度看,两者存在巨大差别。Angular bootstrap process(译注:这个比较微妙,不知道怎么翻译,暂且译作引导进程吧)包含两个主要阶段:
而且,组件的constructor会在Angular构造组件树的时候被调用。所有生命周期钩子包括 Angular构造组件树的时候,根模块注入器就已经配置好,所以你可以注入任何全局依赖。而且,当Angular实例化一个子组件类的时候,父组件的注入器也已经配置好,所以你可以注入父组件中定义的提供商(providers),包括父组件自身。组件的constructor是在注入器的上下文中被调用的唯一方法,所以如果你需要任何依赖,constructor是唯一获得这些依赖的地方。 Angular开始变更检测的时候组件树已经构造完毕,在组件树中的所有组件的constructor都会被调用。而且这时候所有组件的模板节点(template nodes)也已经添加到DOM中,这时,初始化组件的所有数据都已齐全——依赖注入提供商、DOM和输入绑定(?DI providers,DOM and input bindings)。 你可以在Everything you need to know about change detection in Angular学习关于变更检测的知识,在The mechanics of property bindings update in Angular学习Angular进程如何输入。 我们用个简单例子证明这些阶段。假设有如下模板: <my-app> <child-comp [i]='prop'> Angular开始引导应用程序。如上所述,它首先创建每个组件的类,因此调用 MyAppView - MyApp component instance - my-app host element data ChildComponentView - ChildComponent component instance - child-comp host element data 直到那时Angular才会运行变更检测、更新 你可以在Here is why you will not find components inside Angular了解更多知识。 用法上的区别现在从用法的角度看看两者的区别。 Constructor在Angular中,一个类的constructor主要用来注入依赖。Angular调用constructor injection pattern在这里已经解释得很详细,更深入的见解你可以读Mi?ko Hevery的文章Constructor Injection vs. Setter Injection。 然而,constructor的使用不仅限于依赖注入(DI)。举个例子, 惯例就是,在constructor中,逻辑应尽可能少。 NgOnInit前文我们看到,当Angular调用 习惯上用 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |