0

我正在使用 Firebase / AngularFire 构建一个 Ionic 应用程序。而且我面临一个棘手的情况:我希望我的 ng-repeat 得到更多的性能优化。我听说最好的方法是无限滚动。我使用 AngularFire 在服务/工厂中获取我的所有数据——更具体地说,是 $firebaseArray。

我在谷歌上发现了这个: http: //firebase.github.io/firebase-util/#/toolbox/Paginate/example/ionic

问题 1:使用 Firebase util 库的 Ionic 示例的无限滚动是服务器端无限滚动还是客户端?这个库是否解决了这里提到的 ng-repeat 的性能问题:(http://www.alexkras.com/11-tips-to-improve-angularjs-performance/

问题2:我的firebaseArray其实需要orderBy一个动态计算的变量叫distance。我仍然可以在我的安全规则中使用 .indexOn 规则来提高查询性能吗?(对我来说听起来不可能,因为距离一开始没有存储在火力基地中)

这是我的代码:我的工厂:taskService.js

    var ref = new Firebase(FirebaseUrl);
    var tasks = $firebaseArray(ref.child('tasks'));
    var Task = {
        all: tasks,
        getAllTasks: function() {
            if (tasks.length == 0) {
                tasks = $firebaseArray(ref.child('tasks'));
            } else {   
                tasks = tasks;
            }
            return tasks;
        },
     }

我的 ng-repeat 视图控制器:

    $scope.tasks = taskService.getAllTasks();
    $scope.tasks.$loaded().then(function(data){
            calculateDistance($scope.tasks, $scope.userCurrentLocation);  
    });
    var unwatch = $scope.tasks.$watch(function(event) {
          calculateDistance($scope.tasks, $scope.userCurrentLocation);
        });
    $scope.$on('$ionicView.leave', function(){
          // Anything you can think of
          unwatch();
        });
    }
    //--------------GeoLocation Calculation
    var calculateDistance = function (tasks, userCurrentLocationData) {
        for (var id in tasks) {
            var task = tasks[id];
            if (task.addressLat) {
                var taskLocation = new google.maps.LatLng(task.addressLat, task.addressLng);
                var userCurrentLocation = new google.maps.LatLng(userCurrentLocationData.lat, userCurrentLocationData.lng);
                var distance = google.maps.geometry.spherical.computeDistanceBetween(userCurrentLocation, taskLocation);
                $scope.tasks[id].distance = parseInt(distance*0.000621371192);
            }
        }
    }

而我的观点:

<a class="item item-avatar" ng-repeat="task in tasks | filter: searchTask | orderBy: ['-status', 'distance', '-datetime'] track by task.$id" ng-href="#/app/task/{{task.$id}}">
....
</a>

正如您在此处看到的,我在获得 firebaseArray 对象后添加了距离属性。并且这个距离是根据用户当前的设备位置动态计算的。因此 ng-repeat 将显示最接近用户当前位置的项目。由于距离是动态的,我无法将它事先保存在我的 Firebase 中,因此 firebase 规则将不起作用。

问题 3:如何在动态值上使用 Firebase.util 无限滚动 - 如此处的“距离”属性?

当我看到 firebase util 的文档时,我需要这样做:

   // create a scrollable reference
  var scrollRef = new Firebase.util.Scroll(baseRef, 'distance');

但是baseRef中没有距离。它是在加载 firebaseArray 后生成的。那么我应该如何处理呢?

另外,从结构的角度来看,我会将 scrollRef 和 firebaseArray 都放在我的工厂中 - taskService.js

// 创建一个可滚动引用 var scrollRef = new Firebase.util.Scroll(baseRef, 'distance');

// 在作用域上创建一个同步数组 return $firebaseArray(scrollRef);

然后,由于工厂只返回 $firebaseArray(scrollRef),我如何访问文档中所述的 scroll.next 函数,如 scrollRef.scroll.next(3); 在我的控制器中?由于我没有 scrollRef 对象,只有 FirebaseArray ...

4

1 回答 1

5

关于 Q1:firebase-util 的 Scroll 通过更新查询参数并在滚动时同步来自服务器的更改来实现滚动。服务器通过缓存和预取来参与,以使滚动更新更快。

ng-repeat 性能问题似乎是 ng-repeat 不能处理大量元素。使用 Scroll 通过限制重复元素的数量来帮助解决这个问题。

Re Q2:索引用户与您要显示的元素之间的大圆距离是不可能的。更好的方法可能是使用地理哈希。geofire库直接为firebase实现了这一点,可以很容易地找到用户附近的东西。

关于 Q3:GeoFire 本身提供了一种限制结果的方法(通过限制半径),因此您甚至可能不必解决这个问题。如果您想限制固定数量的元素,您需要自己对 geofire 查询的结果进行后处理。

于 2015-09-16T16:51:59.780 回答