未找到页面上的 Vue 路由器重定向(404)

我试图重定向到没有使用 router.beforeEach全局钩子找到的页面上的404.html,但是没有多少成功(使用 VueVue-Router1.0) :

router.beforeEach(function (transition) {
if (transition.to.path === '/*') {
window.location.href = '/404.html'
} else {
transition.next()
}
});

这并不是在插入不存在的路由时重定向到页面 404.html,而只是给我一个空的片段。只有当硬编码 some-site.com/* 时,它才会重定向到预期的 some-site.com/404。Html

我肯定这里有些很明显的东西我忽略了,但是我不知道是什么。


请注意,我正在寻找的是一个 重定向到一个新页面,而不是重定向到另一个路由,这可以很容易地实现使用 router.redirect,如在这些代码片段:

router.redirect({
'*': '404'
})

然而在我的 router.map上,我可以有以下几点:

 router.map({
'/404': {
name: '404'
component: {
template: '<p>Page Not Found</p>'
}
}
})
186318 次浏览

I think you should be able to use a default route handler and redirect from there to a page outside the app, as detailed below:

const ROUTER_INSTANCE = new VueRouter({
mode: "history",
routes: [
{ path: "/", component: HomeComponent },
// ... other routes ...
// and finally the default route, when none of the above matches:
{ path: "*", component: PageNotFound }
]
})

In the above PageNotFound component definition, you can specify the actual redirect, that will take you out of the app entirely:

Vue.component("page-not-found", {
template: "",
created: function() {
// Redirect outside the app using plain old javascript
window.location.href = "/my-new-404-page.html";
}
}

You may do it either on created hook as shown above, or mounted hook also.

Please note:

  1. I have not verified the above. You need to build a production version of app, ensure that the above redirect happens. You cannot test this in vue-cli as it requires server side handling.

  2. Usually in single page apps, server sends out the same index.html along with app scripts for all route requests, especially if you have set <base href="/">. This will fail for your /404-page.html unless your server treats it as a special case and serves the static page.

Let me know if it works!

Update for Vue 3 onward:

You'll need to replace the '*' path property with '/:pathMatch(.*)*' if you're using Vue 3 as the old catch-all path of '*' is no longer supported. The route would then look something like this:

{ path: '/:pathMatch(.*)*', component: PathNotFound },

See the docs for more info on this update.

This answer may come a bit late but I have found an acceptable solution. My approach is a bit similar to @Mani one but I think mine is a bit more easy to understand.

Putting it into global hook and into the component itself are not ideal, global hook checks every request so you will need to write a lot of conditions to check if it should be 404 and window.location.href in the component creation is too late as the request has gone into the component already and then you take it out.

What I did is to have a dedicated url for 404 pages and have a path * that for everything that not found.

{ path: '/:locale/404', name: 'notFound', component: () => import('pages/Error404.vue') },
{ path: '/:locale/*',
beforeEnter (to) {
window.location = `/${to.params.locale}/404`
}
}

You can ignore the :locale as my site is using i18n so that I can make sure the 404 page is using the right language.

On the side note, I want to make sure my 404 page is returning httpheader 404 status code instead of 200 when page is not found. The solution above would just send you to a 404 page but you are still getting 200 status code. To do this, I have my nginx rule to return 404 status code on location /:locale/404

server {
listen                      80;
server_name                 localhost;


error_page  404 /index.html;
location ~ ^/.*/404$ {
root   /usr/share/nginx/html;
internal;
}


location / {
root   /usr/share/nginx/html;
index  index.html index.htm;
try_files $uri $uri/ @rewrites;
}


location @rewrites {
rewrite ^(.+)$ /index.html last;
}


location = /50x.html {
root   /usr/share/nginx/html;
}
}

@mani's response is now slightly outdated as using catch-all '*' routes is no longer supported when using Vue 3 onward. If this is no longer working for you, try replacing the old catch-all path with

{ path: '/:pathMatch(.*)*', component: PathNotFound },

Essentially, you should be able to replace the '*' path with '/:pathMatch(.*)*' and be good to go!

Reason: Vue Router doesn't use path-to-regexp anymore, instead it implements its own parsing system that allows route ranking and enables dynamic routing. Since we usually add one single catch-all route per project, there is no big benefit in supporting a special syntax for *.

(from https://next.router.vuejs.org/guide/migration/#removed-star-or-catch-all-routes)

Do not use redirect; use beforeEnter

const router = [


// { path: '*', redirect: '/404'},
{ path: '*', beforeEnter: (to, from, next) => { next('/404') } },
{
path: '/404',
name: '404',
component: () => import('@/views/404')
}
]

This will make it work too:

{
path: '/*/',
name: 'PageNotFound',
component: () => import('../views/PageNotFound.vue')
}

I do not specifically answer your question, but I have an answer for anyone who is looking for page not found route syntax in Vue js just like I was looking for and came here.

Here are two things you can do:

  1. First, create a component in the views and write some HTML like error 404!

  2. Then import that component in index.js in router folder and import it there like:

  3. import yourcomponentName from '../views/yourcomponentName.vue'

  4. const routes = [ { path: '/:catchAll(.*)', ->This is the regex pattern name: 'whatever name you want to give', component: yourComponentName }]

  5. If it does not work then use this

  6. const routes = [ { path: '/:pathMatch(.*)', ->This is the regex pattern name: 'whatever name you want to give', component: yourComponentName }]

    Remove the comment: 'This is the regex pattern it is writtern for understanding'

path: "*" is outdated. It belongs to vue-router2 on vue-router3. You can catch all 404 error pages by using

/:pathMatch(.*)*

It works well.