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
今天的文章injector解析分享到此就结束了,感谢您的阅读。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/7168.html