95

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

为此,我在视图的主要元素上使用了 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;
}

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

接下来,我对发生的事件顺序有疑问。在视图中,我有一个“保存”按钮,它使用如下ng-disabled指令:

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

isClean()功能在控制器中定义:

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

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

问题:加载视图时,isClean 函数在函数之前init()调用,因此标志isSavingundefined. 我能做些什么来防止这种情况发生?

4

4 回答 4

138

当您的视图加载时,其关联的控制器也会加载。而不是 using ,只需在控制器中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


如果您想等待某些数据被预设,要么将该数据请求移至解析,要么将观察者添加到该集合或对象,并在您的数据满足您的 init 标准时调用您的 init 方法。一旦满足我的数据要求,我通常会删除观察者,因此如果您观察的数据发生变化并符合您运行 init 方法的标准,init 函数不会随机重新运行。

var init = function () {
    // do something
}
...
var unwatch = scope.$watch('myCollecitonOrObject', function(newVal, oldVal){
                    if( newVal && newVal.length > 0) {
                        unwatch();
                        init();
                    }
                });
于 2013-04-22T17:34:41.567 回答
39

从 AngularJS 1.5 开始,我们应该使用$onInit在任何 AngularJS 组件上都可用的。取自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';
    }
});

>>小提琴演示


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

组件生命周期使我们能够以良好的方式处理组件。它允许我们为组件的“init”、“change”或“destroy”创建事件。通过这种方式,我们能够管理取决于组件生命周期的东西。这个小例子展示了注册和注销一个$rootScope事件监听器$on。通过知道,当控制器在视图中丢失其引用或被销毁时,$on绑定的事件$rootScope将不会被取消,我们需要手动销毁$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();
  }
});

>>小提琴演示

于 2017-04-08T23:29:01.060 回答
17

或者您可以在控制器中初始化内联。如果您使用控制器内部的 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 }
}
于 2013-04-22T19:41:14.120 回答
14

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

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  */ {
            // ...
        }

    });
于 2015-06-05T11:31:25.123 回答