加载视图时运行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函数,因此标记isSaving
是undefined
。 我能做些什么来防止呢?
当你的视图加载时,其相关的控制器也是如此。 不要使用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 */ { // ... } });