0

我正在尝试使用 AngularJS 和 moment.js 以在加载 json 数据后格式化时间,并且我使用 $watch 来监视 $scope.comments,但不确定 $watch 为何识别 3 个事件(结果集来自json 包含 3 个项目)而不是我预期的 1 次。console.lof('changed') 已执行 3 次

var MyApp = angular.module('MyApp', ['ng', 'commentController']);
MyApp.config(['$routeProvider',
    function ($routeProvider) {
        $routeProvider.
        when('', {
            templateUrl: '/partials/comment-list.html',
            controller: 'CommentListCtrl'
        });
    }
]);

MyApp.directive("timeago", function () {
    return function ($scope, element, attrs) {
        $scope.$watch("comments", function () {
            $('.timeago').each(function (index) {
                console.log('chaneged');
                $(this).removeClass('timeago');
                var time = moment($(this).text());
                //console.log(time.fromNow());
                $(this).text(time.fromNow());
            })
        });
    };
});

/* Controllers */
var commentController = angular.module('commentController', []);
commentController.controller('CommentListCtrl', function CommentListCtrl($http, $scope) {
    $scope.comments = [];

    $http.get('/api/json?n=3').success(function (data) {
        $scope.commentsLoaded(data);
    });

    $scope.commentsLoaded = function (data, status) {
        $scope.comments = data;
    }

});

和模板:

<div ng-Controller="CommentListCtrl">
    <ul class="comments" timeago>
        <li ng-repeat="comment in comments">        
            <span class="timeago">{{comment.time}}</span>
            <p>{{comment.content}}</p>
        </li>
    </ul>
</div>

非常感谢您的帮助。

4

2 回答 2

1

在您的情况下, $watch 执行 3 次的原因是:

  • 它第一次执行是在启动时,其中newValue == undefined
  • 第二次是当您调用此行时:$scope.comments = [];
  • 第三次是收到json的时候:$scope.comments = data;

它与您的 json 无关,有 3 个项目。

但是,不确定为什么 console.log($(this).text()); 加载数据后只得到这个:{{comment.time}}似乎在模板渲染之前捕获了事件

因为当时,angular 还没有更新它的绑定,视图也没有更新

对于关注点的分离以及我们应该如何使用像角度这样的 mvc 结构,视图是用于显示的,您不应该从那里访问数据,而是通过模型访问它。在您的情况下,您正在尝试格式化显示,它应该是过滤器的工作

像这样写一个过滤器:

angular.module('commentController').
  filter('dateFormat', function() {
    return function(input) {
      return moment(input).fromNow();
    }
  });

在 HTML 中使用它,不需要timeago指令:

<div ng-Controller="CommentListCtrl">
    <ul class="comments">
        <li ng-repeat="comment in comments">        
            <span class="timeago">{{comment.time | dateFormat }}</span>
            <p>{{comment.content}}</p>
        </li>
    </ul>
</div>
于 2013-10-10T12:21:08.480 回答
1

watch 方法接受一个带有 2 个参数(newValue,oldValue)的函数。您可以在执行手表时检查这些值。

 $scope.$watch("comments", function (newValue,oldValue) {

据我所知,它第一次执行是在设置时,其中 oldValue 是null. 然后在任何其他任务。检查这些值,您就会知道。

要正确处理它,请进行检查,例如

if(newValue && newValue!=oldValue) {
   //do something
}
于 2013-10-10T09:27:47.307 回答