javascript - 在 Angular 中,如何将 JSON 对象/数组传递给指令?

标签 javascript json angularjs angularjs-directive angularjs-ng-repeat

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

我想知道的是:将 Controller 的 JSON 请求形成的数组传递到指令中的最佳方法是什么?当我已经通过 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

指令(当我使用除 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
   });
});

最佳答案

如果您想遵循所有“最佳实践”,我建议您做一些事情,其中​​一些在此问题的其他答案和评论中有所提及。


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

我个人建议采用 AngularJS 的 promise system ,与原始回调相比,这将使您的异步服务更具可组合性。幸运的是,Angular 的 $http 服务已经在后台使用了它们。这是一个服务,它将返回一个解析为 JSON 文件中的数据的 promise ;多次调用该服务不会引起第二个 HTTP 请求。

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 操作;您应该为它们注入(inject)特定于应用程序的服务。在这种情况下,很容易将 locations 服务简单地注入(inject)指令中,但这会将指令与该服务耦合。

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

在这种特定情况下,您应该将适当的数据放在 Controller 的范围内,并通过属性与指令共享。

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 请求。

关于javascript - 在 Angular 中,如何将 JSON 对象/数组传递给指令?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21667613/

相关文章:

javascript - 从 JSF 访问 Javascript 变量

javascript - angular-ui/bootstrap typeahead 支持 ng-model-options 吗?

javascript - 如何将 angularjs 值分配给 jquery

javascript - 如何获得 $http API 调用的 promise

javascript - 向下滚动时如何创建一个小窗口?

javascript - Highchart - 将更多系列添加到多个同步的 Highstock 图表之一

javascript - Node.js 中的生产质量错误处理

java - 改造预计为 BEGIN_OBJECT,但实际为 BEGIN_ARRAY android

javascript - 我是如何丢失 JavaScript 内置对象和所有全局变量的?

javascript - 在 Rails 中使用 <%= image_tag> Bootstrap 模态