【问题标题】:AngularJS - Directive + ng-repeat, 5 elements, loops 15 timesAngularJS - 指令 + ng-repeat,5 个元素,循环 15 次
【发布时间】:2016-04-28 00:13:19
【问题描述】:

我尝试将动态图片添加到我的 div 中,我通过 url2img 插件解决了这个问题。效果很好。但是当我通过 ng-repeat 循环时,它会为循环中的每个 div 加载最后一张图片。所以它循环了15次。我有 2 种方法现在不起作用。

1.) HTML + load-img-from-ext

<div ng-repeat="link in links">
    <div class="jumbotron">
      <div>
        {{link.title}}
      </div>
      <div>
        <img class="img-thumbnail img-thumb-ext" id="thumb-{{$index}}" src="data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs%3D" load-img-from-ext="{{link.url}}"/>
      </div>
    </div>
  </div>

1.) 指令

.directive("loadImgFromExt", ['$timeout', function (timer) {
    return {
      link: timer(function (scope, elem, attr) {

          $(".img-thumb-ext").each(function () {
             console.log(attr[loadImgFromExt]);
            $.ajax({
              url: 'https://www.googleapis.com/pagespeedonline/v1/runPagespeed?url=' + attr["loadImgFromExt"] + '&screenshot=true',
              context: this,
              type: 'GET',
              dataType: 'json',
              success: function (data) {
                data = data.screenshot.data.replace(/_/g, '/').replace(/-/g, '+');
                $(this).attr('src', 'data:image/jpeg;base64,' + data);
              }
            });
          })
        }
      }
    }
 }])

对于在屏幕上呈现的 5 个元素循环 15 次。 所以控制台日志的输出是

0

0 1

0 1 2

0 1 2 3

0 1 2 3 4

而我的图片源代码被最后一张图片覆盖了。

2.) 第二种方法 HTML + 发射最后一个重复元素

<div ng-repeat="link in links" emit-last-repeater-element>
    <div class="jumbotron">
      <div>
        {{link.title}}
      </div>
      <div>
        <img class="img-thumbnail img-thumb-ext" id="thumb-{{$index}}" src="data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs%3D" alt="{{link.url}}" data-url="{{link.url}}"/>
      </div>
    </div>
  </div>
  </div>

2.) 指令

.directive('emitLastRepeaterElement', function() {
    return function(scope) {
      if (scope.$last){
        scope.$emit('LastRepeaterElement');
      }
    };
  });

2.) 调用的控制器

$scope.$on('LastRepeaterElement', function(){
      console.log('good to go');
      $('img[data-url]').each(function() {
        console.log($(this)[0].attributes[3])
        console.log($(this)[0].attributes[3].nodeValue);
        //var myUrl = $(this)[0].attributes[3];
        console.log($(this).data('url'));
        $.ajax({
          url: 'https://www.googleapis.com/pagespeedonline/v1/runPagespeed?url=' + $(this).data('url') + '&screenshot=true',
          context: this,
          type: 'GET',
          dataType: 'json',
          success: function(data) {
            data = data.screenshot.data.replace(/_/g, '/').replace(/-/g, '+');
            $(this).attr('src', 'data:image/jpeg;base64,' + data);
          }
        });
      });
    });

这行得通,因此它只循环 5 次。但是$(this).data('url'); 输出{{link.url}},而不是像http://www.google.com 这样的url。

$(this)[0].attributes[3] 输出data-url="http://www.google.com" 并且是object 的一种类型

$(this)[0].attributes[3].nodeValue ouputs {{link.url}}string 的一种

谁能告诉我如何只循环 5 次并获得正确格式的网址?

所以{{link.url}} 应该是例如http://www.google.comhttp://www.yahoo.com 以便我可以在我的 ajax 请求中的 url 属性中使用它。

【问题讨论】:

  • 每次你的链接函数运行时,你都在使用 jQuery 来迭代每一个具有匹配类的现有 DOM 节点;这意味着每次迭代都作用于所有先前的迭代。停止在 Angular 中使用 jQuery 方法。让每个指令只对自己的内容起作用。 Angular 和 jQuery:两种很棒的口味,一起尝起来可怕

标签: jquery angularjs angularjs-directive ng-repeat


【解决方案1】:

我开始相信 jQuery 专业知识是学习 Angular 的一个积极障碍:你习惯使用的许多技术与你在 Angular 中应该做的完全相反。您显然习惯于使用 DOM 作为数据存储——在 Angular 中,您需要更多地将其视为数据模型的副作用表示。

每个指令在作用域上已经有自己的link.url,因此不需要在jQuery 中爬取DOM,从其他指令中收集每个link.url。同样,没有理由继续读取和设置 DOM 属性上的数据——使用指令范围;您需要的所有数据都已经存在。

<div ng-repeat="link in links">
    <div class="jumbotron">
      <div>{{link.title}}</div>
      <div>
        <img ng-src="{{link.parsedUrl}}">
      </div>
    </div>
</div>

...并在指令链接函数中,直接从link.url构造link.parsedUrl

$.ajax({ // or, better, use $http
    url: 'https://www.googleapis.com/pagespeedonline/v1/runPagespeed?url=' + scope.link.url + '&screenshot=true',
    context: this,
    type: 'GET',
    dataType: 'json',
    success: function(data) {
        data = data.screenshot.data.replace(/_/g, '/').replace(/-/g, '+');
        scope.link.parsedUrl = 'data:image/jpeg;base64,' + data;
    }
});

【讨论】:

  • 好的,我对 Angular 还是很陌生...我尝试过这种方式,并且效果很好。但我对它做了些许改动。它不适用于scope.link.parsedUrl = 'data:image/jpeg;base64,' + data;,而是我写了elem.attr('src', 'data:image/jpeg;base64,' + data);,这有效,你能解释一下为什么吗?
  • 不确定您那里出了什么问题。这是它工作的一个玩具示例:jsfiddle.net/on8kcL1m/2(这将是少数几个像您一样直接设置属性会安全的情况之一——在指令中,只修改它自己的内部 DOM——但它仍然是一个 jQuery值得改掉的习惯。Angular 不知道你直接对 DOM 所做的任何更改,并且倾向于用它认为的当前状态覆盖它们。)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-07-05
  • 1970-01-01
  • 1970-01-01
  • 2015-05-04
  • 1970-01-01
  • 2013-07-12
  • 2012-07-12
相关资源
最近更新 更多