加载视图时运行AngularJS初始化代码

当我加载一个视图,我想在其相关的控制器中运行一些初始化代码。

为此,我在视图的主要元素上使用了ng-init指令:

<div ng-init="init()"> blah </div> 

并在控制器中:

 $scope.init = function () { if ($routeParams.Id) { //get an existing object }); } else { //create a new object } $scope.isSaving = false; } 

第一个问题:这是正确的做法吗?

接下来,我遇到了一系列事件。 在视图中,我有一个“保存”button,它使用ng-disabled指令:

 <button ng-click="save()" ng-disabled="isClean()">Save</button> 

isClean()函数在控制器中定义:

 $scope.isClean = function () { return $scope.hasChanges() && !$scope.isSaving; } 

如您所见,它使用$scope.isSaving标志,它在init()函数中被初始化。

问题:加载视图时,在init()函数之前调用isClean函数,因此标记isSavingundefined 。 我能做些什么来防止呢?

当你的视图加载时,其相关的控制器也是如此。 不要使用ng-init ,只需在控制器中调用init()方法即可:

 $scope.init = function () { if ($routeParams.Id) { //get an existing object } else { //create a new object } $scope.isSaving = false; } ... $scope.init(); 

由于你的控制器在ng-init之前运行,这也解决了你的第二个问题。

小提琴


正如John David Five提到的,为了使这个方法是私有的,你可能不想把它附加到$scope

 var init = function () { // do something } ... init(); 

见jsFiddle


如果要等待某些数据被预设,请将该数据请求移至某个parsing,或者将观察者添加至该集合或对象,并在数据满足init标准时调用init方法。 当我的数据需求被满足时,我通常会移除监视器,所以如果你观察的数据发生变化,并且符合你的标准来运行你的init方法,init函数不会随机的重新运行。

 var init = function () { // do something } ... var unwatch = scope.$watch('myCollecitonOrObject', function(newVal, oldVal){ if( newVal && newVal.length > 0) { unwatch(); init(); } }); 

或者你可以在控制器中初始化内联。 如果使用控制器内部的init函数,则不需要在范围中定义。 事实上,它可以自我执行:

 function MyCtrl($scope) { $scope.isSaving = false; (function() { // init if (true) { // $routeParams.Id) { //get an existing object } else { //create a new object } })() $scope.isClean = function () { return $scope.hasChanges() && !$scope.isSaving; } $scope.hasChanges = function() { return false } } 

由于AngularJS 1.5我们应该使用任何AngularJS组件上的$onInit 。 从v1.5开始,从组件生命周期文档中获取它的优先方式:

$ onInit() – 在一个元素上的所有控制器都被构造并且初始化了绑定(并且在这个元素上的指令的前后链接函数之前)之后,在每个控制器上调用。 这是放置控制器初始化代码的好地方。

 var myApp = angular.module('myApp',[]); myApp.controller('MyCtrl', function ($scope) { //default state $scope.name = ''; //all your init controller goodness in here this.$onInit = function () { $scope.name = 'Superhero'; } }); 

>> 小提琴演示


使用组件生命周期的高级示例:

组件生命周期使我们能够以一种好的方式处理组件。 它允许我们创build一个事件,例如一个组件的“init”,“change”或“destroy”。 这样我们就可以pipe理取决于组件生命周期的东西。 这个小例子显示注册和注销一个$rootScope事件监听器$on 。 通过了解,绑定在$rootScope $on的事件$on不会在控制器在视图中丢失引用或被销毁的时候被忽略,我们需要手工销毁$rootScope.$on 。 放置这些东西的好地方是一个组件的$onDestroy生命周期函数:

 var myApp = angular.module('myApp',[]); myApp.controller('MyCtrl', function ($scope, $rootScope) { var registerScope = null; this.$onInit = function () { //register rootScope event registerScope = $rootScope.$on('someEvent', function(event) { console.log("fired"); }); } this.$onDestroy = function () { //unregister rootScope event by calling the return function registerScope(); } }); 

>> 小提琴演示

我在我的项目中使用以下模板:

 angular.module("AppName.moduleName", []) /** * @ngdoc controller * @name AppName.moduleName:ControllerNameController * @description Describe what the controller is responsible for. **/ .controller("ControllerNameController", function (dependencies) { /* type */ $scope.modelName = null; /* type */ $scope.modelName.modelProperty1 = null; /* type */ $scope.modelName.modelPropertyX = null; /* type */ var privateVariable1 = null; /* type */ var privateVariableX = null; (function init() { // load data, init scope, etc. })(); $scope.modelName.publicFunction1 = function () /* -> type */ { // ... }; $scope.modelName.publicFunctionX = function () /* -> type */ { // ... }; function privateFunction1() /* -> type */ { // ... } function privateFunctionX() /* -> type */ { // ... } });