AngularJS使用字符串作为控制器来解析
AngularJS使用字符串作为控制器来解析
我写Angular控制器的风格是这样的(使用控制器名称而不是函数):\n
angular.module('mymodule', []) .controller('myController', ['$scope', function($scope) { // 这里是一些代码 }]);
\n现在我需要在提供路由时定义resolve部分:\n
$routeProvider.when('/someroute', { templateUrl: 'partials/someroute.html', resolve: myController.resolve}) // 这是关键的一行
\n由于控制器被定义为一个名称,如何完成下面的resolve部分?\n更详细地说明,我想在路由解析之前从服务器加载一些数据,然后在控制器中使用这些数据。\n更新:更准确地说,我希望每个模块都有一个\"resolve\"函数,在执行具有该控制器的路由之前调用该函数。在这个帖子中的解决方案(由Misko Hevery回答)正是我想要的,但我不是将控制器作为函数而是作为名称。
在AngularJS中,可以使用resolve属性来定义在控制器加载之前需要解析的依赖项。通常,resolve属性的值是一个对象,其中的键是依赖项的名称,值是一个函数或一个数组。如果值是一个函数,它应该返回一个promise对象。如果值是一个数组,数组的最后一个元素应该是一个函数,它应该返回一个promise对象。resolve属性可以用来确保在控制器加载之前,所有的依赖项都被解析和注入。
然而,在某些情况下,当控制器以字符串的形式传递给AngularJS的controller方法时,resolve属性不起作用。这是因为当控制器以字符串形式传递时,AngularJS无法获取控制器的实例,因此无法将resolve属性的值与控制器实例相关联。
解决这个问题的方法是将控制器定义为一个变量,并将resolve属性添加到该变量上。然后,使用controller方法将该变量传递给AngularJS。这样,AngularJS就能够正确地解析resolve属性,并在控制器加载之前解析和注入所有的依赖项。
以下是正确使用resolve属性的示例代码:
var MyController = myApp.controller('MyController', ['$scope', 'myData', function($scope, myData) { // Some code here }]); MyController.resolve = { myData: ['$http', '$q', function($http, $q) { var defer = $q.defer(); $http.get('/foo/bar') .success(function(data) { defer.resolve(data); }) .error(function(error, status) { defer.reject(error); }); return defer.promise; }] };
在上面的代码中,我们首先定义了一个变量MyController,并将其设置为myApp.controller方法的返回值。然后,我们将resolve属性添加到MyController上,并定义了一个名为myData的依赖项。myData依赖项使用$http服务来获取数据,并返回一个promise对象。
最后,我们使用controller方法将MyController作为字符串传递给AngularJS。由于MyController是一个变量,而不是一个字符串,AngularJS能够正确地解析resolve属性,并在控制器加载之前解析和注入myData依赖项。
通过这种方式,我们可以确保在控制器加载之前,myData依赖项已经被解析和注入,从而避免了resolve属性不起作用的问题。
问题出现的原因是想要在AngularJS中使用resolve和controller作为字符串,而不是函数。解决方法是在路由文件中添加resolve属性,并将controller和resolve的值都作为字符串放入数组中。
首先,在模块中定义控制器和工厂函数,其中工厂函数返回一个promise。然后在控制器中使用resolved的工厂函数。代码如下:
angular.module('mymodule', []) .controller('myController', ['$scope', 'myModelCombination', function($scope, myModelCombination) { // myModelCombination[0] === (resolved) myModel // myModelCombination[1] === (resolved) myModel2 }]) .controller('myController2', ['$scope', 'myModel', function($scope, myModel) { // Some code here }]) .factory('myModel', ['$scope', function($scope) { // return a promise }]) .factory('myModel2', ['$scope', function($scope) { // return a promise }]) .factory('myModelCombination', ['$scope', 'myModel', 'myModel2', function($scope) { return $q.all(['myModel', 'myModel2']); }]);
然后在路由文件中添加resolve属性,并将controller和resolve的值都作为字符串放入数组中。代码如下:
$routeProvider.when('/someroute', { templateUrl: 'partials/someroute.html', resolve: ['myModel'] //ALWAYS IN ARRAY) }); $routeProvider.when('/myModelCombination', { templateUrl: 'partials/someroute2.html', resolve: ['myModel'] //ALWAYS IN ARRAY) });
最后,确保每个工厂函数只返回一个值或一个promise,除非希望等待所有promise完成并将它们一起返回。需要注意的是,工厂函数的返回值应该是一个promise。代码如下:
.factory('myModel', ['$scope', function($scope) { // return a promise }])
这样就可以在AngularJS中使用resolve和controller作为字符串了。详细的API文档可以参考http://docs.angularjs.org/api/ng.$routeProvider。
如果有多个promise需要返回,可以使用$q.all()方法将它们一起返回。代码如下:
.factory('myModelCombination', ['$scope', 'myModel', 'myModel2', function($scope) { return $q.all(['myModel', 'myModel2']); }]);
如果以上方法不起作用,可以尝试在fiddle中运行代码来进行调试。
AngularJS中,控制器定义和解析部分需要分别在路由定义中指定。
如果在模块级别上定义控制器,需要将它们作为字符串引用,如下所示:
$routeProvider.when('/someroute', { templateUrl: 'partials/someroute.html', controller: 'myController', resolve: { myVar: function(){ //在路由变化之前执行的代码 }; });
上面的代码还展示了如何定义一组在路由变化之前将被解析的变量。当这些变量被解析后,可以将它们注入到控制器中。所以根据上面的代码片段,你可以这样编写控制器:
.controller('myController', ['$scope', 'myVar', function($scope, myVar) { // myVar已经被解析并注入到这里 } ]);
这个视频也可能会有帮助:http://www.youtube.com/watch?v=P6KITGRQujQ
你可以将服务注入到控制器和解析函数中,如果这是你的问题的话...你能更具体一些吗?
在when()内部,'myController',
应该是controller: 'myController',
吗?
确实是这样的。已经修复了。
.opensource当我为路由的controller
属性提供一个字符串时,我会得到一个关于myVarProvider
未知的错误。有什么想法吗?
你使用的是哪个版本?
在这种情况下,resolve键的确切含义是什么?在这个例子中是"myVar"吗?
当我为路由的controller
属性提供一个字符串时,我也会遇到"provider unknown"的错误。然而,如果我使用一个函数,那么resolve属性就能成功注入,并且一切都很顺利。
我刚刚遇到了同样的问题,并在这里找到了答案:groups.google.com/forum/#!topic/angular/6nA4MEKyKAc。基本上,我还需要从我的视图中删除ng-controller,并让路由添加它以及解析后的数据。
太棒了,我不知道我可以直接从路由的解析部分将变量注入到控制器中,我一直在使用$route['current']['locals']来获取解析定义中的变量。
.opensource是否可以在解析中添加多个控制器,例如: controller: 'myController', 'secondController
, thirdController
?
AngularJS中的一个常见问题是在使用控制器字符串进行解析时出现错误。通常,在路由定义中,控制器定义和解析部分需要分别指定。如果在模块级别上定义控制器,需要将它们作为字符串引用。下面是一个示例的代码片段:
$routeProvider.when('/someroute', { templateUrl: 'partials/someroute.html', controller: 'myController', resolve: { myVar: function(){ //在路由变化之前执行的代码 }; });
上面的代码中,定义了一个将在路由变化之前解析的变量myVar。当这些变量被解析后,可以将它们注入到控制器中。以下是控制器的示例代码:
.controller('myController', ['$scope', 'myVar', function($scope, myVar) { // myVar已经被解析并注入到这里 }]);
通过这种方式,可以在控制器中使用解析后的变量。同时,还可以将服务注入到控制器和解析函数中。
此外,有一个视频也可以帮助解决这个问题。如果需要注入多个控制器,在解析部分可以添加多个控制器的引用。
如果使用控制器字符串进行解析时出现问题,可能是因为在路由定义中使用了错误的语法。可以参考相关文档或寻求社区的帮助来解决这个问题。
参考链接: