浏览器历史记录后数据未绑定

时间:2015-10-08 13:07:57

标签: javascript angularjs angularjs-scope angularjs-routing

我有一个基于jHipster模板的网页和浏览器后退按钮的问题。

我们说我有两页

  • 文章列表(/articles/{id},{name},类别ID,类别名称)
  • 文章详情(/article/{id},文章ID)

文章列表页面显示范围中设置的类别名称:

JS:

$scope.name = $stateParams.name; 

HTML:

<div>{{ name }}</div>
<ul>
<li ng-repeat="item in items">
    <a ui-sref="article({id: item.id})">{{ item.title }}</a>
</li>
</ul>

当我进入此页面时,它完全正常。显示类别名称,然后我使用链接导航到文章。一切都很好。使用浏览器历史记录后退按钮时问题开始。

它加载文章列表状态,它使用服务下载项目并显示列表,但它不显示类别名称。正在显示简单的{{name}}。

Chrome显示奇怪的错误,但Firefox显示更具体的问题:

Error: [$rootScope:inprog] $digest already in progress
http://errors.angularjs.org/1.4.5/$rootScope/inprog?p0=%24digest

虽然我确实理解为什么它可能是一个问题并且在other SO question中已经清楚地描述了,但我不明白问题的根源是什么,因此我无法理解解决它。

1 个答案:

答案 0 :(得分:0)

这听起来像是从外部事件执行AngularJS代码导致的问题。例如,您需要使用$scope.$apply(...)来执行window.resize事件中的代码。

这可能在正常的应用程序使用期间正常工作,但当您回到历史记录时,代码将在摘要循环中执行。这会触发错误,如果在编译期间发生此错误,则模板最终会出现不完整的绑定。这就是您在页面上看到{{name}}的原因。

这是一个可以解决问题的功能。

    /**
     * @param {angular.IScope|angular.IRootScopeService} $scope
     * @param {function()} func
     */
    function safeApply($scope, func) {
        if ($scope.$$phase) {
            func();
        }
        else {
            $scope.$apply(function () {
                func();
            });
        }
    };

您需要使用$scope.$apply(function(){....})

查找并替换safeApply($scope,function(){....});

safeApply将检查摘要是否已在进行中。如果没有摘要,它知道该方法是从Angular外部调用的,它将调用$apply。否则,它按原样执行回调。

问题可能不在您的应用中。它可能是你正在使用的堆栈中的东西。您需要进行一些挖掘以找出问题所在。如果问题在堆栈中。您应该向作者报告,以便其他人可以受益。