返回浏览器历史记录后数据未绑定
Data not binded after browser history back
我有一个基于 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>
当我进入这个页面时,一切正常。显示类别名称,然后我使用 link 导航到文章。一切正常。当我使用浏览器历史记录后退按钮时,问题就开始了。
它会加载文章列表状态,会使用服务下载项目并显示列表,但不会显示类别名称。只是简单的 {{ name }} 正在显示。
Chrome 显示奇怪的错误,但 Firefox 显示更具体的问题:
Error: [$rootScope:inprog] $digest already in progress
http://errors.angularjs.org/1.4.5/$rootScope/inprog?p0=%24digest
虽然我明白为什么这可能是一个问题,并且在 other SO question 中有清楚的描述,但我不明白问题的根源是什么,因此我无法解决它。
这听起来像是从外部事件执行 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
。否则,它按原样执行回调。
问题可能不在您的应用中。它可能来自您正在使用的堆栈。您需要进行一些挖掘以找出问题所在。如果问题出在堆栈中。您应该将其报告给作者,以便其他人可以受益。
我有一个基于 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>
当我进入这个页面时,一切正常。显示类别名称,然后我使用 link 导航到文章。一切正常。当我使用浏览器历史记录后退按钮时,问题就开始了。
它会加载文章列表状态,会使用服务下载项目并显示列表,但不会显示类别名称。只是简单的 {{ name }} 正在显示。
Chrome 显示奇怪的错误,但 Firefox 显示更具体的问题:
Error: [$rootScope:inprog] $digest already in progress
http://errors.angularjs.org/1.4.5/$rootScope/inprog?p0=%24digest
虽然我明白为什么这可能是一个问题,并且在 other SO question 中有清楚的描述,但我不明白问题的根源是什么,因此我无法解决它。
这听起来像是从外部事件执行 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
。否则,它按原样执行回调。
问题可能不在您的应用中。它可能来自您正在使用的堆栈。您需要进行一些挖掘以找出问题所在。如果问题出在堆栈中。您应该将其报告给作者,以便其他人可以受益。