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

What I'm wondering is: what's the best way to go about passing the array formed from my controller's JSON request into the directive? How can I pass the array into my directive and iterate through when I've already accessed it via my controller?

Controller

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

Directive (Works when I use a file name besides locations.json, since I've already requested it once

.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
   });
});

推荐答案

If you want to follow all the "best practices," there's a few things I'd recommend, some of which are touched on in other answers and comments to this question.


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

I would personally recommend embracing AngularJS's promise system, which will make your asynchronous services more composable compared to raw callbacks. Luckily, Angular's $http service already uses them under the hood. Here's a service that will return a promise that resolves to the data from the JSON file; calling the service more than once will not cause a second HTTP request.

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操作而设计的;您应该用特定于应用程序的服务将它们注入not.在本例中,简单地将locations服务注入到指令中是很有诱惑力的,但是这会将指令耦合到该服务.

A brief aside on code modularity: a directive’s functions should almost never be responsible for getting or formatting their own data. There’s nothing to stop you from using the $http service from within a directive, but this is almost always the wrong thing to do. Writing a controller to use $http is the right way to do it. A directive already touches a DOM element, which is a very complex object and is difficult to stub out for testing. Adding network I/O to the mix makes your code that much more difficult to understand and that much more difficult to test. In addition, network I/O locks in the way that your directive will get its data – maybe in some other place you’ll want to have this directive receive data from a socket or take in preloaded data. Your directive should either take data in as an attribute through scope.$eval and/or have a controller to handle acquiring and storing the data.

- The 80/20 Guide to Writing AngularJS Directives

In this specific case, you should place the appropriate data on your controller's scope and share it with the directive via an attribute.

app.controller('SomeController', function($scope, locations) {
  locations().success(function(data) {
    $scope.locations = data;
  });
});
<ul class="list">
   <li ng-repeat="location in locations">
      <a href="#">{{location.id}}. {{location.name}}</a>
   </li>
</ul>
<map locations='locations'></map>
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指令可以与any组位置数据一起使用——该指令没有硬编码以使用特定的数据集,并且简单地通过将其包含在DOM中来链接该指令不会触发随机HTTP请求.

Json相关问答推荐

2020-12年草案中的Json列举模式

您可以使用Jolt对JSON执行OR条件吗

如何在使用GO时检测JSON中不需要的字段?

对面的行/列进行排序时可能出现错误

在Jenkins中使用ReadJSON读取json子元素

解析JSON说函数parse_json不存在?

褐煤面积图中的分选问题

如何将文件夹组织的.json文件合并为一个JSON文件,文件夹/文件名作为键

在 json 对象中存储多个键:值对

Python 将 struct 化文本转换和筛选为对象

无法使用 vue.js 访问 JSON 数组的项目

如何加入或合并列表元素列表(未知长度)

从 JSON 响应中获取最新版本发布字段

将哈希表转换为 json 后,Powershell 缺少数组

关于使用 $ref 的 JSON 模式

在 Webpack 中加载静态 JSON 文件

带有方法参数的 WCF webHttpBinding 错误. 最多可以在没有包装元素的情况下序列化一个主体参数

有 Json 标签但未导出

PHP json_encode json_decode UTF-8

jq:按属性分组和键