TokenKey
// packages/core/src/view/util.ts
const _tokenKeyCache = new Map<any, string>();
export function tokenKey(token: any): string {
let key = _tokenKeyCache.get(token);
if (!key) {
key = stringify(token) + '_' + _tokenKeyCache.size;
_tokenKeyCache.set(token, key);
}
return key;
}
// packages/core/src/view/provider.ts
const RendererV1TokenKey = tokenKey(RendererV1);
const Renderer2TokenKey = tokenKey(Renderer2);
const ElementRefTokenKey = tokenKey(ElementRef);
const ViewContainerRefTokenKey = tokenKey(ViewContainerRef);
const TemplateRefTokenKey = tokenKey(TemplateRef);
const ChangeDetectorRefTokenKey = tokenKey(ChangeDetectorRef);
const InjectorRefTokenKey = tokenKey(Injector);
resolveDep()
export function resolveDep(
view: ViewData, elDef: NodeDef,
allowPrivateServices: boolean, depDef: DepDef,
notFoundValue: any = Injector.THROW_IF_NOT_FOUND): any {
const tokenKey = depDef.tokenKey;
// ...
while (view) {
if (elDef) {
switch (tokenKey) {
case RendererV1TokenKey: { // tokenKey(RendererV1)
const compView = findCompView(view, elDef, allowPrivateServices);
return createRendererV1(compView);
}
case Renderer2TokenKey: { // tokenKey(Renderer2)
const compView = findCompView(view, elDef, allowPrivateServices);
return compView.renderer;
}
case ElementRefTokenKey: // tokenKey(ElementRef)
return new ElementRef(asElementData(view, elDef.index).renderElement);
// ... 此外还包括:ViewContainerRefTokenKey、TemplateRefTokenKey、
// ChangeDetectorRefTokenKey 等
}
}
}
// ...
}
通过以上代码,我们发现当我们在组件类的构造函数中声明相应的依赖对象时,如 Renderer2 和 ElementRef,Angular 内部会调用 resolveDep() 方法,实例化 Token 对应依赖对象。
在大多数情况下,我们开发的 Angular 应用程序是运行在浏览器平台,接下来我们来了解一下该平台下的默认渲染器 - DefaultDomRenderer2。
DefaultDomRenderer2
在浏览器平台下,我们可以通过调用 DomRendererFactory2 工厂,根据不同的视图封装方案,创建对应渲染器。
DomRendererFactory2
// packages/platform-browser/src/dom/dom_renderer.ts
@Injectable()
export class DomRendererFactory2 implements RendererFactory2 {
private rendererByCompId = new Map<string, Renderer2>();
private defaultRenderer: Renderer2;
constructor(
private eventManager: EventManager,
private sharedStylesHost: DomSharedStylesHost) {
// 创建默认的DOM渲染器
this.defaultRenderer = new DefaultDomRenderer2(eventManager);
};
createRenderer(element: any, type: RendererType2|null): Renderer2 {
if (!element || !type) {
return this.defaultRenderer;
}
// 根据不同的视图封装方案,创建不同的渲染器
switch (type.encapsulation) {
// 无 Shadow DOM,但是通过 Angular 提供的样式包装机制来封装组件,
// 使得组件的样式不受外部影响,这是 Angular 的默认设置。
case ViewEncapsulation.Emulated: {
let renderer = this.rendererByCompId.get(type.id);
if (!renderer) {
renderer =
new EmulatedEncapsulationDomRenderer2(this.eventManager,
this.sharedStylesHost, type);
this.rendererByCompId.set(type.id, renderer);
}
(<EmulatedEncapsulationDomRenderer2>renderer).applyToHost(element);
return renderer;
}
// 使用原生的 Shadow DOM 特性
case ViewEncapsulation.Native:
return new ShadowDomRenderer(this.eventManager,
this.sharedStylesHost, element, type);
// 无 Shadow DOM,并且也无样式包装
default: {
// ...
return this.defaultRenderer;
}
}
}
}
内容版权声明:除非注明,否则皆为本站原创文章。
