Angular2 - Class - DirectiveResolver

DirectiveResolver

resolve(type: Type) : DirectiveMetadata
Return DirectiveMetadata for a given Type.

resolve(type: Type): DirectiveMetadata {
var typeMetadata = reflector.annotations(resolveForwardRef(type));
//找到所有 @annotations
if (isPresent(typeMetadata)) {
//看他是不是指令
var metadata = typeMetadata.find(_isDirectiveMetadata);
if (isPresent(metadata)) {
//propertyMetadata 是指用了makePropDecorator 来创建的一些Factory, 比如ContentChild/ViewChildren
var propertyMetadata = reflector.propMetadata(type);
return this._mergeWithPropertyMetadata(metadata, propertyMetadata);
}
}

throw new BaseException(`No Directive annotation found on ${stringify(type)}`);
}

debug 跟踪后找到 Class RuntimeMetadataResolver 这次扒皮应该会挖出怎么动态加载组件,指令什么的

getDirectiveMetadata(directiveType: Type): cpl.CompileDirectiveMetadata {
var meta = this._directiveCache.get(directiveType);
if (isBlank(meta)) {
//头一次遇到这个指令没Cache过
var dirMeta = this._directiveResolver.resolve(directiveType);
var moduleUrl = null;
var templateMeta = null;
var changeDetectionStrategy = null;

//如果是个组件
//dirMeta 是 DirectiveMetadata 类型
if (dirMeta instanceof md.ComponentMetadata) {
var cmpMeta = <md.ComponentMetadata>dirMeta;
moduleUrl = calcModuleUrl(directiveType, cmpMeta);
// 得到viewMeta , templateMeta
var viewMeta = this._viewResolver.resolve(directiveType);
templateMeta = new cpl.CompileTemplateMetadata({
encapsulation: viewMeta.encapsulation,
template: viewMeta.template,
templateUrl: viewMeta.templateUrl,
styles: viewMeta.styles,
styleUrls: viewMeta.styleUrls
});

// 赋值检查策略
changeDetectionStrategy = cmpMeta.changeDetection;
}

meta = cpl.CompileDirectiveMetadata.create({
selector: dirMeta.selector,
exportAs: dirMeta.exportAs,
isComponent: isPresent(templateMeta),
dynamicLoadable: true,
type: new cpl.CompileTypeMetadata(
{name: stringify(directiveType), moduleUrl: moduleUrl, runtime: directiveType}),
template: templateMeta,
changeDetection: changeDetectionStrategy,
inputs: dirMeta.inputs,
outputs: dirMeta.outputs,
host: dirMeta.host,
lifecycleHooks: LIFECYCLE_HOOKS_VALUES.filter(hook => hasLifecycleHook(hook, directiveType))
});
this._directiveCache.set(directiveType, meta);
}
// meta 是 CompileDirectiveMetadata
return meta;
}

谁调用了getDirectiveMetadata?

compileHostComponentRuntime(type: Type): Promise<HostViewFactory> {
var compMeta: CompileDirectiveMetadata =
this._runtimeMetadataResolver.getDirectiveMetadata(type);
var hostCacheKey = this._hostCacheKeys.get(type);
//hostCacheKey 查找
if (isBlank(hostCacheKey)) {
//没有就创建hostCache - 估计是存host的缓存 可能是set类型
hostCacheKey = new Object();
this._hostCacheKeys.set(type, hostCacheKey);
//确认他是组件类型
assertComponent(compMeta);

//createHostComponentMeta 是去定位此组件的标签也就是host元素去了,并创建hostMeta
var hostMeta: CompileDirectiveMetadata =
createHostComponentMeta(compMeta.type, compMeta.selector);

//因为没hostCacheKey,所以去做些 compiledTemplate 相关的事cache compiledTemplate/compilingComponentCacheKeys
//返回 compiledTemplate
this._compileComponentRuntime(hostCacheKey, hostMeta, [compMeta], [], []);
}
return this._compiledTemplateDone.get(hostCacheKey)
.then((compiledTemplate: CompiledTemplate) =>
// 类型上的变化 compiledTemplate -> HostViewFactory
new HostViewFactory(compMeta.selector, compiledTemplate.viewFactory));
}

谁调用了compileHostComponentRuntime 呢?

@Injectable()
export class RuntimeCompiler_ extends Compiler_ implements RuntimeCompiler {
constructor(private _templateCompiler: TemplateCompiler) { super(); }

compileInHost(componentType: Type): Promise<HostViewFactoryRef_> {
return this._templateCompiler.compileHostComponentRuntime(componentType)
//继续类型上变化 HostViewFactory -> HostViewFactoryRef_
.then(hostViewFactory => new HostViewFactoryRef_(hostViewFactory));
}

clearCache() {
super.clearCache();
this._templateCompiler.clearCache();
}
}

继续…

就回到DynamicComponentLoader_

loadAsRoot(type: Type, overrideSelector: string, injector: Injector, onDispose?: () => void,
projectableNodes?: any[][]): Promise<ComponentRef> {
return this._compiler.compileInHost(type).then(hostProtoViewRef => {
var hostViewRef = this._viewManager.createRootHostView(hostProtoViewRef, overrideSelector,
injector, projectableNodes);
var newLocation = this._viewManager.getHostElement(hostViewRef);
var component = this._viewManager.getComponent(newLocation);

var dispose = () => {
if (isPresent(onDispose)) {
onDispose();
}
this._viewManager.destroyRootHostView(hostViewRef);
};
return new ComponentRef_(newLocation, component, type, injector, dispose);
});
}

后面继续跟踪type是怎么来的,这个很重要
其实就是组件名字。。

@Component({
selector: 'my-app',
template: 'Parent (<child id="child"></child>)'
})
class MyApp {
constructor(dcl: DynamicComponentLoader, injector: Injector) {
dcl.loadAsRoot(ChildComponent, '#child', injector);
}
}

回顾一下:
几种metadata:

  • compiledTemplate
  • hostMeta
  • compMeta
  • CompileDirectiveMetadata
  • DirectiveMetadata
  • viewMeta
  • templateMeta
  • metadata

还有几种Cache:

  • hostCacheKey
  • compilingComponentCacheKeys
  • _directiveCache