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

时间:2016-10-22 15:07:26

标签: http-status-code-404 vue.js vue-router

我正在尝试使用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>'
        }
    }
})

5 个答案:

答案 0 :(得分:71)

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

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,这将失败,除非您的服务器将其视为特殊情况并提供静态页面。

  3. 让我知道它是否有效!

答案 1 :(得分:6)

@mani的响应现在已经有些过时了,因为从Vue 3开始使用所有'*'路由都是no longer supported。如果这对您而言不再起作用,请尝试将旧的万能路径替换为

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

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

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

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

答案 2 :(得分:3)

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

将其放入全局挂钩和放入组件本身并不理想,全局挂钩会检查每个请求,因此您将需要编写很多条件来检查在创建组件时是否为404和window.location.href为时已晚,因为请求已进入组件,然后将其取出。

我要做的是为404页设置专用网址,并为所有未找到的内容提供路径*

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

当我的网站使用i18n时,您可以忽略:locale,以便确保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;
    }
}

答案 3 :(得分:2)

@mani的原始答案是所有您想要的,但是如果您也想以正式的方式阅读,这里是

参考Vue的官方页面

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

答案 4 :(得分:0)

不要使用重定向,使用beforeEnter

SELECT products.*, 
       productvar1.colorvalue as colorvalue1,
       productvar1.price as price1,
       productvar2.colorvalue as colorvalue2,
       productvar2.price as price2
FROM PT1 products 
LEFT JOIN productvariations AS productvar1 
ON products.idproducts = productvar1.productid AND productvar1.colorvalue = '0' 
LEFT JOIN productvariations AS productvar2 
ON products.idproducts = productvar2.productid AND productvar2.colorvalue = '1'
WHERE products.checked = '0' LIMIT 200;