injector解析

injector解析injector有两种类型,ProviderInjector和InstanceInjector.两者get方法执行起来有差异ProviderInjector的结构如下:`{get:functiongetService(serviceName){returncacheProvider[serviceName];}}`InstanceInjector结构…

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

(0)
编程小号编程小号

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注