【发布时间】:2014-03-04 16:25:59
【问题描述】:
假设我有一个用于编辑电子贺卡的 Angular 应用程序。创建新的 eCard 使用类似 #/ecard/create 的路径,编辑现有 eCard 使用类似 #/ecard/:id 的路径。选项卡系统让我们可以同时打开多张电子贺卡进行编辑。
我们想要一个自动保存功能,就像用户期望的那样,例如现代 webmail 或 wiki 软件(或 StackOverflow 本身)。我们不想在用户打开创建表单的那一刻保存电子贺卡草稿,这会给我们很多空白电子贺卡草稿,因此我们会在用户开始输入后开始自动保存。
我想在我们的控制器中编写这样的代码(这被简化为不包括错误处理或关闭选项卡时停止自动保存等):
$scope.autosave = function () {
ECardService.autosave($scope.eCard).then(function (response) {
$location.path('/ecard/' + response.id).replace();
$timeout($scope.autosave, AUTOSAVE_INTERVAL);
});
};
$timeout($scope.autosave, AUTOSAVE_INTERVAL);
上面的代码效果很好,除了一件事:当位置改变时,我们的控制器重新加载并且视图重新渲染。因此,如果用户在自动保存完成时正在打字,则会出现短暂的闪烁,然后他们就会失去位置。
我考虑了几种方法来缓解这个问题:
1) 将路径更改为使用搜索路径,并在ngRoute 配置中将reloadOnSearch 设置为false。因此路径将从#/ecard?id=create 更改为例如#/ecard/id=123,因此不会强制重新加载。问题是我可能打开了多个电子贺卡,我确实想从例如更改。 #/ecard/id=123 到 #/ecard/id=321 触发路由更改并重新加载控制器。所以这实际上是不可行的。
2) 在这种情况下,不要费心编辑 URL 并处理后退按钮会产生奇怪的行为。这很诱人,但是如果用户打开他们现有的 eCard 列表并尝试打开已保存的特定 eCard,我们希望选项卡系统能够识别它应该只显示当前存在的选项卡而不是打开一个新选项卡。
从理论上讲,我们可以通过更新我们的标签系统来解决这个问题。它不仅可以检查路径,还可以检查路径和持久 id,我们可以将其存储在某个地方。这将使选项卡系统变得更加复杂,而且对于这个功能来说这似乎有点过头了。
3) 仅在用户不主动编辑时更改 URL,例如编写一个$scope.userIsIdle() 函数返回true,如果自用户进行任何编辑后至少10 秒,则基于此更新路径。其简化版本如下所示:
$scope.updatePathWhenSafe = function (path) {
if ($scope.userIsIdle()) {
$location.path(path).replace();
} else {
$timeout(function () {
$scope.updatePathWhenSafe(path);
}, 1000);
}
};
我最终选择了选项 #3;它比选项#2 简单得多,但实现和测试比我想要的要复杂得多,尤其是当我考虑到边缘情况时,例如“如果该选项卡在此超时触发时不再是活动选项卡怎么办?”我希望选项 #4 成为可能。
4) 在 Angular 之外编辑当前位置和历史记录,假设这是必要且可能的。这将是我的首选解决方案,但我的研究表明,尝试绕过 $location 服务来更改路径或编辑历史记录是不安全/不明智的。有什么安全的方法可以做到这一点吗?如果我可以说“更改当前路径但不要重新加载控制器”,这会使事情如此变得简单得多。
选项#4 可能/可行吗?如果没有,那么有没有更好的方法?也许是一些神奇的“以角度方式做,但不知何故不刷新控制器”?
【问题讨论】:
-
对我来说,选项 (2) 听起来很明显。但是如果不了解您的
tabbing system是如何工作的,就很难进一步研究这个选项。你说tabbing系统可以打开多个eCard进行编辑,如果你说使用路径/ecard/:id进行编辑,如何区分不同的eCard? -
为什么在
autosave的then函数中使用$location.path? 据我了解,除非选项卡更改,否则位置不应更改。我会假设自动保存功能正在响应当前选项卡的响应,因此response的id应该与当前的id相同。 -
@TylerEich:新的电子贺卡没有 ID。理论上,我们可以用一个 id 来开始每个 eCard,但是如果您打开撰写表单然后关闭它而不做任何更改,就会有一个空白的 eCard 草稿。这就是为什么我们需要更改位置,例如
/ecard/new到/ecard/123. -
@Beyers:为了澄清,现有电子贺卡的网址是例如
/ecard/123或/ecard/42- 我使用:id表示我们实际上将 id 放在了路径中,然后我们通过$routeParams服务获得。 -
@EliCourtwright 我明白了,我要问的是您说您可以同时打开多个电子贺卡进行编辑,那么当您在同一时间?
标签: javascript angularjs tabs angularjs-routing