【问题标题】:AngularJS: Delay disappear with $timeoutAngularJS:延迟随着 $timeout 消失
【发布时间】:2015-08-19 09:03:39
【问题描述】:

当鼠标在 .mousemove DIV 上移动时,会出现 .show DIV,如果鼠标在 3 秒内没有移动,则 .show DIV 会消失。

<div class="mousemove" ng-mousemove="myToggle()" ng-model="loading" ></div>
<div class="show" ng-show="loading"></div>

$scope.myToggle = function() {
    $scope.loading = true; 
    $timeout(
        function() {
            $scope.loading = false;
        }, 
    3000);
}

我已经做了一些事情,但是当我在 .mousemove DIV 上不断移动鼠标时,.show DIV 会闪烁。我该怎么办,而且我是 AngularJS 的新手。 这是我的演示:http://embed.plnkr.co/WbhqAQ4JJvOfuCN4tI3I/preview

【问题讨论】:

    标签: angularjs timeout


    【解决方案1】:

    如果 $timeout 已经在运行,您可以在重新启动它之前取消它。

    var myApp = angular.module('myApp',[]);
    
    myApp.controller('myController', function($scope, $timeout) {
    
        $scope.myToggle = function() {
          // Check to see if there already is a $scope.loading timer
          if($scope.loading){
            // if there is then use the $timeout.cancel() method
            $timeout.cancel($scope.loading);
          }
          // Initialize the $timeout into the $scope.loading propert
          $scope.loading = $timeout(
            function() {
              $scope.loading = false;
          }, 3000);
        }
    });
    

    演示:http://embed.plnkr.co/WbqGbFG9JTVNXJW970l8/preview

    【讨论】:

    • 很抱歉现在回复你,因为网络太糟糕了。现在它可以成功地与你的代码一起工作。但我不明白“$scope.loading”没有设置为“true”在您的代码中,如何显示 .show DIV?
    • @holton $timeout 返回一个承诺 docs.angularjs.org/api/ng/service/$timeout,因此它不是 false。虽然不是专门 true 它是 truthy 足以通过 if 子句 sitepoint.com/javascript-truthy-falsy
    【解决方案2】:

    您必须在重新启动之前清除超时,如下所示:

    var myApp = angular.module('myApp',[]);
    
    myApp.controller('myController', function($scope, $timeout) {
        $scope.timeout;
        $scope.myToggle = function() {
            $scope.loading = true;
    
            window.clearTimeout($scope.timeout);
            $scope.timeout = window.setTimeout(function() {
                $scope.$apply(function() {
                    $scope.loading = false;
                });
            }, 3000);
        }
    });
    

    working Plunker

    【讨论】:

    • 首先,很抱歉现在回复你,因为网络太糟糕了。你的代码运行良好,但我选择了其他人的答案。无论如何,谢谢。
    • 我尝试了,但我没有获得15的声望,不能投票(。_。)
    【解决方案3】:

    这个笨蛋有几个问题。

    首先,这里没有理由使用 ng-model。只需将其设置为范围变量即可,因为无论如何您都在从控制器中对其进行编辑。

    其次,mousemove 会连续执行。每次移动鼠标时,它都会创建一个新的超时,并且不会取消旧的超时。这就是它闪烁的原因。调用这个函数并不断调用$timeout.cancel()$timeout(function() { }, 3000)也是非常低效的。

    请考虑使用 mouseenter 和 mouseleave 并确保取消旧的超时。

    HTML

    <div ng-app="myApp" ng-controller="myController">
      <div class="mousemove" ng-mouseenter="enter()" ng-mouseleave="leave()"></div>
      <div class="show" ng-show="loading"></div>
    </div>
    

    Javascript

    var myApp = angular.module('myApp',[]);
    
    myApp.controller('myController', function($scope, $timeout) {
    
      var timeoutCanceller = null;
    
      $scope.loading = false;
    
      $scope.enter = function() {
        cancelTimeout();
        $scope.loading = true;
      };
    
      $scope.leave = function() {
        timeoutCanceller = $timeout(function() {
          $scope.loading = false;
        }, 3000);
      };
    
      function cancelTimeout() {
        if (timeoutCanceller) $timeout.cancel(timeoutCanceller);
      }
    });
    

    Here is a working demo.

    编辑:将这些事件绑定到父容器而不是直接绑定到元素上可能也是一个好主意。如果该加载程序是一个覆盖,则可能会意外调用 mouseleave 事件。还为您提供了更多样式选择。

    <div ng-app="myApp" ng-controller="myController">
      <div ng-mouseenter="enter()" ng-mouseleave="leave()">
        <div class="mousemove"></div>
        <div class="show" ng-show="loading"></div>
      </div>
    </div>
    

    【讨论】:

    • 很抱歉现在回复你,因为网络太差了。我从你的建议中学到了很多,但是,也许我没有清楚地描述我想要什么。当鼠标在第一个 DIV 中一动不动时,第二个 DIV 消失而不是离开 DIV。现在我已经解决了。无论如何谢谢.
    猜你喜欢
    • 2017-08-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-01-31
    • 2014-04-11
    • 2016-08-26
    • 2015-03-08
    • 1970-01-01
    相关资源
    最近更新 更多