javascript - Angular Directive(指令) $http. http响应前后

标签 javascript angularjs

简单的事情..

<my-directive info-key="total_users"></my-directive>

结果:<div>You asked for {{ infoKey }}, you get {{ apiValue }}</div>

现在的问题是,在 API 响应之前,我想在那里添加一些 html。

例如<div You asked for {{ infoKey }}, you get <small>pending..</small></div> 然后为 API 结果删除它。

当然我尝试初始化结果 $scope.apiValue = 'pending...';但我只是想知道是否有更好的方法,因为我还不太熟悉“Angular 方式”。

尽管我的整个逻辑可能是错误的,但请检查下面的代码片段。

apiUrl = 'https://api.stackexchange.com/2.2/info?site=stackoverflow';

angular.module('app', []).directive('myDirective', [
  function() {
    return {
      restrict: 'E',
      replace: true,
      template: '<div>you asked for <strong>{{ infoKey }}</strong>, you get: <strong>{{ apiValue }}</strong></div>',
      controller: ['$scope', '$http',
        function($scope, $http) {
          $scope.askApi = function(key) {
            $http.get(apiUrl).success(function(data) {
              $scope.apiValue = data.items[0][key];
            });
          };
        }
      ],
      link: function(scope, element, attrs, ctrl) {
        scope.infoKey = attrs.infoKey;
        scope.askApi(scope.infoKey);
      }
    }
  }
]);
<html ng-app="app">

<head></head>

<body>
  <my-directive info-key="total_users"></my-directive>

  <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
</body>

</html>

最佳答案

您大体上是在正确的轨道上。但是,正如您所注意到的,您没有遵循最佳 Angular 实践。我要更改的一些内容(如下所示):

  1. 避免使用 $scope,而是使用 controllerAs 语法。避免 $scope 可以消除由于 $scope 具有的原型(prototype)继承和共享而可能发生的大量错误和混淆。

  2. 不要使用替换,而是使用该元素作为您的包含元素。它在功能上是等效的,并使您的标记更具语义。这里唯一要记住的是自定义元素将有一个 display: inline;默认样式而不是显示: block ;如果它是一个 div,它就会有。

  3. 使用 bindToController。公平地说,这是带有 Angular 1.3 的,而您的示例使用 Angular 1.2。可以说它删除了一些代码。

  4. 将您的 API 访问逻辑分离到一个服务中。

还有一些我要补充但没有显示的内容:

  1. 测试! Angular 旨在简化单元测试。通过编写测试,您对代码的理解将大大提高,更不用说您从编写测试中获得的其他好处了。

  2. 处理错误。在 Controller 中 promise 的 .success() 之后,您应该有一个 .catch() block 并处理错误。即使只是向用户显示错误也会有好处,甚至包括重试按钮。

angular.module('app', []).directive('myDirective', [
  function() {
    return {
      restrict: 'E',
      template: 'you asked for <strong>{{ vm.infoKey }}</strong>, you get: <strong>{{ vm.apiValue }}</strong>',
      controllerAs: 'vm',
      scope: {
        infoKey: '@'
      },
      bindToController: true,
      controller: ['stackoverflowInfo',
        function(stackoverflowInfo) {
          var vm = this;

          vm.apiValue = 'pending ...';

          stackoverflowInfo.get(vm.infoKey).then(function(value) {
            vm.apiValue = value;
          });
        }
      ]
    }
  }
]).service('stackoverflowInfo', ['$http', '$q', function ($http, $q) {
  var svc = this;
  var apiUrl = 'https://api.stackexchange.com/2.2/info?site=stackoverflow';

  svc.get = get;
  
  function get (key) {
    return getFromApi().then(function(data) {
      return data.items[0][key];
    });
  }

  function getFromApi () {
    var defer = $q.defer();
    $http.get(apiUrl).success(defer.resolve).error(defer.reject);
    return defer.promise;
  }
}]);
<html ng-app="app">

<head></head>

<body>
  <my-directive info-key="total_users"></my-directive>

  <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular.min.js"></script>
</body>

</html>

关于javascript - Angular Directive(指令) $http. http响应前后,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29843844/

相关文章:

javascript - 循环遍历动态添加的元素

angularjs - 这是指令的正确用法吗?

javascript - 分层数据模型的 Angular 嵌套过滤器

javascript - 使用 ng-class (AngularJS) 搜索 JSON 对象

javascript - 如何防止 Angular 拦截器在 jasmine 测试期间获取 $httpBackend 响应

javascript - AngularJS 循环遍历数组(一系列数字)

javascript - 使用片段生成渐变的奇怪的一对一问题

angularjs - 使用 Angularjs 加密客户端本地存储数据

javascript - gmaps.js 使用 native Google Maps API v3 函数

javascript - jQuery 在 optgroup 前面添加标签