无法访问 $http.get in 指令设置的范围属性



我正在使用这个应用程序.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+ 组件不支持观察程序,解决方法是什么?

相关内容

  • 没有找到相关文章

最新更新