angularFire 3 方式数据绑定不会更新功能
angularFire 3 way data binding won't update an function
我有一个 firebaseObject (MyFirebaseService.getCurrentUser()) 绑定到 $scope.user。
绑定成功后,我循环对象以查看对象是否包含 "associatedCourseId" 等于某个值 ($stateParams.id)。如果是,则 $scope.finishLessonCount 计数。问题是,当我通过其他页面或在 firebase 内部在 firebaseObject(绑定到用户)中添加新对象时,finishLessonCount 值不会像我对 3 种方式绑定所期望的那样改变。我需要刷新页面以查看 finishLessonCount 反映的真实值。怎么了?我希望在将更多 finishedLessons 添加到 firebaseObject 中时使用比较函数更改 finishLessonCount。请看下面的代码:
MyFirebaseService.getCurrentUser().$bindTo($scope, "user").then(function(){
for (var key in $scope.user.finishedLessons) {
if ($scope.user.finishedLessons.hasOwnProperty(key)) {
if ($scope.user.finishedLessons[key].associatedCourseId == $stateParams.id) {
$scope.finishLessonCount++;
}
}
};
console.log ($scope.finishLessonCount);
});
UPDATE 1 根据@Kato 解决方案:
我决定使用 Extending firebaseOject 的方式来解决这个问题。但是,它仍然没有。我没有在这里使用工厂来简化事情,因为我需要传入 courseId 来进行操作。这是我的代码:
function countLessons(lessons, courseId) {
var count = 0;
for(var key in lessons) {
if( lessons[key].associatedCourseId == courseId) {
count++;
}
}
return count;
}
var UserWithLessonsCounter = $firebaseObject.$extend({
$$updated: function(snap) {
var changed = $firebaseObject.prototype.$$updated.call(this, snap);
this.lessonCount = countLessons(this.finishedLessons, $stateParams.id);
}
});
var refTemp = new Firebase($rootScope.baseUrl + "users/" + $rootScope.userId);
var userTemp = new UserWithLessonsCounter(refTemp);
userTemp.$bindTo($scope, "userTemp").then(function(){
console.log($scope.userTemp);
});
userTemp.$watch(function() {
console.log("Does this run at all? " + $scope.userTemp.lessonCount);
});
我更新了用户对象,除非我刷新页面,否则 lessonCount 值没有改变。而$watch里面的console.log根本就没有运行。怎么了?
$bindTo 返回的承诺只被调用一次。它不是事件侦听器。每次有变化时,您都无法收听此更新。
请先阅读 the guide, start to finish, and read about Angular's $watch 方法,然后再继续这条路线,作为一些基础知识,这不应该是你的第一直觉。
初学者的方法是使用 $watch:
MyFirebaseService.getCurrentUser().$bindTo($scope, "user");
$scope.$watch('user', function() {
for (var key in $scope.user.finishedLessons) {
if ($scope.user.finishedLessons.hasOwnProperty(key)) {
if ($scope.user.finishedLessons[key].associatedCourseId == $stateParams.id) {
$scope.finishLessonCount++;
}
}
};
console.log ($scope.finishLessonCount);
});
或者,在熟悉了 AngularFire API 之后,人们可能会选择 $scope.user.$watch() 来代替 scope 方法,这样会更有效率。
写了大部分 AngularFire 代码后,我会选择 $extend 工具,它是为这样的用例添加的:
// making some assumptions here since you haven't included
// the code for your firebase service, which does not seem SOLID
app.factory('UserWithLessonsCounter', function($firebaseObject) {
return $firebaseObject.$extend({
$$updated: function(snap) {
var changed = $firebaseObject.prototype.$$updated.call(this, snap);
this.lessonCount = countLessons(this.finishedLessons);
return changed;
}
});
});
function countLessons(lessons) {
var count = 0;
for(var key in lessons) {
if( lessons.hasOwnProperty(key) ) {
count++;
}
}
return count;
}
现在在您的控制器中:
app.controller('...', function($scope, UserWithLessonsCounter) {
var ref = new Firebase(...);
var user = new UserWithLessonCounter(ref);
user.$bindTo($scope, 'user');
user.$watch(function() {
console.log($scope.user.lessonCount);
});
});
我有一个 firebaseObject (MyFirebaseService.getCurrentUser()) 绑定到 $scope.user。 绑定成功后,我循环对象以查看对象是否包含 "associatedCourseId" 等于某个值 ($stateParams.id)。如果是,则 $scope.finishLessonCount 计数。问题是,当我通过其他页面或在 firebase 内部在 firebaseObject(绑定到用户)中添加新对象时,finishLessonCount 值不会像我对 3 种方式绑定所期望的那样改变。我需要刷新页面以查看 finishLessonCount 反映的真实值。怎么了?我希望在将更多 finishedLessons 添加到 firebaseObject 中时使用比较函数更改 finishLessonCount。请看下面的代码:
MyFirebaseService.getCurrentUser().$bindTo($scope, "user").then(function(){
for (var key in $scope.user.finishedLessons) {
if ($scope.user.finishedLessons.hasOwnProperty(key)) {
if ($scope.user.finishedLessons[key].associatedCourseId == $stateParams.id) {
$scope.finishLessonCount++;
}
}
};
console.log ($scope.finishLessonCount);
});
UPDATE 1 根据@Kato 解决方案: 我决定使用 Extending firebaseOject 的方式来解决这个问题。但是,它仍然没有。我没有在这里使用工厂来简化事情,因为我需要传入 courseId 来进行操作。这是我的代码:
function countLessons(lessons, courseId) {
var count = 0;
for(var key in lessons) {
if( lessons[key].associatedCourseId == courseId) {
count++;
}
}
return count;
}
var UserWithLessonsCounter = $firebaseObject.$extend({
$$updated: function(snap) {
var changed = $firebaseObject.prototype.$$updated.call(this, snap);
this.lessonCount = countLessons(this.finishedLessons, $stateParams.id);
}
});
var refTemp = new Firebase($rootScope.baseUrl + "users/" + $rootScope.userId);
var userTemp = new UserWithLessonsCounter(refTemp);
userTemp.$bindTo($scope, "userTemp").then(function(){
console.log($scope.userTemp);
});
userTemp.$watch(function() {
console.log("Does this run at all? " + $scope.userTemp.lessonCount);
});
我更新了用户对象,除非我刷新页面,否则 lessonCount 值没有改变。而$watch里面的console.log根本就没有运行。怎么了?
$bindTo 返回的承诺只被调用一次。它不是事件侦听器。每次有变化时,您都无法收听此更新。
请先阅读 the guide, start to finish, and read about Angular's $watch 方法,然后再继续这条路线,作为一些基础知识,这不应该是你的第一直觉。
初学者的方法是使用 $watch:
MyFirebaseService.getCurrentUser().$bindTo($scope, "user");
$scope.$watch('user', function() {
for (var key in $scope.user.finishedLessons) {
if ($scope.user.finishedLessons.hasOwnProperty(key)) {
if ($scope.user.finishedLessons[key].associatedCourseId == $stateParams.id) {
$scope.finishLessonCount++;
}
}
};
console.log ($scope.finishLessonCount);
});
或者,在熟悉了 AngularFire API 之后,人们可能会选择 $scope.user.$watch() 来代替 scope 方法,这样会更有效率。
写了大部分 AngularFire 代码后,我会选择 $extend 工具,它是为这样的用例添加的:
// making some assumptions here since you haven't included
// the code for your firebase service, which does not seem SOLID
app.factory('UserWithLessonsCounter', function($firebaseObject) {
return $firebaseObject.$extend({
$$updated: function(snap) {
var changed = $firebaseObject.prototype.$$updated.call(this, snap);
this.lessonCount = countLessons(this.finishedLessons);
return changed;
}
});
});
function countLessons(lessons) {
var count = 0;
for(var key in lessons) {
if( lessons.hasOwnProperty(key) ) {
count++;
}
}
return count;
}
现在在您的控制器中:
app.controller('...', function($scope, UserWithLessonsCounter) {
var ref = new Firebase(...);
var user = new UserWithLessonCounter(ref);
user.$bindTo($scope, 'user');
user.$watch(function() {
console.log($scope.user.lessonCount);
});
});