你能帮我理解一下如何在视图之前加载下面示例中的控制器吗?它看起来就像是在控制器还没有加载的时候立即加载视图。
//app.js
$stateProvider.state('index', {
url: "/",
views: {
"topMenu": {
templateUrl: "/Home/TopMenu",
controller: function($scope, $injector) {
require(['controllers/top-menu-controller'], function(module) {
$injector.invoke(module, this, { '$scope': $scope });
});
}
}
}
});
//top-menu-controller.js
define(['app'], function (app) {
app.controller('TopMenuCtrl', ['$scope', function ($scope) {
$scope.message = "It works";
}]);
});
//Home/TopMenu
<h3>TopMenu</h3>
<div ng-controller="TopMenuCtrl">
{{message}}
</div>发布于 2015-01-03 18:50:59
I created working plunker here。
让我们使用这个index.html
<!DOCTYPE html>
<html>
<head>
<title>my lazy</title>
</head>
<body ng-app="app">
<a href="#/home">#/home</a> // we have three states - 'home' is NOT lazy
<a href="#/">#/</a> - index // 'index' is lazy, with two views
<a href="#/other">#/other</a> // 'other' is lazy with unnamed view
<div data-ui-view="topMenu"></div>
<div data-ui-view=""></div>
<script src="angular.js"></script> // standard angular
<script src="angular-ui-router.js"></script> // and ui-router scritps
<script src="script.js"></script> // our application
<script data-main="main.js" // lazy dependencies
src="require.js"></script>
</body>
</html>让我们观察一下main.js - RequireJS配置:
require.config({
//baseUrl: "js/scripts",
baseUrl: "",
// alias libraries paths
paths: {
// here we define path to NAMES
// to make controllers and their lazy-file-names independent
"TopMenuCtrl": "Controller_TopMenu",
"ContentCtrl": "Controller_Content",
"OtherCtrl" : "Controller_Other",
},
deps: ['app']
});实际上,我们只为ControllerNames及其Controller_Scripts.js文件创建别名(路径)。就这样。此外,我们返回请求应用程序,但我们将在稍后使用不同的功能-注册延迟加载的控制器。
deps: ['app']是什么意思?首先,我们需要提供app.js ( 'app‘的意思是查找app.js__):
define([], function() {
var app = angular.module('app');
return app;
})此返回值是我们可以在每个异步加载的文件中请求的值
define(['app'], function (app) {
// here we would have access to the module("app")
});我们如何懒惰地加载控制器?这里已经为ngRoute证明了这一点
angularAMD是一个实用程序,可促进在支持按需加载第三方模块(如angular-ui )的AngularJS应用程序中使用RequireJS。
我们将向angular请求$controllerProvider的引用--稍后使用它来注册控制器。
这是我们script.js的第一部分
// I. the application
var app = angular.module('app', [
"ui.router"
]);
// II. cached $controllerProvider
var app_cached_providers = {};
app.config(['$controllerProvider',
function(controllerProvider) {
app_cached_providers.$controllerProvider = controllerProvider;
}
]);正如我们所看到的,我们刚刚创建了应用程序'app‘,还创建了holder app_cached_providers (遵循angularAMD风格)。在配置阶段,我们向angular请求$controllerProvider并保留它的引用。
现在让我们继续script.js
// III. inline dependency expression
app.config(['$stateProvider', '$urlRouterProvider',
function($stateProvider, $urlRouterProvider) {
$urlRouterProvider
.otherwise("/home");
$stateProvider
.state("home", {
url: "/home",
template: "<div>this is home - not lazily loaded</div>"
});
$stateProvider
.state("other", {
url: "/other",
template: "<div>The message from ctrl: {{message}}</div>",
controller: "OtherCtrl",
resolve: {
loadOtherCtrl: ["$q", function($q) {
var deferred = $q.defer();
require(["OtherCtrl"], function() { deferred.resolve(); });
return deferred.promise;
}],
},
});
}
]);上面的这部分显示了两个状态声明。其中之一- 'home'是标准的,不是懒惰的。它的控制器是隐式的,但可以使用标准。
第二个是以未命名视图ui-view=""为目标的名为"other"的状态。在这里,我们首先可以看到,惰性负载。在resolve内部(请参见:)
您可以使用resolve为控制器提供自定义状态的内容或数据。resolve是一个可选的依赖映射,它应该被注入到控制器中。
如果这些依赖项中的任何一个是promises,那么在控制器实例化和触发$stateChangeSuccess事件之前,它们将被解析并转换为一个值。
在我们的套件中,我们知道,一旦解析完成,将在angular存储库中搜索控制器(按其名称):
// this controller name will be searched - only once the resolve is finished
controller: "OtherCtrl",
// let's ask RequireJS
resolve: {
loadOtherCtrl: ["$q", function($q) {
// wee need $q to wait
var deferred = $q.defer();
// and make it resolved once require will load the file
require(["OtherCtrl"], function() { deferred.resolve(); });
return deferred.promise;
}],
},很好,现在,正如上面提到的,main包含这个别名def
// alias libraries paths
paths: {
...
"OtherCtrl" : "Controller_Other",这意味着,将搜索并加载文件"Controller_Other.js“。这就是它的内容,它实现了神奇的。这里最重要的是使用以前缓存的对$controllerProvider的引用
// content of the "Controller_Other.js"
define(['app'], function (app) {
// the Default Controller
// is added into the 'app' module
// lazily, and only once
app_cached_providers
.$controllerProvider
.register('OtherCtrl', function ($scope) {
$scope.message = "OtherCtrl";
});
});诀窍不是使用app.controller(),而是
Angular使用$controller服务来创建新的控制器。此提供程序允许通过
register()方法进行控制器注册。
最后还有另一个状态定义,具有更窄的分辨率...试着让它更具可读性:
// IV ... build the object with helper functions
// then assign to state provider
var loadController = function(controllerName) {
return ["$q", function($q) {
var deferred = $q.defer();
require([controllerName], function() {deferred.resolve(); });
return deferred.promise;
}];
}
app.config(['$stateProvider', '$urlRouterProvider',
function($stateProvider, $urlRouterProvider) {
var index = {
url: "/",
views: {
"topMenu": {
template: "<div>The message from ctrl: {{message}}</div>",
controller: "TopMenuCtrl",
},
"": {
template: "<div>The message from ctrl: {{message}}</div>",
controller: "ContentCtrl",
},
},
resolve : { },
};
index.resolve.loadTopMenuCtrl = loadController("TopMenuCtrl");
index.resolve.loadContentCtrl = loadController("ContentCtrl");
$stateProvider
.state("index", index);
}]);上面我们可以看到,我们为该状态的两个/所有命名视图解析了两个控制器
就这样。此处定义的每个控制器
paths: {
"TopMenuCtrl": "Controller_TopMenu",
"ContentCtrl": "Controller_Content",
"OtherCtrl" : "Controller_Other",
...
},将通过resolve和$controllerProvider -通过RequireJS -延迟加载。检查所有here
发布于 2014-09-09 21:07:41
在一个项目中,我使用了延迟加载控制器,并且必须手动调用作用域上的$digest才能使其正常工作。我猜这个行为不会随着ui-router的变化而改变。你试过了吗?
define(['app'], function (app) {
app.controller('TopMenuCtrl', ['$scope', function ($scope) {
$scope.message = "It works";
$scope.$digest();
}]);
});https://stackoverflow.com/questions/22627806
复制相似问题