在 Angular 中,如何将 JSON 对象/数组传递给指令? [英] In Angular, how to pass JSON object/array into directive?

查看:20
本文介绍了在 Angular 中,如何将 JSON 对象/数组传递给指令?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Currently, my app has a controller that takes in a JSON file then iterates through them using "ng-repeat". This is all working great, but I also have a directive that needs to iterate through the same JSON file. This is posing a problem as I cannot request the same JSON file twice on one page (nor would I want to because it would be inefficient). Both the directive and controller request and iterate through the JSON data just fine if I change the filename of one of the JSON files.

我想知道的是:将从控制器的 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?

控制器

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

推荐答案

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

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.

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

First, while it doesn't have too much of an affect on the specific question you asked, you did mention efficiency, and the best way to handle shared data in your application is to factor it out into a service.

我个人建议采用 AngularJS 的 promise 系统,这将使您的异步服务与原始回调相比更具组合性.幸运的是,Angular 的 $http 服务已经在幕后使用了它们.这是一个服务,它将返回一个解析为来自 JSON 文件的数据的承诺;多次调用该服务不会导致第二次 HTTP 请求.

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


As far as getting the data into your directive, it's important to remember that directives are designed to abstract generic DOM manipulation; you should not inject them with application-specific services. In this case, it would be tempting to simply inject the locations service into the directive, but this couples the directive to that service.

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

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.

- 80/20编写 AngularJS 指令的指南

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

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 指令可以与任何 组位置数据一起使用——该指令不是硬编码来使用特定的数据组,并且通过将指令包含在 DOM 中来简单地链接指令不会触发随机 HTTP 请求.

In this way, the map directive can be used with any set of location data--the directive is not hard-coded to use a specific set of data, and simply linking the directive by including it in the DOM will not fire off random HTTP requests.

这篇关于在 Angular 中,如何将 JSON 对象/数组传递给指令?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆