35

我正在开发一个 AngularJS 应用程序,该应用程序具有一条捕获所有路由(例如,.when('/:slug', {...)),这是支持来自应用程序的先前(非角度)版本的旧 url 格式所必需的。响应 catch all 的控制器尝试拉取相关对象,如果未找到,则使用该$location.path方法重定向到 404 页面。这可以让用户进入 404 页面,但是当用户在浏览器中回击时,它会将他们带回到最初迫使他们进入 404 页面的页面,并且他们最终无法摆脱循环。

我的问题是,是否有 1)更好的模式来处理这种情况,或者 2)是否有一种方法可以重新路由用户而不强制浏览器中的历史推送状态?

4

2 回答 2

58

您可以在不添加到历史状态的情况下更改 url,“替换方法”下可以找到。这实际上与调用 HTML5 的 history.replaceState() 相同。

$location.path('/someNewPath').replace();

我还没有发现可以在不更改 url 的情况下更改视图。我发现更改视图的唯一方法是更改​​位置路径。

于 2013-09-25T22:21:44.523 回答
3

路由系统的正常操作是让$route服务监听$locationChangeSuccess事件,然后开始加载路由。当它完成加载模板、执行解析步骤并实例化控制器然后它依次广播一个$routeChangeSuccess事件。这$routeChangeSuccess是由指令监控的ng-view,这就是它知道一旦新路由准备好就换出模板和范围的方式。

综上所述,$route通过更新当前路由并发出路由更改事件以更新视图,让应用程序代码模拟服务的行为可能会起作用:

var errorRoute = $route.routes[null]; // assuming the "otherwise" route is the 404
// a route instance is an object that inherits from the route and adds
// new properties representing the routeParams and locals.
var errorRouteInstance = angular.inherit(
    errorRoute,
    {
        params: {},
        pathParams: {},
    }
);
// The $route service depends on this being set so it can recover the route
// for a given route instance.
errorRouteInstance.$$route = errorRoute;

var last = $route.current;
$route.current = errorRouteInstance;

// the ng-view code doesn't actually care about the parameters here,
// since it goes straight to $route.current, but we should include
// them anyway since other code might be listening for this event
// and depending on these params to behave as documented.
$rootScope.broadcast('$routeChangeSuccess', errorRoute, last);

以上假设您的“否则”路线没有任何“解决”步骤。它还假定它不期望任何$routeParams,这对于“否则”路线当然是正确的,但如果您使用不同的路线,则可能并非如此。

目前尚不清楚上述内容取决于实现细节与接口。该$routeChangeSuccess事件当然已记录在案,但$$route路由实例的属性似乎是路由系统的实现细节,因为它具有双美元符号名称。“否则”路由与密钥一起保存在路由表中的null细节可能也是一个实现细节。因此,尽管如此,这种行为在 AngularJS 的未来版本中可能不会保持功能。

有关更多信息,您可以参考处理此事件ng-view代码,这最终是上述代码试图取悦的,以及我用作上述示例基础的事件发射代码。正如您可以从这些链接中推断的那样,这篇文章中的信息来自 AngularJS 的最新主分支,在撰写本文时它被标记为 1.2.0-snapshot。

于 2013-10-04T01:22:14.557 回答