首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >在Angular中,如何将JSON对象/数组传入指令?

在Angular中,如何将JSON对象/数组传入指令?
EN

Stack Overflow用户
提问于 2014-02-10 09:26:13
回答 3查看 101.1K关注 0票数 52

目前,我的应用程序有一个控制器,它接受一个JSON文件,然后使用"ng-repeat“遍历它们。这一切都很好用,但是我还有一个指令需要遍历相同的JSON文件。这带来了一个问题,因为我不能在一个页面上请求相同的JSON文件两次(我也不想这样做,因为这样效率会很低)。如果我更改了其中一个JSON文件的文件名,那么指令和控制器都可以请求和迭代JSON数据。

我想知道的是:将控制器的JSON请求形成的数组传递到指令中的最佳方法是什么?当我已经通过我的控制器访问数组时,我如何将数组传递到我的指令中并遍历它?

控制器

代码语言:javascript
复制
appControllers.controller('dummyCtrl', function ($scope, $http) {
   $http.get('locations/locations.json').success(function(data) {
      $scope.locations = data;
   });
});

HTML

代码语言:javascript
复制
<ul class="list">
   <li ng-repeat="location in locations">
      <a href="#">{{location.id}}. {{location.name}}</a>
   </li>
</ul>
<map></map> //executes a js library

指令(当我使用locations.json以外的文件名时有效,因为我已经请求过一次

代码语言:javascript
复制
.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
   });
});
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2014-02-10 11:52:49

如果你想遵循所有的“最佳实践”,我会推荐一些东西,其中一些在这个问题的其他答案和评论中涉及到。

首先,虽然它对您提出的特定问题没有太大影响,但您确实提到了效率,并且在应用程序中处理共享数据的最佳方法是将其分解到服务中。

我个人推荐使用AngularJS的promise system,与原始回调相比,它将使您的异步服务更具可组合性。幸运的是,Angular的$http服务已经在幕后使用它们。下面的服务将返回解析来自JSON文件的数据的承诺;多次调用该服务不会导致第二个HTTP请求。

代码语言:javascript
复制
app.factory('locations', function($http) {
  var promise = null;

  return function() {
    if (promise) {
      // If we've already asked for this data once,
      // return the promise that already exists.
      return promise;
    } else {
      promise = $http.get('locations/locations.json');
      return promise;
    }
  };
});

就将数据放入指令而言,重要的是要记住,指令是为抽象通用DOM操作而设计的;您不应该向它们注入特定于应用程序的服务。在这种情况下,很容易简单地将locations服务注入到指令中,但这会将指令耦合到该服务。

关于代码模块化的简要说明:指令的函数几乎不应该负责获取或格式化自己的数据。没有什么可以阻止您从指令中使用$http服务,但这几乎总是错误的做法。编写一个使用$http的控制器是正确的方法。指令已经触及了DOM元素,这是一个非常复杂的对象,很难将其存根出来进行测试。将网络I/O添加到混合中会使您的代码更难理解,也更难测试。此外,网络I/O锁定了您的指令获取数据的方式--在其他地方,您可能希望让此指令从套接字接收数据或接收预加载的数据。您的指令应该通过scope.$eval将数据作为属性接受,并且/或者使用一个控制器来处理获取和存储data.

在这种特定情况下,您应该将适当的数据放在控制器的作用域上,并通过属性与指令共享它。

代码语言:javascript
复制
app.controller('SomeController', function($scope, locations) {
  locations().success(function(data) {
    $scope.locations = data;
  });
});
代码语言:javascript
复制
<ul class="list">
   <li ng-repeat="location in locations">
      <a href="#">{{location.id}}. {{location.name}}</a>
   </li>
</ul>
<map locations='locations'></map>
代码语言:javascript
复制
app.directive('map', function() {
  return {
    restrict: 'E',
    replace: true,
    template: '<div></div>',
    scope: {
      // creates a scope variable in your directive
      // called `locations` bound to whatever was passed
      // in via the `locations` attribute in the DOM
      locations: '=locations'
    },
    link: function(scope, element, attrs) {
      scope.$watch('locations', function(locations) {
        angular.forEach(locations, function(location, key) {
          // do something
        });
      });
    }
  };
});

通过这种方式,map指令可以与任何一组位置数据一起使用--该指令并不是硬编码为使用一组特定的数据,只是通过在DOM中包含它来链接该指令并不会触发随机的HTTP请求。

票数 91
EN

Stack Overflow用户

发布于 2014-02-10 09:33:11

正如您所说,您不需要请求该文件两次。把它从你的控制器传递给你的指令。假设您在控制器的作用域内使用该指令:

代码语言:javascript
复制
.controller('MyController', ['$scope', '$http', function($scope, $http) {
  $http.get('locations/locations.json').success(function(data) {
      $scope.locations = data;
  });
}

然后在HTML中(在其中调用指令)。

注意:locations是对控制器$scope.locations的引用。

代码语言:javascript
复制
<div my-directive location-data="locations"></div>

最后在你的指令中

代码语言:javascript
复制
...
scope: {
  locationData: '=locationData'
},
controller: ['$scope', function($scope){
  // And here you can access your data
  $scope.locationData
}]
...

这只是一个指导您正确方向的大纲,因此它是不完整的,也没有经过测试。

票数 11
EN

Stack Overflow用户

发布于 2014-02-10 11:10:28

你需要的是一个合适的服务:

代码语言:javascript
复制
.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;
    }
]);

locations将被缓存在服务中,该服务作为单例模型工作。这是获取数据的正确方式。

在你的控制器中使用这个服务DataLayer,指令是可以的,如下所示:

代码语言:javascript
复制
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
                });
            });
        }
    };
});
票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/21667613

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档