无法访问指令中 $http.get 设置的范围 属性
Unable to access scope property set by $http.get in directive
我正在使用这个 app.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;
});
}]);
和这个 index.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="app\app.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;
});
因此,您会收到回复 a.e。延迟初始化 $scope.ninjas
。
您可以继续 2 个解决方案:
[解决方案 1]
当ninjas
不是undefined
时,使用ng-if
初始化指令
<random-ninja
ng-if="ninjas"
the-ninjas="ninjas"
title="'Random Ninja'">
</random-ninja>
[方案二]
使用 $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
绑定使用来自服务器的数据更新时更新组件指令。
注意:该指令需要使用单向(<
)绑定。
来自文档:
Life-cycle hooks
Directive controllers can provide the following methods that are called by AngularJS at points in the life-cycle of the directive:
$onChanges(changesObj)
- Called whenever one-way (<
) or interpolation (@
) bindings are updated. The changesObj
is a hash whose keys are the names of the bound properties that have changed, and the values are an object of the form { currentValue, previousValue, isFirstChange() }
. Use this hook to trigger updates within a component such as cloning the bound value to prevent accidental mutation of the outer value. Note that this will also be called when your bindings are initialized.
有关详细信息,请参阅
我正在使用这个 app.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;
});
}]);
和这个 index.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="app\app.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;
});
因此,您会收到回复 a.e。延迟初始化 $scope.ninjas
。
您可以继续 2 个解决方案:
[解决方案 1]
当ninjas
不是undefined
ng-if
初始化指令
<random-ninja
ng-if="ninjas"
the-ninjas="ninjas"
title="'Random Ninja'">
</random-ninja>
[方案二]
使用 $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
绑定使用来自服务器的数据更新时更新组件指令。
注意:该指令需要使用单向(<
)绑定。
来自文档:
Life-cycle hooks
Directive controllers can provide the following methods that are called by AngularJS at points in the life-cycle of the directive:
$onChanges(changesObj)
- Called whenever one-way (<
) or interpolation (@
) bindings are updated. ThechangesObj
is a hash whose keys are the names of the bound properties that have changed, and the values are an object of the form{ currentValue, previousValue, isFirstChange() }
. Use this hook to trigger updates within a component such as cloning the bound value to prevent accidental mutation of the outer value. Note that this will also be called when your bindings are initialized.
有关详细信息,请参阅