AngularJS 控制器在 jquery 文档就绪回调之前调用

AngularJS controller called before jquery document ready callback

我有两个 Angular 1.x 控制器和一个外部开源库,在文档准备就绪时初始化如下,

 $(function () {
    $.support.x = 10;
 });

所以我加载 JS 文件的顺序是 1. Angular 框架 2. 这个外部 OS 库 3. 我的 AngularJS 控制器

一旦我加载页面,开源库的 document.ready(jquery) 不会首先被调用,而是控制首先进入 AngularJS 控制器构造函数。 controller执行完成后,只调用document.ready(jquery)

我在这里简化了上下文,但在我的控制器之前还有其他 javascript 文件。我的疑惑是,

  1. 为什么首先加载控制器?
  2. 这与我的 JS 文件的排序有关吗?
  3. Angular无论其他document.ready(jquery)方法如何,JS首先加载 在其他 JS 库中 ?

提前致谢。

您在使用 ng-app 吗?如果是这样,您可以 bootstrap angular 手册并删除 ng-app

document.ready(function{
    angular.bootstrap(document, ['myApp']);
})

然后angular会在dom准备好后运行 angular bootstrap

来自docs

AngularJS initializes automatically upon DOMContentLoaded event or when the angular.js script is evaluated if at that time document.readyState is set to complete.

所以:

1) 我认为这是因为 angular.js 脚本比任何 $(document).ready(function(){}); 处理程序更早,并且 angularjs 在该处理程序被触发之前开始引导;

2) 是的。看看这两个例子(不同之处仅在于 angular.js 脚本位置):

angular.module('myApp', [])
.controller('MyCtrl', ['$scope', '$timeout', function MyCtrl($scope, $timeout) {
    var ctrl = this;
    console.log('ctrl');  
    return ctrl;
}]);
<div ng-app="myApp">
  <div ng-controller="MyCtrl as $ctrl">  
  </div>
</div>

<script src="//ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script>
$(document).ready(function(){
    console.log('doc');
});
</script>
<script src="//code.angularjs.org/1.6.2/angular.js"></script>

和:

angular.module('myApp', [])
.controller('MyCtrl', ['$scope', '$timeout', function MyCtrl($scope, $timeout) {
    var ctrl = this;
    console.log('ctrl');  
    return ctrl;
}]);
<div ng-app="myApp">
  <div ng-controller="MyCtrl as $ctrl">  
  </div>
</div>
<script src="//ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="//code.angularjs.org/1.6.2/angular.js"></script>
<script>
$(document).ready(function(){
    console.log('doc');
});
</script>

对于第一个,输出将是 doc-ctrl,对于第二个,输出将是 ctrl-doc

3) 默认情况下,它会按照引用中的描述进行加载。但是你可以使用manual initialization来控制进程。无论什么时候包含angular.js脚本,输出的顺序都是doc - stuff.loaded -> do bootstrap - ctrl

angular.module('myApp', [])
.controller('MyCtrl', ['$scope', '$timeout', function MyCtrl($scope, $timeout) {
    var ctrl = this;
    console.log('ctrl');  
    return ctrl;
}]);
<div>
  <div ng-controller="MyCtrl as $ctrl">  
  </div>
</div>

<script src="//ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="//code.angularjs.org/1.6.2/angular.js"></script>

<script>
$(document).on('stuff.loaded', function(){
  console.log("stuff.loaded -> do bootstrap");
  //manually bootstrap angularjs app
  angular.element(function() {
    angular.bootstrap(document, ['myApp']);
  });
});
</script>

<script>
$(document).ready(function(){
  console.log('doc');
  //some your stuff here 
  //...
  $(document).trigger('stuff.loaded');
});
</script>