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

Posted

技术标签:

【中文标题】找不到页面上的 Vue-router 重定向 (404)【英文标题】:Vue-router redirect on page not found (404) 【发布时间】:2017-03-04 18:25:41 【问题描述】:

我正在尝试使用 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 轻松实现,例如在这些 sn-ps :

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

而在我的router.map 上,我可以拥有以下内容:

 router.map(
    '/404': 
        name: '404'
        component: 
            template: '<p>Page Not Found</p>'
        
    
)

【问题讨论】:

我还没有解决方案,但是如果您尝试使用 Vue 路由器未处理的 &lt;a&gt; 标签导航到路由会发生什么?它是否导航出应用程序? 无论我使用 href 还是 v-link(例如,href="some-site.com/home" 而不是 v-link="name:'home' ”)。不知道你问的是不是这个? 抱歉,即使我们有&lt;base href="/"&gt;,我也在考虑如何完全退出应用程序。无论如何,这与您的问题无关。我已经在下面发布了我的想法作为答案,请尝试一下,如果它有效,请告诉我! 【参考方案1】:

不要使用重定向,使用 beforeEnter

  const  router = [


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

【讨论】:

你能扩展一下为什么这样更好吗?【参考方案2】:

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

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 钩子也可以。

请注意:

    我还没有验证以上内容。您需要构建应用程序的生产版本,确保发生上述重定向。您不能在 vue-cli 中测试它,因为它需要服务器端处理。

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

让我知道它是否有效!

Vue 3 以后的更新:

如果您使用 Vue 3,则需要将 '*' 路径属性替换为 '/:pathMatch(.*)*',因为不再支持 '*' 的旧包罗万象路径。然后路线看起来像这样:

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

有关此更新的更多信息,请参阅the docs。

【讨论】:

我认为真正的答案是服务器端处理,如上面“请注意”部分所述。你的router.beforeEach 和我的方法一样。您的服务器只需将404.html 作为一个特殊情况处理,您只能在实际服务器中进行测试,而不是vue-cli 您的解决方案运行良好,非常感谢!另外,感谢您使用router.beforeEach 提供有关服务器端处理的提示。我正在使用运行 nginx 的本地机器(vagrant+virtualbox)。我将尝试配置,看看是否可以提出服务器端解决方案。 作为 Vue 路由器 2.2.0,我在路由器定义中使用 path: '*' 来“捕获所有”未定义的路由,如 docs 中所述【参考方案3】:

@mani 的响应现在稍微过时了,因为使用 Vue 3 以后的所有路由 '*' 是 no longer supported。如果这不再适合您,请尝试将旧的包罗万象的路径替换为

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

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

原因: Vue Router 不再使用path-to-regexp,而是实现了自己的解析系统,允许路由排名并启用动态路由。由于我们通常为每个项目添加一个单一的包罗万象的路由,因此支持 * 的特殊语法并没有太大的好处。

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

【讨论】:

(.*)* 替换它怎么样,因为:pathMatch 只是匹配分配给的参数,对吗?所以它可能是 path: '/:thisIsMyCustomErrorCatchAll(.*)*', component: PathNotFound ,。我查看了文档以确认,但找不到任何与此相反的内容。 next.router.vuejs.org/guide/essentials/…【参考方案4】:

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

把它放到全局hook和组件本身是不理想的,全局hook会检查每个请求,所以你需要写很多条件来检查它是否应该是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 页面在找不到页面时返回 httpheader 404 状态代码而不是 200。上面的解决方案只会将您发送到 404 页面,但您仍然会收到 200 状态代码。 为此,我有我的 nginx 规则在位置 /: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;
    

【讨论】:

这个问题导致 404 页面的 200 状态码,从 SEO 角度来看这是不可接受的。谁能建议如何在 VueJS 中为 404 页面设置 404 状态码?【参考方案5】:

@mani 的原始答案是你想要的,但如果你也想以官方方式阅读它,这里是

参考Vue官方页面:

https://router.vuejs.org/guide/essentials/history-mode.html#caveat

【讨论】:

以上是关于找不到页面上的 Vue-router 重定向 (404)的主要内容,如果未能解决你的问题,请参考以下文章

找不到子域时如何使网站重定向到页面[重复]

找不到静态文件路径页面重定向到另一个页面

Javascript 代码重定向到同一页面上的一个部门

如果在反应中找不到本地存储值,则重定向到特定页面

vuejs - 如果已经登录,则从登录/注册重定向到主页,如果未登录 vue-router,则从其他页面重定向到登录

将旧域的每个页面重定向到新域上的相同页面URL