【问题标题】:Second Angular directive suffers from $timeout in first第二个 Angular 指令首先遭受 $timeout
【发布时间】:2015-04-01 19:25:06
【问题描述】:

在构建一个简单的 Angular 应用程序时,我使用了两个指令。 第一个指令创建幻灯片,第二个指令提供一些阅读链接。

app.directive('slider', function($timeout) {
    return {
        restrict: 'AE',
        replace: true,
        scope: {
            images: '='
        },
        link: function(scope, elem, attrs) {
            var timer;
            scope.currentIndex = 0; // Initially the index is at the first image

            scope.next = function() {
                scope.currentIndex < scope.images.length - 1 ? scope.currentIndex++ : scope.currentIndex = 0;
            };
            scope.prev = function() {
                scope.currentIndex > 0 ? scope.currentIndex-- : scope.currentIndex = scope.images.length - 1;
            };

            var sliderFunc = function() {
                timer = $timeout(function() {
                    scope.next();
                    timer = $timeout(sliderFunc, 5000);
                }, 10);
            };

            sliderFunc();

            scope.$watch('currentIndex', function() {
                scope.images.forEach(function(image) {
                    image.visible = false; // make every image invisible
                });

                if (scope.images.length > 0) {
                    scope.images[scope.currentIndex].visible = true; // make the current image visible
                }
            });

            scope.$on('$destroy', function() {
                $timeout.cancel(timer); // when the scope is getting destroyed, cancel the timer
            });
        },
        templateUrl: 'app/slider.tpl.html'
    };
})
.directive('readMore', function() {
    return {
        restrict: 'A',
        scope: true,
        link: function(scope, elem, attrs) {
            scope.more = false;

            elem.find('.readmore').bind('click', function() {
                scope.more = scope.more === false ? true : false;
            });
        }
    };
});

两个指令都按预期工作。

第一个指令使用 $timeout,因此幻灯片图像每 5 秒循环一次。

阅读更多链接中存在问题。 当我单击链接时,脚本(指令)等待(最多)5 秒。执行,同时幻灯片也执行。

我对 Angular 还很陌生,但我认为具有不同作用域的指令不会相互干扰。

我该怎么做才能让我的阅读链接立即触发?

【问题讨论】:

    标签: angularjs angularjs-directive timeout


    【解决方案1】:

    这是因为在第二个指令中,您在 jQuery click 事件中更新您的范围,这超出了 Angular 生命周期。

    视图将在下一个摘要周期刷新,例如由任何 $timeout 调用触发。

    一个快速而肮脏的解决方法是在第二个指令的点击侦听器中调用scope.$apply()(或scope.$digest())。

    更好的解决方法是使用 ng-click 指令而不是 jQuery 侦听器以角度方式捕获点击事件(然后将它们作为其生命周期的一部分 - 无需手动 $apply)

    更新:这里是如何使用ng-click

    <a class="readmore" ng-click="more = !more">Read more</a>
    


    作为旁注,您可能应该使用$interval 而不是$timeout,因为它是您实际模拟的。

    【讨论】:

    • 感谢$interval 的提示,这感觉好多了。
    • 我尝试使用 ng-click 代替 jQuery 侦听器,但我仍然缺乏使其工作的技能。 html 锚点与调用指令的元素不同。 ng-click 似乎在那里不起作用。 &lt;div class="text" read-more&gt; &lt;h3&gt;Title&lt;/h3&gt; &lt;p class="less" ng-hide="more"&gt;Lorum ipsum.&lt;/p&gt; &lt;p class="more" ng-show="more"&gt;Lorum ipsum long...&lt;/p&gt; &lt;a class="readmore" ng-click="readmore"&gt;Read more&lt;/a&gt; &lt;/div&gt;
    • 您需要将表达式传递给ng-click,例如ng-click="readmore()"(注意括号)。然后在$scope.readmore 中放置一个完成这项工作的函数。
    • 或者没有函数你可以直接把所有的逻辑:ng-click="more = !more"!会切换布尔值,真为假,假为真)。我已经用这个例子更新了我的答案。这样做会更干净,请继续尝试,直到成功为止,我们可以为您提供帮助。
    • 很高兴它有效。要记住的主要思想是,使用 jQuery 从来都不是一个好主意,这就是为什么它默认不包含在 Angular 中:总是尝试以 Angular 的方式做事,你会避免很多问题。
    【解决方案2】:

    您正在从角度上下文中修改 scope.more。请在此处调用 scope.$digest()

      elem.find('.readmore').bind('click', function() {
                scope.more = scope.more === false ? true : false;
                scope.$digest();
            });
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-12-01
      • 2014-06-07
      • 1970-01-01
      • 2018-09-04
      • 1970-01-01
      相关资源
      最近更新 更多