AngularJS-源碼閱讀(七)

如今開始看module的初始化。html

function setupModuleLoader(window) {//初始化angular以及和angular捆綁的第一個module
      var $injectorMinErr = minErr('$injector');
      var ngMinErr = minErr('ng');

      function ensure(obj, name, factory) {
       return obj[name] || (obj[name] = factory());
  }

  var angular = ensure(window, 'angular', Object);//每個window下面只有一個angular實例的緣由

  // We need to expose `angular.$$minErr` to modules such as `ngResource` that reference it during bootstrap
  //ensure(angular,'$$minErr',minErr);
  angular.$$minErr = angular.$$minErr || minErr;

  return ensure(angular, 'module', function() {//向angular寫入module初始化函數
    /** @type {Object.<string, angular.Module>} */
    var modules = {};//記錄一loadModules個angularjs下面全部的modules


    return function module(name, requires, configFn) {
      var assertNotHasOwnProperty = function(name, context) {
        if (name === 'hasOwnProperty') {
          throw ngMinErr('badname', 'hasOwnProperty is not a valid {0} name', context);
        }
      };

      assertNotHasOwnProperty(name, 'module');
      if (requires && modules.hasOwnProperty(name)) {
        modules[name] = null;//同名時,覆蓋掉老的。感受這個地方應該報錯,而不是覆蓋
      }
      return ensure(modules, name, function() {
        if (!requires) {
          throw $injectorMinErr('nomod', "Module '{0}' is not available! You either misspelled " +
             "the module name or forgot to load it. If registering a module ensure that you " +
             "specify the dependencies as the second argument.", name);
        }

        /** @type {!Array.<Array.<*>>} */
        var invokeQueue = [];

        /** @type {!Array.<Function>} */
        var runBlocks = [];

        var config = invokeLater('$injector', 'invoke');//instanceCache.$injector =

        /** @type {angular.Module} */
        var moduleInstance = {
          // Private state
          _invokeQueue: invokeQueue,//用來記錄注入到本module實例下面的各類具體方法函數。
          _runBlocks: runBlocks,

          requires: requires,

          name: name,


          provider: invokeLater('$provide', 'provider'),//$provide來自於上一節講的providerCache

          factory: invokeLater('$provide', 'factory'),

          service: invokeLater('$provide', 'service'),

          value: invokeLater('$provide', 'value'),

          constant: invokeLater('$provide', 'constant', 'unshift'),

          animation: invokeLater('$animateProvider', 'register'),

          filter: invokeLater('$filterProvider', 'register'),

      controller: invokeLater('$controllerProvider', 'register'),//這些provider之後挑着講解

      directive: invokeLater('$compileProvider', 'directive'),

      config: config,

      run: function(block) {
        runBlocks.push(block);
        return this;
      }
    };

    if (configFn) {
      config(configFn);//這也是爲何moduleconfig爲function,按代碼邏輯來說它是支持注入的,但因爲加載順序,只能注入requires module裏的attr
    }

    return  moduleInstance;

    /**
     * @param {string} provider
     * @param {string} method
     * @param {String=} insertMethod
     * @returns {angular.Module}
     * 延遲加載
     */
    function invokeLater(provider, method, insertMethod) {
      return function() {
        invokeQueue[insertMethod || 'push']([provider, method, arguments]);
        return moduleInstance;
      };
    }
  });
};

});angularjs

總結一下,就是返回module建立函數,這個函數會建立module實例以及注入controller、directive、factory等。bootstrap

var angularModule = setupModuleLoader(window);
try {
    angularModule('ngLocale');
} catch (e) {
    angularModule('ngLocale', []).provider('$locale', $LocaleProvider);//$LocaleProvider記錄默認日期分隔符等信息
    //這個地方,感受沒必要要try catch ,直接angularModule('ngLocale', []).provider('$locale', $LocaleProvider);。前提是        module(name)name屢次相同時,報錯。
}


 angularModule('ng', ['ngLocale'], ['$provide',
    function ngModule($provide) {
      // $$sanitizeUriProvider needs to be before $compileProvider as it is used by it.
      $provide.provider({
        $$sanitizeUri: $$SanitizeUriProvider//格式化Uri 
      });
      //$CompileProvider的源碼1500行+。這裏不講
      $provide.provider('$compile', $CompileProvider).
        directive({
        a: htmlAnchorDirective,
        ...//各類內置directive的注入。之後挑着講
        });
       ...//依舊是directive 的注入
      $provide.provider({
        $anchorScroll: $AnchorScrollProvider,
        ...//provider的注入,之後挑着講
      });
    }
  ]);
}

爲module注入內置的函數。並命名爲ngmodule。ide

相關文章
相關標籤/搜索