Ember路由器 - 如何处理404(未找到)路由?

14

我正在研究如何使用Ember.Router处理应用程序中的无效路由。

当前,如果我输入一个无效的路径,例如myapp.com/#FooBarDoesntExist,它会重定向到索引路由('/')。我希望定义一个notFound或404状态,以便可以将其路由到,这样我就可以告知用户发生了什么。而不是他们被转到主页。

3个回答

19

处理这个问题的一个好方法是声明一个路由,将所有可能的网址映射到你的路由中。你可以在这里找到一个例子:http://jsfiddle.net/mbreton/r3C9c/

var App = Ember.Application.create();

App.Router.map(function(){
    this.route('detail', {path: "detail"});
    this.route('missing', { path: "/*path" });
});


App.MissingRoute = Em.Route.extend({
    redirect: function () {
        Em.debug('404 :: redirection to index');
        this.transitionTo("index");
    }
});

App.ApplicationView = Em.View.extend({
    didInsertElement:function(){
        $('#missingLink').on('click', function (e){
            window.location.hash = "#/pepepepepep";
            return false;      
        });
    }
});
在这个例子中,所有未知的网址将被重定向到主页路由。

有没有人支持这条评论 ^^?我问这个问题是因为原贴和这个帖子相隔了将近一年。 - Ian Steffy
1
不,如果您有嵌套资源,这是行不通的。也就是说,它将无法捕获/nestedResource/routeThatDoesNotExist。 - marcopolo
这是在 http://emberjs.com/guides/routing/defining-your-routes/#toc_wildcard-globbing-routes 上记录的默认处理不正确的URL的方法,它也适用于嵌套资源。 - ppcano

6

Ember.Router在当前版本中不提供处理未知路由的方法。是时候动手解决了!

解决方案1- 快速而肮脏

这里的想法是:我们有Ember.Router.route(path)方法,该方法会使用请求的(可能未知的)路径进行调用。在调用此方法后,路由器的路径已知。因此,如果我们比较请求的路径和实际路径,并且它们不同 - 那么请求的路径无效,我们可以将用户重定向到404页面。

  App.Router = Ember.Router.extend({

    route: function(path) {
      this._super(path);
      var actualPath = this.get("currentState").absoluteRoute(this);
      if (path !== actualPath) {
        this.transitionTo("404page");
      }
    }
  });

这个解决方案相当昂贵。例如,如果当前状态是“/a/b/c”,用户想要导航到“/b/d/e/unknown”,路由器将忠实地输入已知状态“b”、“d”和“e”,然后我们才会将路径丢弃为未知的。在实际路由开始之前告诉我们这一点会很好。
解决方案2-玩弄私有方法
在这里,我们检查给定路径的有效性,然后告诉路由器继续:
App.Router = Ember.Router.extend({

checkPath: function (path) {
  path = path.replace(this.get('rootURL'), '').replace(/^(?=[^\/])/, "/"); 
  var resolvedStates = this.get("states.root").resolvePath(this, path);
  var lastState = resolvedStates.get("lastObject");
  return lastState.match.remaining == "";
},

route: function(path) {
  if (this.checkPath(path)) {
    this._super(path);
  } else {
    this.transitionTo("404page");
  }
}
});

这种解决方案也有缺点 - 它使用标记为私有的resolvePath方法。尽管如此,我会使用这个解决方案,因为它比第一个更有效。


这两种解决方案都不完美,但在我看来已经非常接近了。感谢您抽出时间把它们都整理出来。奖金已获得。 - Wesley Workman
修复语法错误,您不应该在对象属性上使用 var - iConnor
1
请使用mbreton的解决方案。 - Igor

2
在Ember 1.13中,建议的做法是创建一个catch-all路由来实现这一点:
Router.map(function () {
  this.route('home');
  this.route('login');
  this.route('404', { path: '/*path' });  // capture route in path
});

然后将你的404模板放置在404.hbs中。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接