如何在Ember.js中处理“未匹配路由”并显示404页面?

47

如何处理错误

Uncaught Error: No route matched the URL '...'

并显示自定义的404页面?


注意:这个问题之前已经被问过并且回答了几个月前 - 但是现在不再起作用。

5个回答

54
App.Router.map(function() {
  //set up all of your known routes, and then...
  this.route("fourOhFour", { path: "*path"});
});

您可以定义FourOhFourRoute来显示您选择的“找不到路由”消息。在fourOhFour路由中,您可以通过路径参数访问最初请求的路径。

编辑:仅为澄清-此答案是在其他答案被报告无法使用后提供的。

编辑2:我已经更新了答案以反映Yehuda Katz的评论(如果我有错误,请让我知道)。


谢谢!当我第一次尝试时,确实错过了冒号。这应该被记录在某个地方! - Pascal
9
:不是必需的,但参数名是必需的(这样你就可以从路由中获取它)。我使用*path - Yehuda Katz
2
如果您正在使用Ember CLI,则模板文件应该是破折号格式(即four-oh-four.hbs)。 - noctufaber

12

以下是一个例子:

我使用通配符路由定义我的路由器中的最后一条路线,请参阅:http://emberjs.com/guides/routing/defining-your-routes/#toc_wildcard-globbing-routes

我有一个/not-found路由,参见我路由器中定义的最后一个路由/*path,以捕获任何文本字符串,请参阅:https://github.com/pixelhandler/blog/blob/master/client/app/router.js#L19

Router.map(function () {
  this.route('about');
  this.resource('posts', function () {
    this.resource('post', { path: ':post_slug' });
  });
  this.resource('admin', function () {
    this.route('create');
    this.route('edit', { path: ':edit_id' });
  });
  this.route('not-found', { path: '/*path' });
});

该路由重定向到/not-found,请参见:https://github.com/pixelhandler/blog/blob/master/client/app/routes/not-found.js

import Ember from 'ember';
export default Ember.Route.extend({
  redirect: function () {
    var url = this.router.location.formatURL('/not-found');
    if (window.location.pathname !== url) {
      this.transitionTo('/not-found');
    }
  }
});

任何具有钩子(例如modelbeforeModelafterModel)的路由,如果导致一个被拒绝的承诺,可以使用error操作来转换到404页面。

actions: {
  error: function (error) {
    Ember.Logger.error(error);
    this.transitionTo('/not-found');
  }
}

这将呈现一个 not-found 模板,请参见:https://github.com/pixelhandler/blog/blob/master/client/app/templates/not-found.hbs

<h1>404 Not Found</h1>
<p>
  Perhaps you have a link that has changed, see {{#link-to 'posts'}}Archives{{/link-to}}.
</p>

这是我的404页面:http://pixelhandler.com/not-found


我最终在这个主题上写了一篇文章,链接在这里:http://pixelhandler.com/posts/how-to-use-404-page-in-your-emberjs-application - pixelhandler
2
很棒的解决方案!我发现使用replaceWith而不是transitionTo更合适,否则如果用户在浏览器上点击“返回”按钮,他们将始终被重定向回到/not-found页面,因为他们试图返回到最初未找到的页面。 - SeanK

6
您可以尝试在路由器的末尾添加一个通配符路由:
App.Router.map(function() {
  this.resource('post', ...);
  this.resource('user', ...);
  this.route('catchAll', { path: '/*' });
});

App.CatchAllRoute = ...

我之前从未考虑过这个问题 - 但是我需要为每个资源都设置一个“catchAll”...现在可以作为一种解决方法,但我想知道是否有更好的方法... - stephanos

1

在Ember 2.x中

App.Router.map函数内,将下面的代码放在回调函数的末尾。

this.route('your_handler_route_name', { path: '/*path' });

现在,之前定义的所有路由没有被捕获的路由都将被 your_handler_route_name 路由捕获。

1
这是一个好答案。但是我遇到的问题是,如果我的 URL 更加复杂(例如,mysite/good_directory/bad_directory),那么我就会遇到困难。 - Cameron

0

解决方案1

显示404内容:

App.Router.reopen({
        handleURL: function (url) {
            try {
                return this._super(url);
            } catch (error) {
                if (error.message.match(/No route matched the URL/)) {
                    return this._super('/404');
                }
            }
        }
    });

如果您想要将URL更改为404:
App.Router.reopen({
        location: locationImplementation,
        handleURL: function (url) {
            try {
                return this._super(url);
            } catch (error) {
                if (error.message.match(/No route matched the URL/)) {
                    this.transitionTo('404');
                    return this._super('/404');
                }
            }
        }
    });

为了理解这里发生了什么,请查看ember rc2中的第22636行。 解决方案2 解析当前URL,并使用App.Router.router.recognizer.hasRoute('route.path.goes.here');检查路由或资源是否存在。

这看起来是一个不错的方法!但是错误消息的匹配似乎非常脆弱.. - stephanos
@stephanos 这是我目前发现的最好的东西。无论如何,在这个 Ember 版本中,消息不会改变,所以当升级到 rc3 时,我会检查它。另一个选项是覆盖 Ember.js 的这一部分 - 在 JS 中非常简单,最后一个函数胜出。 - Wojciech Bednarski
这似乎不起作用,请提供替代方案,在第 "this._super(url);" 行没有抛出任何异常。也许是 Promise 模式延迟了异常。(Ember v1.9.1) - Bamboo

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