我怎样才能得到指令视图加载之后触发?(How can I get directive to fire

2019-09-02 23:45发布

我知道这已经被问了一千时间,但我想我已经想尽解决方案,我读过,我似乎无法得到它的工作。

我从我得到我的图像时,图像揪成我希望他们使用photoswipe显示在移动设备上查看后的API。

我有一个指令:

'use strict';

App.directive('photoswipe', function () {
return {
    replace: false,
    restrict: 'A',
    link: function photoSwipeLink(scope, element, attr) {
      scope.$watch(attr.photoswipe, function(value){
        angular.element('#gallery a').photoSwipe({
          enableMouseWheel: false,
          enableKeyboard: false
        });
      });
    }
  };
});

我在控制台中此错误:

Code.PhotoSwipe.createInstance: No images to passed.

我想这是因为视图已使之前的指令运行。

如果我添加$超时而不是手表,然后代码没有工作。 不幸的是这个解决方案是不行的,因为有可能是从API获取数据的延迟。 此外,代码不超时内工作。

我都试过了,上面的代码中,我使用$ viewcontentloaded尝试,试图在NG-重复最后一个元素后发射功能,但既不工作。

任何帮助将非常感激。

编辑:

这里的HTML。

<h1>{{ gallery.headline }}</h1>
<ul id="gallery" photoswipe>
  <li class="gallery" ng-repeat="image in gallery.images">
    <a href="{{ image.url }}" alt="image.caption">
      <img ng-src="{{ image.thumb_url }}" class="thumb" alt="{{ image.caption }}" style="display: block;">
      <h3 class="headline">{{ image.caption }}</h3>
    </a>
  </li>
</ul>

Answer 1:

我认为这是发生,因为角正在处理您的指令,结果被绑定到列表中。 这可能是一个竞争条件。 解决方法之一是做

$scope.$broadcast("picsDownloaded" ... 

事件在您的控制器后,你得到的结果。 在指令代替,

scope.$watch(attr.photoswipe ....

做这个

scope.$on("picsDownloaded" ....

并在处理程序中应用的jQuery插件。



Answer 2:

是的,你可以使用事件数据时存在信号。 虽然你也许不得不使用$ rootScope,取决于使用情况。

但我认为,最可能的原因是你的错误是,所有的$观察家被AngularJS有一个未定义的值初始化时,他们被称为第一次。

你应该检查你的$的手表功能,可以立即解决您的问题。



Answer 3:

正如有人指出,你需要等到所有的东西呈现只用结果您的API调用返回后发生的。 您的指令信号将是改变gallery.images阵列。 所以,让你的指令,看它像下面这样。

请注意新引进的隔离范围 - 对我来说,它听起来就像它应该被隔离,但我真的不能说,这是肯定的,因为我不知道你的应用程序代码的其余部分。

不管怎么说,它告诉角度,无论值是使用photoswipe模板属性(见下文)应绑定到images的指令的作用域属性。 使用这样的结构保证了这的每一个变化发生gallery.images无论何时以及如何发生的。 所有你需要做外就是改变集时,API调用完成,剩下的将只是工作。 没有事件(对我来说,他们是在角1.x中相当繁琐),不同组件之间没有联系,没有关注混合。 漂亮干净的解决方案。 但是,你需要了解如何$ watchCollection()的作品,它是从常规有点不同$watch ,它执行浅集扫描,并没有比较集合自己的对象,但只有它们的引用。

另一个重要的时刻是一个清理。 你必须确保当东西正从集合中删除,然后相应的事件和其他任何该插件结合的元素被正确销毁,否则你会最终有内存泄漏,突发性事件和性能低下。

App.directive('photoswipe', function ($timeout) {
return {
    replace: false,
    restrict: 'A',
    scope: {
        "images": "=photoswipe"
    },
    link: function photoSwipeLink(scope, element, attr) {
        scope.$watchCollection('images', function(value){
            // here $timeout() is necessary because this event will be fired
            // immediately after collection change
            // thus not giving angular time to render it
            // so, jquery plugin will be fired on the next angular digest
            // and everything will be rendered by then.
            $timeout(function () {
                angular.element('#gallery a').photoSwipe({
                    enableMouseWheel: false,
                    enableKeyboard: false
                });
                // and now figure out how to clean it up!
            });
        });
    }
  };
});

我们的模板。 请注意,我第一次使用photoswipe="gallery.images"属性。 这就是告诉角度绑定gallery.images到的范围photoswipe指令images性能。

由于指令现在推出了自己独立的范围里面的东西就应该考虑到这个事实。 这就是为什么ng-repeat="image in images"

<h1>{{ gallery.headline }}</h1>
<ul id="gallery" photoswipe="gallery.images">
  <li class="gallery" ng-repeat="image in images">
    <a href="{{ image.url }}" alt="image.caption">
      <img ng-src="{{ image.thumb_url }}" class="thumb" alt="{{ image.caption }}" style="display: block;">
      <h3 class="headline">{{ image.caption }}</h3>
    </a>
  </li>
</ul>

老实说,我没有测试此代码,但是除了可能的语法错误,它应该工作。 另外,我想强调一个更多的时间,我不知道你的应用程序的其它部分的结构,所以引入隔离范围可以打破它,如果你的指令里面的东西必然要高一些范围 - 但对我来说是坏主意本身因为它引入了组件之间隐藏的互连。



文章来源: How can I get directive to fire after view loaded?