Javascript 在Angular中,如何将JSON对象/数组传递到指令中?
目前,我的应用程序有一个控制器,它接收一个JSON文件,然后使用“ng repeat”对它们进行迭代。这一切都很好,但我还有一个指令需要遍历同一个JSON文件。这是一个问题,因为我不能在一个页面上两次请求同一个JSON文件(我也不想这样做,因为这样会效率低下)。如果我更改其中一个JSON文件的文件名,指令和控制器都会请求并迭代JSON数据 我想知道的是:将控制器的JSON请求形成的数组传递到指令中的最佳方式是什么?当我已经通过控制器访问数组时,如何将数组传递到指令中并进行迭代 控制器Javascript 在Angular中,如何将JSON对象/数组传递到指令中?,javascript,json,angularjs,angularjs-directive,angularjs-ng-repeat,Javascript,Json,Angularjs,Angularjs Directive,Angularjs Ng Repeat,目前,我的应用程序有一个控制器,它接收一个JSON文件,然后使用“ng repeat”对它们进行迭代。这一切都很好,但我还有一个指令需要遍历同一个JSON文件。这是一个问题,因为我不能在一个页面上两次请求同一个JSON文件(我也不想这样做,因为这样会效率低下)。如果我更改其中一个JSON文件的文件名,指令和控制器都会请求并迭代JSON数据 我想知道的是:将控制器的JSON请求形成的数组传递到指令中的最佳方式是什么?当我已经通过控制器访问数组时,如何将数组传递到指令中并进行迭代 控制器 appCo
appControllers.controller('dummyCtrl', function ($scope, $http) {
$http.get('locations/locations.json').success(function(data) {
$scope.locations = data;
});
});
HTML
<ul class="list">
<li ng-repeat="location in locations">
<a href="#">{{location.id}}. {{location.name}}</a>
</li>
</ul>
<map></map> //executes a js library
-
//执行js库
指令(在我使用locations.json之外的文件名时有效,因为我已经请求过一次了
.directive('map', function($http) {
return {
restrict: 'E',
replace: true,
template: '<div></div>',
link: function(scope, element, attrs) {
$http.get('locations/locations.json').success(function(data) {
angular.forEach(data.locations, function(location, key){
//do something
});
});
指令('map',函数($http){
返回{
限制:'E',
替换:正确,
模板:“”,
链接:函数(范围、元素、属性){
$http.get('locations/locations.json').success(函数(数据){
角度.forEach(数据.位置,功能(位置,键){
//做点什么
});
});
正如您所说,您不需要两次请求该文件。将其从控制器传递到指令。假设您在控制器范围内使用该指令:
.controller('MyController', ['$scope', '$http', function($scope, $http) {
$http.get('locations/locations.json').success(function(data) {
$scope.locations = data;
});
}
然后在HTML中(您在其中调用指令)。注意:
locations
是对控制器的引用$scope.locations
<div my-directive location-data="locations"></div>
这只是一个为您指明正确方向的大纲,因此它不完整且未经测试。您需要的是正确的服务:
.factory('DataLayer', ['$http',
function($http) {
var factory = {};
var locations;
factory.getLocations = function(success) {
if(locations){
success(locations);
return;
}
$http.get('locations/locations.json').success(function(data) {
locations = data;
success(locations);
});
};
return factory;
}
]);
位置
将缓存在作为单例模型工作的服务中。这是获取数据的正确方法
在控制器中使用此服务DataLayer
,指令正常,如下所示:
appControllers.controller('dummyCtrl', function ($scope, DataLayer) {
DataLayer.getLocations(function(data){
$scope.locations = data;
});
});
.directive('map', function(DataLayer) {
return {
restrict: 'E',
replace: true,
template: '<div></div>',
link: function(scope, element, attrs) {
DataLayer.getLocations(function(data) {
angular.forEach(data, function(location, key){
//do something
});
});
}
};
});
appControllers.controller('dummyCtrl',函数($scope,DataLayer){
DataLayer.getLocations(函数(数据){
$scope.locations=数据;
});
});
.directive('map',函数(数据层){
返回{
限制:'E',
替换:正确,
模板:“”,
链接:函数(范围、元素、属性){
DataLayer.getLocations(函数(数据){
角度.forEach(数据、功能(位置、键){
//做点什么
});
});
}
};
});
如果你想遵循所有的“最佳实践”,我建议你做几件事,其中一些会在这个问题的其他答案和评论中提到
首先,虽然它对您提出的特定问题没有太大影响,但您确实提到了效率,在应用程序中处理共享数据的最佳方法是将其分解到服务中 我个人建议采用AngularJS,这将使您的异步服务比原始回调更具可组合性。幸运的是,Angular的
$http
服务已经在幕后使用了它们。这里有一个服务将返回解析JSON文件中数据的承诺;在将不会导致第二个HTTP请求
app.factory('locations',函数($http){
var-promise=null;
返回函数(){
如果(承诺){
//如果我们已经问过一次这个数据,
//返回已经存在的承诺。
回报承诺;
}否则{
promise=$http.get('locations/locations.json');
回报承诺;
}
};
});
至于将数据输入到指令中,重要的是要记住,指令是为抽象通用DOM操作而设计的;您不应该将它们注入特定于应用程序的服务。在这种情况下,只需将
locations
服务注入指令中就很有诱惑力,但这会将指令与那项服务
关于代码模块化的简短旁白:指令的函数几乎不应该负责获取或格式化它们自己的数据。没有什么可以阻止您在指令中使用$http服务,但这几乎总是错误的。编写控制器以使用$http是正确的方法。指令lready涉及一个DOM元素,它是一个非常复杂的对象,很难进行测试。将网络I/O添加到混合中会使您的代码更难理解,也更难测试。此外,网络I/O会以指令获取数据的方式锁定—可能在您需要的其他地方t使此指令从套接字接收数据或接收预加载的数据。您的指令应通过scope.$eval将数据作为属性接收,和/或使用控制器处理数据的获取和存储
-
在这种特定情况下,您应该在控制器的作用域上放置适当的数据,并通过属性与指令共享数据
app.controller('SomeController',函数($scope,locations){
位置().成功(函数(数据){
$scope.locations=数据;
});
});
-
app.directive('map',function(){
返回{
限制:'E',
替换:正确,
模板:“”,
范围:{
//在指令中创建范围变量
//被称为绑定到所传递内容的“位置”
//在中,通过DOM中的“locations”属性
位置:'=位置'
},
链接:函数(范围、元素、属性){
范围:$watch('位置'),功能(位置){
角速度(位置、功能(l
appControllers.controller('dummyCtrl', function ($scope, DataLayer) {
DataLayer.getLocations(function(data){
$scope.locations = data;
});
});
.directive('map', function(DataLayer) {
return {
restrict: 'E',
replace: true,
template: '<div></div>',
link: function(scope, element, attrs) {
DataLayer.getLocations(function(data) {
angular.forEach(data, function(location, key){
//do something
});
});
}
};
});