【问题标题】:Why is that the UI is not refreshed when data is updated in typescript and angularjs program为什么在typescript和angularjs程序中更新数据时UI没有刷新
【发布时间】:2014-09-18 16:51:07
【问题描述】:

学了几天typescript和angularjs,现在有个问题困扰了我好几天,想做一个gps追踪系统,所以尝试写一个这样的服务:

1.

  module Services {
        export class MyService {
            getGpsPeople(): Array<AppCommon.GPSPerson> {
                var gpsPeople = new Array<AppCommon.GPSPerson>()
                for (var i = 0; i < 10; i++) {
                    var tempPerson = new AppCommon.GPSPerson({ name: "username" + i.toString() });
                    gpsPeople.push(tempPerson);
                }
                return gpsPeople;
            }
        } // MyService class
    }
  1. 这样的控制器:

    模块 AppCommon { 出口类控制器{ 范围:ng.IScope;

         constructor($scope: ng.IScope) {
             this.scope = $scope;
    
         }
     }
    

    } 模块控制器 {

     export interface IMyScope extends ng.IScope {
    
         gpsPeople: Array<AppCommon.GPSPerson>;
     }
    
     export class MyController extends AppCommon.Controller {
         scope: IMyScope;
    
         static $inject = ['$scope','myService'];
         constructor($scope: IMyScope,service:Services.MyService) {
             super($scope);
    
             $scope.gpsPeople = service.getGpsPeople();
         }
     }
    

    }

3.GPSPerson 类如下:

 export class GPSPoint {
        latitude = 0;
        longtitude = 0;

        constructor(la: number, lg: number) {
            this.latitude = la;
            this.longtitude = lg;
        }
    }

    export interface IPerson {
        name: string;
    }

    export class GPSPerson  
    {
        name: string;
        lastLocation: GPSPoint;
        countFlag = 1;
        historyLocations: Array<GPSPoint>;
    
        timerToken: number;
        startTracking() {
            this.timerToken = setInterval(
                () => {
                    var newGpsPoint = null;
                    var offside = Math.random();

                    if (this.countFlag % 2 == 0) {
                        newGpsPoint = new GPSPoint(this.lastLocation.latitude - offside, this.lastLocation.longtitude - offside);
                    }
                    else {
                        newGpsPoint = new GPSPoint(this.lastLocation.latitude + offside, this.lastLocation.longtitude + offside);
                    }

                    this.lastLocation = newGpsPoint;
                    this.historyLocations.push(newGpsPoint);
                    console.log(this.countFlag.toString() + "+++++++++++++++++++" + this.lastLocation.latitude.toString() + "----" + this.lastLocation.longtitude.toString());
                    this.countFlag++;
                }
                , 10000);
        }

        stopTracking() {
            clearTimeout(this.timerToken);
        }

        constructor(data: IPerson) {
            this.name = data.name;
            this.lastLocation = new GPSPoint(123.2, 118.49);
            this.historyLocations = new Array<GPSPoint>();
        }
    }

问题是:

1.我应该让 GPSPerson 类成为控制器吗?

2.setinterval 有效,但 UI 没有改变(当我点击按钮时,它改变了,按钮什么也不做)?

我是ts和angular的初学者,对js没有经验,不知道有没有解释清楚,希望有人能帮帮我,谢谢!

【问题讨论】:

    标签: angularjs dependency-injection typescript


    【解决方案1】:

    我会分离跟踪逻辑并仅将数据保留在 GPSPerson 中。对于跟踪逻辑,我会创建一个工厂。 我的示例不在 Typescript 中,但我相信如果您愿意,转换代码不会有任何问题。

    这是Plunk的链接

    我做了一个简单得多的例子,但我想你会理解这个想法。 工厂将有两种方法用于开始和停止跟踪。他们会将人作为参数。

    app.factory('tracking',function($interval){
      var trackingInterval;
      var trackingFn = function(person){
        var currentPos = Math.floor(Math.random()*10);
        var newPosition = {id:person.positions.length, position:currentPos};
        person.positions.push(newPosition);
      };
      var startTracking = function(person){
        person.interval = $interval(function(){
          trackingFn(person);
        },2000);
    
      };
    
      var stopTracking = function(person){
        console.log('STOP');
        $interval.cancel(person.interval);
      };
      var getNewTrack = function(){
      };
      return {
        startTracking: startTracking,
        stopTracking: stopTracking,
      };
    });
    

    我还做了一个非常简单的指令来显示数据

    app.directive('position',function(){
      return {
        templateUrl: 'positionTemplate.html',
        link: function(scope, element,attrs){
        }
      }
    });
    

    模板看起来像这样

    <div>
      <button ng-click="startTracking(person)">Start tracking</button>
      <button ng-click="stopTracking(person)">Stop tracking</button>
      <p>{{person.name}}</p>
      <ul>
        <li ng-repeat="pos in person.positions">{{pos.position}}</li>
      </ul>
    </div>
    

    指令会这样调用

    <div ng-repeat="person in people">
      <div position></div>
    </div>
    

    我并不是说这是一个更好的解决方案,但我就是这样做的。请记住,这只是一个模型,需要大量改进。

    【讨论】:

      【解决方案2】:

      setInterval 有效,但用户界面没有改变

      这是因为角度 $digest 循环不会在 setInterval 完成时运行。你应该使用 $interval service https://docs.angularjs.org/api/ng/service/$interval 因为它告诉 Angular 再次进行脏检查。

      您只需要提供MyService$interval 的访问权限。使用$inject 注入它(参见https://www.youtube.com/watch?v=Yis8m3BdnEM&hd=1)。

      1.我应该让 GPSPerson 类成为控制器吗?

      没有。它是控制器内部的 JavaScript 对象数组,这很好。

      【讨论】:

      • 你的建议真的很有帮助,根据你的回答,我修改了myService,向其中注入了一个$interval,并将它和服务本身作为构造函数参数传递给GPSPerson,每1000ms刷新一次lastPostion属性(从服务中获取新位置),它可以工作,我只是想知道,我将相同的 $interval 对象传递给数组的每个项目,会不会有问题?如果服务任务耗时超过1000ms,是否会跳到下一个服务调用并忽略当前任务?
      猜你喜欢
      • 2019-06-24
      • 2012-02-05
      • 1970-01-01
      • 2023-03-29
      • 2020-05-17
      • 1970-01-01
      • 1970-01-01
      • 2018-03-13
      • 1970-01-01
      相关资源
      最近更新 更多