角度计时器指令不适用于离子框架

Posted

技术标签:

【中文标题】角度计时器指令不适用于离子框架【英文标题】:angular timer directive not working with ionic framework 【发布时间】:2015-01-02 17:50:29 【问题描述】:

我在使用 ionic 框架实现角度计时器指令时遇到问题。 http://siddii.github.io/angular-timer/

当我使用 bower 或 google cdn 实现代码时,我没有任何问题。

    <!DOCTYPE html>
    <html>
    <head>
    <title>Plain javascript Timer Example</title>
    <script src="../bower_components/angular/angular.min.js"></script>
    <script src="../app/js/timer.js"></script>
    <script>
    function startTimer() 
    document.getElementsByTagName('timer')[0].start();
    
    function stopTimer() 
    document.getElementsByTagName('timer')[0].stop();
    
    </script>
    </head>
    <body>
    <div>
    <h2>Plain JavaScript - Timer Example</h2>
    <h3><timer ng-app="timer"/></h3>
    <button onclick="startTimer()">Start Timer</button>
    <button onclick="stopTimer()">Stop Timer</button>
    </div>
    <br/>
    </body>
    </html>

但是当我使用离子束时 http://code.ionicframework.com/1.0.0-beta.13/js/ionic.bundle.js 我无法让计时器工作。 并且似乎在控制台中没有任何错误。

这是一个已知问题吗?

什么会阻止它工作?

是否有可供人们推荐的备用计时器?这个对我来说是最好的?

【问题讨论】:

这个例子似乎不可靠,因为你正在对一个本身就是整个应用程序的角度指令执行非角度逻辑。你可以创建一个 plunker 并可能在 Angular 本身中对按钮进行编码以排除潜在的错误吗? 看了一下angular-timer的代码,虽然它的名字是angular-timer,但是它的工作方式$on、$broadcast和使用id的开始停止等,我个人不会选择它在我的生产代码中,可悲的是它没有以角度方式实现.... @harish 感谢您提供的小费,如果您愿意的话会很棒吗?正如你所说,听起来这个指令可能有一些限制 【参考方案1】:

尝试在此处查看此代码示例: http://siddii.github.io/angular-timer/examples.html#/angularjs-single-timer

以角度启动计时器是通过

完成的
$scope.$broadcast('timer-stop');

不是

element.start();

顺便说一句,您的 ng-app 应该在 html/body 标记中,而不是在计时器标记中。

【讨论】:

感谢您的信息!我在这里得到了一个工作,例如codepen.io/anon/pen/emYOeX,但我无法解决的一件事是如何保持计时器,以便即使我在选项卡之间单击它也能继续计数。例如,在我的 codepen 中,每次单击联系人时它都会重置。你能在这里指出我正确的方向吗?或者这个指令不可能做到这一点? 据此 - siddii.github.io/angular-timer/index.html#/markup 你应该添加 autostart="false" 并且可以使用 start-time 属性,将之前的停止时间设置为新的开始时间。您可能可以使用 timer-stopped 事件保存上一次停止的时间【参考方案2】:

这是角度方式: http://plnkr.co/edit/ug4VqTkkFWlsYLy7uq4O

也使用 $broadcast 事件来控制这个指令

$scope.start = function () 
  $scope.$broadcast('timer-start');
;

【讨论】:

【参考方案3】:

根据 cmets 中的讨论,我正在分享我正在使用的基本指令的实现。这不像 angular-timer 那样通用,因此您可能需要稍微调整一下以满足您的需要。

第一部分:工厂保持定时器,启动/停止等

csapp.factory("timerfactory", function () 
    var refresh = 
        suspend: false,
        pause: function ()  refresh.suspend = true; ,
        cont: function ()  refresh.suspend = false; ,
        toggle: function ()  refresh.suspend = !refresh.suspend; ,
        refreshText: function ()  return refresh.suspend ? "Resume Refresh" : "Pause Refresh"; 
    ;

    var timer = 
        timePending: 0,
        refreshInterval: 60,
        reset: function ()  timer.timePending = timer.refreshInterval; ,
        update: function () 
            if (timer.timePending < 0) timer.reset();
            timer.timePending--;
        ,
        done: function ()  return timer.timePending <= 0; ,
        force: function ()  timer.timePending = 0; 
    ;

    return 
        refresh: refresh,
        timer: timer
    ;
);

第二部分:指令,支持2个操作

    2 路绑定的布尔暂停变量

    on-timeout 函数:将在超时时调用

    interval : 以秒为单位,之后将调用 on-timeout 函数

    csapp.directive("csAutoRefresh", ["timerfactory", "Logger", "$interval", function (factory, logManager, $interval)

    var $log = logManager.getInstance('csAutoRefresh');
    
    var templateFn = function () 
        var template = '<div class="text-left alert alert-success nopadding"';
        template += 'style="margin-bottom: 0; margin-right: 0"> ';
        template += ' <button class="btn btn-link" data-ng-click="factory.refresh.toggle()">';
        template += 'factory.refresh.refreshText()</button>';
        template += '<span>...Refreshing upload status in ';
        template += ' factory.timer.timePending seconds</span>';
        template += ' </div>';
        return template;
    ;
    
    var linkFn = function (scope) 
        scope.pauseOn = false;
        scope.isprocessing = false;
        scope.factory = factory;
        if (angular.isDefined(scope.interval) && collosys.isNumber(parseInt(scope.interval)) && parseInt(scope.interval) > 0) 
            scope.factory.timer.refreshInterval = scope.interval;
        
        factory.timer.reset();
    
        scope.$watch(function () 
            return factory.timer.timePending;
        , function () 
            if (!factory.timer.done()) return;
            var result = scope.$eval(scope.onTimeout);
            if (angular.isObject(result) && angular.isFunction(result.then)) 
                scope.isprocessing = false;
                factory.timer.reset();
                result.finally(function () 
                    factory.timer.reset();
                );
            ;
        );
    
        scope.$watch('pauseOn', function () 
            if (scope.pauseOn) 
                factory.refresh.pause();
             else 
                factory.timer.reset();
                factory.refresh.cont();
            
        );
    
        var updateTimer = function () 
            if (scope.isprocessing) return;
            if (factory.refresh.suspend) return;
            factory.timer.update();
        ;
    
        var interval = $interval(updateTimer, 1000);
        scope.$on('$destroy', function () 
            $interval.cancel(interval);
        );
    ;
    
    return 
        restrict: 'E',
        scope:  onTimeout: '&', pauseOn: '=', interval: '@' ,
        template: templateFn,
        link: linkFn,
     ;
    ]);
    

【讨论】:

@ak85 我还没有为此编写测试,但它可以工作。 我看了一下,它看起来很有用,它看起来虽然主要专注于倒计时?因此,我提供了一个答案,您可以在列表中看到我决定使用的答案。感谢您对角度计时器的建议,我认为我有一个更好的结果,我可以根据自己的需要轻松定制。【参考方案4】:

我决定不使用 angular-timer 指令,因为我在重置选项卡时遇到了问题,正如您在 example here 中看到的那样。

相反,我将我的计时器设为this fiddle。

您可以在this pen 中查看我的最终结果。它在 ionic 中加载了一个计时器,即使在更改选项卡时也能保持计数。展望未来,可能需要对其添加更多更改,例如只能在计时器启动时单击停止等。

        <script id="home.html" type="text/ng-template">
          <ion-view title="Home">
            <ion-content class="padding">
              <p>Home page</p>
                <h1>myStopwatch.data.hours | numberFixedLen:2:myStopwatch.data.minutes | numberFixedLen:2:myStopwatch.data.seconds | numberFixedLen:2</h1>
                <button ng-click='myStopwatch.start()'>Start</button>
                <button ng-click='myStopwatch.stop()'>Stop</button>
                <button ng-click='myStopwatch.reset()'>Reset</button>          
            </ion-content>
          </ion-view> 
        </script>

    <script>
    .filter('numberFixedLen', function () 
        return function (n, len) 
            var num = parseInt(n, 10);
            len = parseInt(len, 10);
            if (isNaN(num) || isNaN(len)) 
                return n;
            
            num = ''+num;
            while (num.length < len) 
                num = '0'+num;
            
            return num;
        ;
    )
    .constant('SW_DELAY', 1000)
    .factory('stepwatch', function (SW_DELAY, $timeout) 
        var data = 
            seconds: 0,
            minutes: 0,
            hours: 0
        ,
        stopwatch = null;

        var start = function () 
            stopwatch = $timeout(function () 
                data.seconds++;
                if (data.seconds >= 60) 
                    data.seconds = 00;
                    data.minutes++;
                    if (data.minutes >= 60) 
                        data.minutes = 0;
                        data.hours++;
                    
                
                start();
            , SW_DELAY);
        ;

        var stop = function () 
            $timeout.cancel(stopwatch);
            stopwatch = null;
        ;

        var reset = function () 
            stop()
            data.seconds = 0;
        ;
        return 
            data: data,
            start: start,
            stop: stop,
            reset: reset
        ;
    )
    .controller('HomeTabCtrl', function($scope, $state, stepwatch) 
      $scope.myStopwatch = stepwatch;
    );
    </script>

【讨论】:

在考试示例中查看我在秒表上的另一个答案【参考方案5】:

根据您的 cmets,我提供了另一个答案...秒表工厂,我在我的项目中使用。根据您的要求,您可以使用如下服务:

查看PLUNKER 以获取实际示例。

    最初您会看到说明页面,其中计时器被初始化为 2 小时。

    然后转到问题 1,计时器开始的地方

    您可以从问题 1 转到帮助页面,此处计时器暂停

    然后您回到问题 2,计时器恢复...

关于如何使用:

    在第一页开始初始化

    app.controller('view1Ctrl', function($scope, $csCountdown)
      $csCountdown.init(2 * 3600); // 2 hours
      $scope.countdown = $csCountdown.data;
    )
    

    在第二页启动计数器

    app.controller('view2Ctrl', function($scope, $csCountdown)
      $csCountdown.start();
      $scope.countdown = $csCountdown.data;
    )
    

您可以使用countdown.stringValue在任何页面上显示该值

<h1>Time : countdown.stringValue</h1>

【讨论】:

感谢 plunker 实际示例。很有帮助。

以上是关于角度计时器指令不适用于离子框架的主要内容,如果未能解决你的问题,请参考以下文章

定时器(NSTimer scheduledTimerWithTimeInternval)和蓝牙委托:CBPeripheralDelegate 不适用于 NSTimer

NSTimer 不适用于 AsyncSocket 库

timeBeginPeriod 不适用于 Intel Comet Lake CPU (i5 10400H)

为啥切换效果不适用于使用角度指令的嵌套 div

IE输入元素焦点不适用于角度指令

Ionic Framework 应用程序适用于“离子服务”,但不适用于 Ionic View 应用程序