当我加载视图时,我想在其关联的控制器中运行一些初始化代码。
为此,我在视图的主要元素上使用了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函数在<{strong> init()
函数之前被称为,因此标记isSaving
为undefined
。我该怎么做才能防止这种情况?
答案 0 :(得分:128)
当您的视图加载时,其关联的控制器也会加载。不要使用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();
如果要等待预设某些数据,请将该数据请求移至解析或将监视器添加到该集合或对象,并在数据符合初始条件时调用init方法。我通常会在满足数据要求后删除观察程序,因此如果您观察的数据发生变化并且符合运行init方法的条件,则init函数不会随机重新运行。
var init = function () {
// do something
}
...
var unwatch = scope.$watch('myCollecitonOrObject', function(newVal, oldVal){
if( newVal && newVal.length > 0) {
unwatch();
init();
}
});
答案 1 :(得分:27)
从AngularJS 1.5开始,我们应该使用任何AngularJS组件上的$onInit
。摘自自v1.5以来的component lifecycle documentation以其优先方式:
$ 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';
}
});
组件生命周期使我们能够以良好的方式处理组件。它允许我们为例如创建事件&#34; init&#34;,&#34;更改&#34;或&#34;销毁&#34;一个组件。通过这种方式,我们可以管理取决于组件生命周期的内容。这个小例子显示了注册&amp;取消注册$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();
}
});
答案 2 :(得分: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 }
}
答案 3 :(得分:13)
我在项目中使用以下模板:
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 */ {
// ...
}
});