找不到页面上的 Vue-router 重定向 (404)

Vue-router redirect on page not found (404)

我正在尝试使用 router.beforeEach 全局挂钩重定向到未找到页面上的 404.html,但没有成功(使用 VueVue-Router 1.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>'
        }
    }
})

我认为您应该能够使用默认路由处理程序并从那里重定向到应用程序外部的页面,详情如下:

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 }
    ]
})

在上面的 PageNotFound 组件定义中,您可以指定实际的重定向,这将使您完全退出应用程序:

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

您可以在 created 挂钩上执行此操作,如上所示,也可以在 mounted 挂钩上执行此操作。

请注意:

  1. 以上我没有验证过。您需要构建应用程序的生产版本,确保上述重定向发生。您无法在 vue-cli 中对此进行测试,因为它需要服务器端处理。

  2. 通常在单页应用程序中,服务器会为所有路由请求发送相同的 index.html 以及应用程序脚本,特别是如果您设置了 <base href="/">。这对于您的 /404-page.html 将失败,除非您的服务器将其视为特殊情况并提供静态页面。

如果有效请告诉我!

Vue 3 更新:

如果您使用 Vue 3,则需要将 '*' 路径 属性 替换为 '/:pathMatch(.*)*',因为 '*' 的旧路径是不再支持。路线将如下所示:

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

有关此更新的详细信息,请参阅 the docs

这个答案可能来得有点晚,但我已经找到了一个可以接受的解决方案。我的方法有点类似于@Mani,但我认为我的方法更容易理解。

放到global hook里,放到组件里不太理想,global hook会检查每一个request所以你需要写很多条件来检查是否应该是404和window.location.href在组件里创建为时已晚,因为请求已经进入组件,然后您将其取出。

我所做的是为 404 页设置专用的 url 并为所有未找到的内容设置路径 *

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

您可以忽略 :locale,因为我的网站正在使用 i18n,这样我可以确保 404 页面使用正确的语言。

附带说明一下,我想确保我的 404 页面是 returning httpheader 404 状态代码,而不是找不到页面时的 200。上面的解决方案只会将您发送到 404 页面,但您仍然会收到 200 状态代码。 为此,我将我的 nginx 规则设置为 return 位置 /:locale/404

上的 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 的响应现在稍微过时了,因为在使用 Vue 3 之后,使用 catch-all '*' 路由是 no longer supported。如果这不再适合您,请尝试用

替换旧的 catch-all 路径
{ path: '/:pathMatch(.*)*', component: PathNotFound },

基本上,您应该能够将 '*' 路径替换为 '/:pathMatch(.*)*' 并且一切顺利!

原因: Vue Router 不再使用path-to-regexp,而是实现了自己的解析系统,允许路由排名并启用动态路由。由于我们通常为每个项目添加一个 catch-all 路由,因此支持 *.

的特殊语法没有太大好处

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

不使用重定向,使用beforeEnter

  const  router = [


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