我正在使用这个应用程序.js文件:
var myNinjaApp = angular.module('myNinjaApp', []);
myNinjaApp.directive('randomNinja', [function(){
return {
restrict: 'E',
scope: {
theNinjas: '=',
title: '='
},
template: '<img ng-src="{{theNinjas[random].thumb}}"/>',
controller: function($scope) {
let length = $scope.theNinjas.length; //$scope.theNinjas is undefined
$scope.random = Math.floor(Math.random() * length);
console.log($scope.random);
}
};
}]);
myNinjaApp.controller('NinjaController', ['$scope', '$http', function($scope, $http) {
$http.get('data/ninjas.json').then(function(data){
$scope.ninjas = data.data;
});
}]);
和这个索引.html文件:
<!DOCTYPE html>
<html lang="en" ng-app="myNinjaApp">
<head>
<title>TheNetNinja Angular Playlist</title>
<link href="content/css/styles.css" rel="stylesheet" type="text/css" />
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.9/angular.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-route/1.7.9/angular-route.min.js"></script>
<script src="appapp.js"></script>
</head>
<body ng-controller="NinjaController">
<random-ninja the-ninjas="ninjas" title="'Random Ninja'"></random-ninja>
</body>
</html>
我注意到在指令的控制器代码中,$scope.theNinjas
是未定义的,但title
没有。
当我调试代码时,我可以看到$http.get()
调用是在读取$scope.theNinjas.length
后进行的。
如何在指令的控制器中获取数组的长度?
你的问题是,$http.get
是异步的,
$http.get('data/ninjas.json').then(function(data){
$scope.ninjas = data.data;
});
因此,您会收到一个响应,即延迟初始化$scope.ninjas
。
您可以使用2个解决方案:
[解决方案 1]
使用ng-if
在未ninjas
时初始化指令undefined
<random-ninja
ng-if="ninjas"
the-ninjas="ninjas"
title="'Random Ninja'">
</random-ninja>
[解决方案 2]
使用$watch
侦听ninjas
更改,并在$scope.theNinjas
具有与undefined
不同的值时调用一些run
方法。之后,通过拨打unreg()
停止观看
let length = 0;
var unreg = $scope.$watch(function () {
return $scope.theNinjas;
},
function (newVal, oldVal) {
if (newVal !== undefined) {
run(newVal);
unreg();
}
});
function run(){
length = $scope.theNinjas.length;
$scope.random = Math.floor(Math.random() * length);
console.log($scope.random);
}
另一种方法是使用$onChanges
生命周期钩子:
myNinjaApp.directive('randomNinja', [function(){
return {
restrict: 'E',
scope: {
̶t̶h̶e̶N̶i̶n̶j̶a̶s̶:̶ ̶'̶=̶'̶,̶
theNinjas: '<',
title: '<'
},
template: '<img ng-src="{{theNinjas[random].thumb}}"/>',
controller: function($scope) {
this.$onChanges = function(changesObj) {
if (changesObj.theNinjas) {
let length = changesObj.theNinjas.currentValue.length;
$scope.random = Math.floor(Math.random() * length);
console.log($scope.random);
};
};
}
};
}]);
当使用来自服务器的数据更新theNinjas
绑定时,这将更新组件指令。
注意:对于此方法,指令需要使用单向(<
(绑定。
从文档中:
生命周期挂钩
指令控制器可以提供以下方法,这些方法由 AngularJS 在指令生命周期的点调用:
$onChanges(changesObj)
- 每当单向(<
(或插值(@
(绑定更新时调用。changesObj
是一个哈希,其键是已更改的绑定属性的名称,值是形式为{ currentValue, previousValue, isFirstChange() }
的对象。使用此挂钩可触发组件中的更新,例如克隆绑定值以防止外部值意外更改。请注意,初始化绑定时也会调用它。
有关详细信息,请参阅
- AngularJS 综合指令 API 参考 - 生命周期钩子
- AngularJS 开发人员指南 - 基于组件的应用程序架构
- AngularJS 1.5+ 组件不支持观察程序,解决方法是什么?