[AngularJS2]AngularJS2应用启动过程
来源:互联网 发布:网络功能虚拟化 编辑:程序博客网 时间:2024/05/21 21:47
当浏览器访问Angular应用时,首先index.html页面被加载。
然后,inline.bundle.js被浏览器加载执行。在inline.bundle.js中定义了函数webpackJsonp(...)
和__webpack_require__(...)
。
通过函数webpackJsonp(chunkIds, moreModules, executeModules)
可以向应用添加代码块,参数chunkIds
是代码块的ID, moreModules
是代码块中包含的模块,而executeModules
指定了需要执行的模块。webpackJsonp(...)
调用__webpack_require__()
执行executeModules
指定的模块。
/******/ (function(modules) { // webpackBootstrap/******/ // install a JSONP callback for chunk loading/******/ var parentJsonpFunction = window["webpackJsonp"];/******/ window["webpackJsonp"] = function webpackJsonpCallback(chunkIds, moreModules, executeModules) {/******//******/ ... .../******//******/ if(executeModules) {/******/ for(i=0; i < executeModules.length; i++) {/******/ result = __webpack_require__(__webpack_require__.s = executeModules[i]);/******/ }/******/ }/******/ return result;/******/ };/******//******/ ... .../******//******/ // The require function/******/ function __webpack_require__(moduleId) {/******//******/ ... .../******//******/ // Execute the module function/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);/******//******/ ... .../******//******/ // Return the exports of the module/******/ return module.exports;/******/ }/******//******/ })/******/ ([]);
当main.bundle.js被浏览器加载执行,函数webpackJsonp(["main"], ..., [0])
会被调用执行。ID为“0”的模被块被执行,在执行中”../../../../../src/main.ts”模块也会被执行__webpack_require__("../../../../../src/main.ts")
。
这里就是angular应用入口点: platformBrowserDynamic().bootstrapModule(AppModule));
webpackJsonp(["main"],{"../../../../../src/main.ts":(function(module, __webpack_exports__, __webpack_require__) {"use strict";eval("Object.defineProperty(__webpack_exports__, \"__esModule\", { value: true });\nvar __WEBPACK_IMPORTED_MODULE_0__angular_core__ = __webpack_require__(\"../../../core/esm5/core.js\");var __WEBPACK_IMPORTED_MODULE_1__angular_platform_browser_dynamic__ = __webpack_require__(\"../../../platform-browser-dynamic/esm5/platform-browser-dynamic.js\");var __WEBPACK_IMPORTED_MODULE_2__app_app_module__ = __webpack_require__(\"../../../../../src/app/app.module.ts\");Object(__WEBPACK_IMPORTED_MODULE_1__angular_platform_browser_dynamic__[\"a\" /* platformBrowserDynamic */])() .bootstrapModule(__WEBPACK_IMPORTED_MODULE_2__app_app_module__[\"a\" /* AppModule */])); /***/ 0:/***/ (function(module, exports, __webpack_require__) {__webpack_require__("../../../../webpack-dev-server/client/index.js?http://0.0.0.0:0");module.exports = __webpack_require__("../../../../../src/main.ts");/***/ })},[0]);
platformBrowserDynamic
的定义可以在angular源代码packages\platform-browser-dynamic\src\platform-browser-dynamic.ts中找到。
export const platformBrowserDynamic = createPlatformFactory ( platformCoreDynamic, 'browserDynamic', INTERNAL_BROWSER_DYNAMIC_PLATFORM_PROVIDERS);
createPlatformFactory()
创建并返回对应的PlatformRef
对象,PlatformRef
是应用程序运行的环境。在packages\core\src\core\application_ref.ts中我们可以找到PlatformRef
的定义。
export class PlatformRef { private _modules: NgModuleRef<any>[] = []; private _destroyListeners: Function[] = []; private _destroyed: boolean = false; bootstrapModule<M>( moduleType: Type<M>, compilerOptions: (CompilerOptions&BootstrapOptions)| Array<CompilerOptions&BootstrapOptions> = []): Promise<NgModuleRef<M>> { const compilerFactory: CompilerFactory = this.injector.get(CompilerFactory); const options = optionsReducer({}, compilerOptions); const compiler = compilerFactory.createCompiler([options]); return compiler.compileModuleAsync(moduleType) .then((moduleFactory) => this.bootstrapModuleFactory(moduleFactory, options)); }}
在BootstrapModule()
中,首先是模块被编译, 然后调用BootstrapModuleFactory()
和_moduleDoBootstrap()
。在_moduleDoBootstrap()
中,我们可以看到对象ApplicationRef
的bootstrap()
方法被调用,参数是模块的每一Component。
const appRef = moduleRef.injector.get(ApplicationRef) as ApplicationRef;if (moduleRef._bootstrapComponents.length > 0) { moduleRef._bootstrapComponents.forEach(f => appRef.bootstrap(f));
ApplicationRef.bootstrap(componentOrFactory: ComponentFactory<C>|Type<C>, rootSelectorOrNode?: string|any)
的实现:
const selectorOrNode = rootSelectorOrNode || componentFactory.selector;const compRef = componentFactory.create(Injector.NULL, [], selectorOrNode, ngModule);compRef.onDestroy(() => { this._unloadComponent(compRef); });const testability = compRef.injector.get(Testability, null);if (testability) { compRef.injector.get(TestabilityRegistry) .registerApplication(compRef.location.nativeElement, testability);}this._loadComponent(compRef);
在这个函数里,componentFactory
是ComponentFactory_
对象的一个实例。componentFactory.create()
的定义可以在packages\core\source\view\ref.ts中找到。
class ComponentFactory_ extends ComponentFactory<any> /** * Creates a new component. */ create( injector: Injector, projectableNodes?: any[][], rootSelectorOrNode?: string|any, ngModule?: NgModuleRef<any>): ComponentRef<any> { if (!ngModule) { throw new Error('ngModule should be provided'); } const viewDef = resolveDefinition(this.viewDefFactory); const componentNodeIndex = viewDef.nodes[0].element !.componentProvider !.nodeIndex; const view = Services.createRootView( injector, projectableNodes || [], rootSelectorOrNode, viewDef, ngModule, EMPTY_CONTEXT); const component = asProviderData(view, componentNodeIndex).instance; if (rootSelectorOrNode) { view.renderer.setAttribute(asElementData(view, 0).renderElement, 'ng-version', VERSION.full); } return new ComponentRef_(view, new ViewRef_(view), component); }}
core\src\view\view.ts: function createRootView()->core\src\view\services.ts: function createProdRootView()->function createRootData()/function createRootView()
export function createRootView(root: RootData, def: ViewDefinition, context?: any): ViewData { const view = createView(root, root.renderer, null, null, def); initView(view, context, context); createViewNodes(view); return view;}
createViewNode()会遍历view.def.nodes。如果node的类型是NodeFlags.TypeElement,createElement()会被调用在DOM树上创建节点,如果这个节点还是一个component, componentView也会被创建。
最后,调用execComponentViewsAction(view, ViewAction.CreateViewNodes),如果子节点是componentView, 递归的调用callViewAction()-> createViewNodes()来创建子节点,直到没有子节点是component.
function createViewNodes(view: ViewData) { let renderHost: any; if (isComponentView(view)) { const hostDef = view.parentNodeDef; renderHost = asElementData(view.parent !, hostDef !.parent !.nodeIndex).renderElement; } const def = view.def; const nodes = view.nodes; for (let i = 0; i < def.nodes.length; i++) { const nodeDef = def.nodes[i]; Services.setCurrentNode(view, i); let nodeData: any; switch (nodeDef.flags & NodeFlags.Types) { case NodeFlags.TypeElement: const el = createElement(view, renderHost, nodeDef) as any; let componentView: ViewData = undefined !; if (nodeDef.flags & NodeFlags.ComponentView) { const compViewDef = resolveDefinition(nodeDef.element !.componentView !); componentView = Services.createComponentView(view, nodeDef, compViewDef, el); } listenToElementOutputs(view, componentView, nodeDef, el); nodeData = <ElementData>{ renderElement: el, componentView, viewContainer: null, template: nodeDef.element !.template ? createTemplateData(view, nodeDef) : undefined }; if (nodeDef.flags & NodeFlags.EmbeddedViews) { nodeData.viewContainer = createViewContainerData(view, nodeDef, nodeData); } nodes[i] = nodeData; } // Create the ViewData.nodes of component views after we created everything else, // so that e.g. ng-content works execComponentViewsAction(view, ViewAction.CreateViewNodes);export function createElement(view: ViewData, renderHost: any, def: NodeDef): ElementData { const elDef = def.element !; const rootSelectorOrNode = view.root.selectorOrNode; const renderer = view.renderer; let el: any; if (view.parent || !rootSelectorOrNode) { if (elDef.name) { el = renderer.createElement(elDef.name, elDef.ns); } else { el = renderer.createComment(''); } const parentEl = getParentRenderElement(view, renderHost, def); if (parentEl) { renderer.appendChild(parentEl, el); } } else { el = renderer.selectRootElement(rootSelectorOrNode); } if (elDef.attrs) { for (let i = 0; i < elDef.attrs.length; i++) { const [ns, name, value] = elDef.attrs[i]; renderer.setAttribute(el, name, value, ns); } } return el;}export function createComponentView( parentView: ViewData, nodeDef: NodeDef, viewDef: ViewDefinition, hostElement: any): ViewData { const rendererType = nodeDef.element !.componentRendererType; let compRenderer: Renderer2; if (!rendererType) { compRenderer = parentView.root.renderer; } else { compRenderer = parentView.root.rendererFactory.createRenderer(hostElement, rendererType); } return createView( parentView.root, compRenderer, parentView, nodeDef.element !.componentProvider, viewDef);}
- [AngularJS2]AngularJS2应用启动过程
- AngularJS2
- Angularjs2
- angularjs2
- angularjs2 一
- angularjs2 二
- angularjs2 三
- angularjs2 四
- angularjs2 五
- angularjs2 六
- angularjs2 七
- angularjs2 八
- angularjs2 九
- angularjs2 十
- angularjs2 指令
- angularjs2 表单
- AngularJS2 架构
- AngularJS2 表单
- pgpool standby node status
- Part Itemtype解读(4): Event的响应机制设定
- 两个变量交换的几种方法
- http get和post请求的区别
- R语言
- [AngularJS2]AngularJS2应用启动过程
- JS ES6中Arguments和Parameters用法解析
- Anaconda(Python科学计算环境)教程
- 派生类的拷贝构造 与 赋值重载
- 油管年度回顾视频堪比新闻联播,17年度梗你知道多少?
- JAVA集合框架
- ViewGroup的测量与绘制
- Struts 2 web 值 Hello World
- 微信小程序-求整数