injector解析

mac2022-06-30  105

injector 有两种类型 ,ProviderInjector 和InstanceInjector .两者get方法执行起来有差异

ProviderInjector 的结构如下: ` { get: function getService(serviceName){ return cacheProvider[serviceName] ; } }

` InstanceInjector 结构如下Pseudocode

{ get: function getService(serviceName){ instanceCache[serviceName] ?... s = ProviderInjector.get(serviceName) invoke(s); ...} }

之所以有这两种injector . providerInjector用来处理module结构里队列中存放的 p结构(第一章提到的),将之处理成Provider构型 ---- 形如 s: {$get:{}} 结构的。 instanceInjector用来实例化Provider构型的。

在service中使用到的$injector,比如 service($injector) $injector就是instanceInjector。

InstanceInjector 会先从ProviderInjector 里拿到同名service再实例化。

ProviderInjector 闭包里有叫cacheProvider的对象,顾名思义会缓存provider。 那么往这个cacheProvider缓存存放Provider构型,则需要$provider.provider。

我们稍作跳跃。

在angular创建injector对象后 ,会利用injector实例化所有模块中的fn. 在所有的模块中‘ng’模块是最先进行处理的。

我们来模拟ng的过程

+--------------+ | |ng| | <------------+ +--------------+ | | | require: 'ng-location' <hasRequire?>-----Y--------+ 1. +-------------------------+ | |_ng-location__| | | | ___ ng_______| | | | +-------------------------+ | <hasRequire?> | N V 2. moduleNgLocation = angular.module('ng-location') //angularModule(module); 1.拿到模块 回顾第一章 每一个 module 都有 invokeQueue 和 configBlock 和 runBlocks, configBlocks里是这样的结构 ['$inject' ,'invoke' ['s' ,fn(s){}] 然后 分别处理该模块的 invokeQueue 和 configBlock runInvokeQueue(moduleFn._invokeQueue); runInvokeQueue(moduleFn._configBlocks); runInvokeQueue的执行过程是 拿其中一条记录['$inject' ,'invoke' ,['$provider' ,fn($provider){}] (第一章提到的p结构)为例 p结构的第一个数据是$inject providerInjector.get('$inject'); 前文提到providerInjector.get方法是从从providerCache里取,那么‘$inject’已经存在于providerCache中了吗? 答案是 Yes . 在创建好providerInjector和 instanceInjector 中就已经放入providerCache中了 (providerCache.$inject = providerInjector) .除了$injector ,providerCache中$provider对象也早早的定义了。他们是始祖对象。 providerInjector.get('$inject') 的值实际上就是providerInjector自身. p结构的第二个数据invoke, 所以去执行invoke方法 , providerInjector.invoke( ['$provider' ,fn($provider){}]) //p结构的第三个数据 invoke会先实例化参数’$provider' 会取providerCache中取$provider ,$provider 随着providerCache定义的时候定义了。

providerCache = { $provide: { provider: supportObject(provider), factory: supportObject(factory), service: supportObject(service), value: supportObject(value), constant: supportObject(constant), decorator: decorator } }, 然后就可以将$provider作为参数 实例化fn 实例化过程:

args.unshift(null); return new (Function.prototype.bind.apply(fn, args))(); 实例化好之后就会放入instanceCache中了 至此ng-location模块处理结束 ,ng-location模块中factory都已实例化好,ng-location退出栈。 回到ng模块,处理方式赘同。 +--------------+ | |ng| | +--------------+ | <hasRequire?>-----Y-------->requireAlreayTackled已处理 | new (Function.prototype.bind.apply(ngModule, args))(); 3.

在ngModule中 provider($compile,$compileProvider) .前文提到$provider.provider方法是往cacheProvider中添加Provider构型的方法。至此能窥探到至关重要的$compile了。

我们回顾下angular的工作过程: 寻找$rootElement ,创建一个injector,这个injector的invoke方法 可以实例化 形如['a',fucntion(a){}]数组的函数。 实际的代码如下 injector.invoke(['$rootScope', '$rootElement', '$compile', '$injector', function bootstrapApply(scope, element, compile, injector) { scope.$apply(function() { element.data('$injector', injector); compile(element)(scope); }); }] );

bootstrapApply会被执行。会调用rootScope.$apply(fn);

$apply(fn), 和 $digest() 是scope中的两个方法 , 该方法会触发 scope上watchers函数.watchers函数正是双向绑定中 data变化反应到ui element中的 机关所在。watch函数是在compilelink阶段绑定到element上的,因为定义指令时element会作为参数传给compilelink函数. $apply(fn) 实际上是先执行fn再调用$rootScope.$digest(); 后面会详细介绍scope.

上面说到 $apply(fn) 实际上是先执行fn; 执行过程 element.data('$injector', injector); compile(element)(scope);

下章讲解 compile, u element与数据间的因缘在compile展现

转载于:https://www.cnblogs.com/koushikan/p/5939401.html

相关资源:前端项目-svg.draggy.js.zip
最新回复(0)