Angular 個人深究【Angular中的Typescript 裝飾器】
最近進入一個新的前端項目,為了能夠更好地了解Angular框架,想到要研究底層代碼。
注:本人前端小白一枚,文章旨在記錄自己的學習過程,如有大神發現錯誤,也請評論指正。
Angular 中的裝飾器
當安裝好Angular后,打開 文件[/my-app/src/app/app.module.ts] 與文件 [/my-app/src/app/app.component.ts]
//app.component.ts
import { Component } from '@angular/core'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent { title = 'app'; }
//app.module.ts import { BrowserModule } from '@angular/platform-browser'; import { NgModule } from '@angular/core'; import { FormsModule, ReactiveFormsModule } from '@angular/forms'; import { AppComponent } from './app.component'; import { Test1Component } from './test1/test1.component'; import { Test2Component } from './test2/test2.component'; @NgModule({ declarations: [ AppComponent, Test1Component, Test2Component ], imports: [ BrowserModule, FormsModule ], providers: [], bootstrap: [AppComponent] }) export class AppModule { }
兩個文件中的@Component與 @Ngmodule 就是我們今天要說的typescript的裝飾器的用法。
Typescript裝飾器的由來
1) 經過查詢資料,裝飾器的概念來自於Python(本人Python也是小白)
def decorator(target): print("You are decorated!") return targett #decorator是可以自定義的 @decorator def yourfunction: print("This is your function!") yourfunction() #一下是運行結果 #You are decorated! #This is your function! #網上還有分析,以上的代碼的等價寫法有助於理解。
2) ES6 引入了裝飾器這個功能。
3) Angular 中 裝飾器的測試
注:查詢網上說Nodejs 與 Typescript都能支持裝飾器,但是本人沒有調試成功,以后擴展。
-
裝飾【類】的裝飾器:
//test1.component.ts import { Component, OnInit } from '@angular/core'; function test (target) { console.log(target); target.title = "app1"; return target; } //裝飾一個類 @test @Component({ selector: 'app-test1', templateUrl: './test1.component.html', styleUrls: ['./test1.component.css'] }) export class Test1Component implements OnInit { title = 'app'; constructor() {} ngOnInit() {} } console.log(Test1Component.title); //輸出結果是app1
-
裝飾【類的方法、屬性】的裝飾器
import { Component, OnInit } from '@angular/core';
function readonly(flag:boolean){
return function readonly(target, name, descriptor) {
console.log(descriptor);
descriptor.writable = flag;
return descriptor;
}
}
export class Test1Component implements OnInit {
ngOnInit() {
this.test = function(){console.log("change")};
}
@readonly(false)
test(){
console.log("inner test function");
}
}
//控制台報錯:ERROR TypeError: Cannot assign to read only property 'test' of object '[object Object]'
//打印的descriptor {value: ƒ, writable: true, enumerable: true, configurable: true}
/* 屬性與方法都是一樣的 */
Angular中的裝飾器解讀
- 【NgModule 裝飾器】
代碼位置:node_modules\@angular\core\fesm5\core.js line1436(直接搜索var NgModule =)
/** * NgModule decorator and metadata. * * * @Annotation */ var NgModule = makeDecorator('NgModule', function (ngModule) { return ngModule; }, undefined, undefined, function (moduleType, metadata) { var imports = (metadata && metadata.imports) || []; if (metadata && metadata.exports) { imports = __spread(imports, [metadata.exports]); } moduleType.ngInjectorDef = defineInjector({ factory: convertInjectableProviderToFactory(moduleType, { useClass: moduleType }), providers: metadata && metadata.providers, imports: imports, }); });
格式:
@NgModule({ providers: Provider[]//Defines the set of injectable objects that are available in the injector of this module. declarations: Array<Type<any> | any[]>//Specifies a list of directives/pipes that belong to this module imports: Array<Type<any> | ModuleWithProviders | any[]>//Specifies a list of modules whose exported directives/pipes should be available to templates in this module. This can also contain ModuleWithProviders exports: Array<Type<any> | any[]>//Specifies a list of directives/pipes/modules that can be used within the template of any component that is part of an Angular module that imports this Angular module. entryComponents: Array<Type<any> | any[]>//Specifies a list of components that should be compiled when this module is defined. For each component listed here, Angular will create a ComponentFactory and store it in the ComponentFactoryResolver. bootstrap: Array<Type<any> | any[]>//Defines the components that should be bootstrapped when this module is bootstrapped. The components listed here will automatically be added to entryComponents. schemas: Array<SchemaMetadata | any[]>//Elements and properties that are not Angular components nor directives have to be declared in the schema. id: string//An opaque ID for this module, e.g. a name or a path. Used to identify modules in getModuleFactory. If left undefined, the NgModule will not be registered with getModuleFactory. }) //更多內容請訪問官網
//https://www.angular.cn/api/core/NgModule
//https://www.angular.cn/guide/architecture-modules
//查看
代碼解讀:
function makeDecorator(name, props, parentClass, chainFn, typeFn) {var metaCtor = makeMetadataCtor(props); function DecoratorFactory() { var args = []; for (var _i = 0; _i < arguments.length; _i++) { args[_i] = arguments[_i]; }if (this instanceof DecoratorFactory) {
// 將使用裝飾器的時候傳入的參數放到descratorFactory
//推薦https://www.jianshu.com/p/00dc4ad9b83f 去查看 .call.apply的作用
//__spread 方法定義在tslib.js中, 將數組元素經過__read方法后concat metaCtor.call.apply(metaCtor, __spread([this], args));return this; } var annotationInstance = new ((_a = DecoratorFactory).bind.apply(_a, __spread([void 0], args)))(); var TypeDecorator = function TypeDecorator(cls) { typeFn && typeFn.apply(void 0, __spread([cls], args)); // Use of Object.defineProperty is important since it creates non-enumerable property which // prevents the property is copied during subclassing. var annotations = cls.hasOwnProperty(ANNOTATIONS) ? cls[ANNOTATIONS] : Object.defineProperty(cls, ANNOTATIONS, { value: [] })[ANNOTATIONS]; annotations.push(annotationInstance); return cls; }; if (chainFn) chainFn(TypeDecorator); return TypeDecorator; var _a; } if (parentClass) { DecoratorFactory.prototype = Object.create(parentClass.prototype); } DecoratorFactory.prototype.ngMetadataName = name; DecoratorFactory.annotationCls = DecoratorFactory;
//最后返回 DecoratorFactory return DecoratorFactory; }
注:期待有大神能夠看到我的文章,並提出我的問題所在,小白一枚如果有錯誤還望指正。在此謝過。
參考網址:
http://es6.ruanyifeng.com/#docs/decorator
http://web.jobbole.com/88572/
https://www.cnblogs.com/Wayou/p/es6_new_features.html#2917341
https://www.jianshu.com/p/00dc4ad9b83f
