【问题标题】:Vue Router return 404 when revisit to the urlVue Router 在重新访问 url 时返回 404
【发布时间】:2016-07-23 19:08:55
【问题描述】:

我只是启用了 Vue 路由器历史模式。当我通过 v-href 或 href 访问 vue 路由时,它工作正常。但是,当我尝试刷新该页面或直接从浏览器地址栏访问时,它只会返回 404。是否有任何选项可以接受刷新/重新访问该 url?

以下是我的Vue路由器配置

var router = new VueRouter({
  hashbang: false,
  history: true,
  mode: 'html5',
  linkActiveClass: "active",
  root:  '/user'
});

【问题讨论】:

    标签: vue.js vue-router


    【解决方案1】:

    通过刷新页面,您正在使用当前 url 向服务器发出请求,服务器返回 404。您必须在 Web 框架或 Web 服务器级别处理此问题。

    https://router.vuejs.org/en/essentials/history-mode.html

    【讨论】:

    • 在我的情况下,在 IIS 中使用子目录而不是根目录,例如:localhost/myvueapp,那么重写 url 应该是:
    【解决方案2】:

    我认为您错过了 SPA 不是服务器端渲染。至少对大多数人来说。因此,当您访问 /anything 时,您的网络服务器不会将其重定向到 index.html。但是,如果您单击任何 vuejs 路由器链接,它将起作用,因为 javascript 起作用了,而不是服务器端。

    要解决这个问题,请使用 .htaccess 并将所有请求重定向到 index.html,如下所示

    <ifModule mod_rewrite.c>
        RewriteEngine On
      RewriteBase /
      RewriteRule ^index\.html$ - [L]
      RewriteCond %{REQUEST_FILENAME} !-f
      RewriteCond %{REQUEST_FILENAME} !-d
      RewriteRule . /index.html [L]
    </ifModule>
    

    希望对某人有所帮助!

    【讨论】:

    • 如果您使用的是 nginx 主机,这里有一个有用的要点 here
    • 具有讽刺意味的是,要点链接为我返回了 404... :(
    • 谢谢。在 apache 服务器上运行良好。
    【解决方案3】:

    如果你有 root 访问权限,那就更好(在 Ubuntu 上)修改 /etc/apache2/apache2.conf,因为在这种情况下,即使是 Apache 自己的 discourage 使用 .htaccess

    注意,首先,你必须这样做

    sudo a2enmod rewrite
    

    然后,将以下块添加到/etc/apache2/apache2.conf

    <Directory /var/www/html/>
            RewriteEngine On
            RewriteBase /
            RewriteRule ^index\.html$ - [L]
            RewriteCond %{REQUEST_FILENAME} !-f
            RewriteCond %{REQUEST_FILENAME} !-d
            RewriteRule . /index.html [L]
    </Directory>
    

    在这之后,做

    sudo systemctl restart apache2
    

    对我来说,这完美无缺,因为它不仅将 Vue 创建的路由重定向回/,而且实际上将网站刷新到相同的路由,因此刷新后您仍然处于相同的视图中。

    【讨论】:

    • 我测试了 Nginx 和 Apache,我刷新了页面,它们都适用于我,谢谢 j
    【解决方案4】:

    这太简单了,你只需要在你的服务器上添加这个配置:

    阿帕奇

    <IfModule mod_rewrite.c>
      RewriteEngine On
      RewriteBase /
      RewriteRule ^index\.html$ - [L]
      RewriteCond %{REQUEST_FILENAME} !-f
      RewriteCond %{REQUEST_FILENAME} !-d
      RewriteRule . /index.html [L]
    </IfModule>
    

    如果你在 Nginx 上:

    location / {
      try_files $uri $uri/ /index.html;
    }
    

    仅此而已

    欲了解更多信息,请访问Link

    【讨论】:

      【解决方案5】:

      如果您不关心 url 中的哈希值,您可以在路由器配置文件中将模式设置为哈希值:mode: 'hash' 无需设置服务器端即可正常工作。

      const router = new VueRouter({
          routes: Routes,
          mode: 'hash'
      });
      

      vue 中默认提供哈希模式,因此即使您留空而不是 mode: 'hash',它也应该可以工作。

      【讨论】:

      • 你能举个例子吗?
      【解决方案6】:

      如果有人在 .NET Core 作为应用程序的后端处理这个问题,一个不错的方法是在我们的 .NET Core 应用程序的 Startup.cs 中使用一个简单的后备处理程序:

      public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
      {
              ....Your configuration
            app.UseMvc(routes =>
            {
              routes.MapRoute(
                        name: "default",
                        template: "{controller=Home}/{action=Index}/{id?}");
            });
            //handle client side routes
            app.Run(async (context) =>
            {
              context.Response.ContentType = "text/html";
              await context.Response.SendFileAsync(Path.Combine(env.WebRootPath, "index.html"));
            });
          }
       }
      

      更多详情:http://blog.manuelmejiajr.com/2017/10/letting-net-core-handle-client-routes.html

      【讨论】:

        【解决方案7】:

        对于使用 Express 后端的人来说,中间件 connect-history-api-fallback 是这样实现的

        const express = require('express');
        const history = require('connect-history-api-fallback');
        
        const app = express(); 
        app.use(history({
          index: '/' //whatever your home/index path is default is /index.html
        }));
        

        或使用本机节点

        const http = require('http')
        const fs = require('fs')
        const httpPort = 80
        
        http.createServer((req, res) => {
          fs.readFile('index.htm', 'utf-8', (err, content) => {
            if (err) {
              console.log('We cannot open "index.htm" file.')
            }
        
            res.writeHead(200, {
              'Content-Type': 'text/html; charset=utf-8'
            })
        
            res.end(content)
          })
        }).listen(httpPort, () => {
          console.log('Server listening on: http://localhost:%s', httpPort)
        })
        

        两者都是documentation 中的建议。

        【讨论】:

          【解决方案8】:

          对于 Netlify,将以下内容添加到 public/_redirects 文件中...

          /*    /index.html   200
          

          https://www.netlify.com/docs/redirects/#history-pushstate-and-single-page-apps

          【讨论】:

            【解决方案9】:

            如果在尝试上述解决方案后仍有任何人遇到问题,请查找以下方法。 如果你有vue.config.js

            module.exports = {
              publicPath: process.env.PUBLIC_URL || "", // <-- this is wrong
              ...
            };
            

            要么删除 vue.config.js,要么尝试从导出对象中删除 publicPath。

            如果您不想删除 publicPath,也可以尝试以下方法

            module.exports = {
              publicPath: process.env.PUBLIC_URL || "/", default)
              transpileDependencies: ["vuetify"],
            };
            

            【讨论】:

              【解决方案10】:

              在我的情况下,它发生在 azure blob 存储中托管的 SPA 中,作为 azure CDN 下的静态网站。 以下问题的解决方案为我解决了这个问题(在 CDN 端点中应用了修复):Hosting SPA with Static Website option on Azure Blob Storage (clean URLs and Deep links)

              【讨论】:

                【解决方案11】:

                其他人遇到同样的问题,我才意识到

                "book/:bookId/read"  // this will not work after page reload
                

                这不一样

                "/book/:bookId/read" // this is what works even after page reload
                

                这当然是在遵循其他人的建议之后,更重要的是在您的应用服务器端捕获所有路由。 我实际上不知道为什么会这样,但是任何有任何想法的人都可以告诉我们。

                【讨论】:

                  【解决方案12】:

                  我正在使用带有 .net core 2.2 的 Razor Pages,我得到了这个工作:

                  app.UseMvc(routes =>
                          {
                              routes.MapRoute(
                                  name: "default",
                                  template: "{controller}/{action=Index}/{id?}");
                  
                              routes.MapRoute(
                                  name: "spa-fallback",
                                  template: "{*url:regex(^((?!.css|.map|.js|sockjs).)*$)}",
                                  defaults: new { controller = "Index", action = "Index" });
                  
                          });
                  

                  【讨论】:

                    【解决方案13】:

                    来晚了,但是.....

                    如果有人对此的解决方法感兴趣,我只是这样做了:

                    1. 将对已知客户端 URL 的请求重定向到索引(但仅限于已知客户端 URL,这样,您可以为实际未找到页面的 URL 保留 404)。如何执行此操作取决于您的服务器。我当时正在使用烧瓶,只是添加了更多路线。

                    2. 为根 vue 元素添加属性

                        &lt;div id="content" redirect_to="{{redirect_to}}"&gt;&lt;/div&gt;

                    我的视图函数将参数替换为 URL 请求的实际路由

                    1. 在根 vue 组件中,检查该属性并检索其值,如下所示:

                    if (this.$el.attributes['redirect_to'].value !== "") 路径 = this.$el.attributes['redirect_to'].value

                    1. 使用属性值调用 $router.push

                    this.$router.push(path).catch(err => {})

                    (需要 catch 否则路由器会抛出 NavigationDuplicated 错误。)

                    我这样做是因为 SPA 中 url 的全部意义在于它们指向特定的资源,我希望我的用户能够使用这些 URL 来返回到相同的资源。

                    希望这可以帮助某人或为他们指明正确的方向,以使其满足他们的特定需求。

                    【讨论】:

                      【解决方案14】:

                      我也面临同样的问题。在路由中添加此代码后 -> web.php 问题已解决。

                         Route::get('/{vue_capture?}', function () {
                          return view('admin.dashboard');
                      })->where('vue_capture', '[\/\w\.-]*');
                      

                      将此路由重定向到您的父刀片视图。

                      【讨论】:

                        【解决方案15】:

                        正如@SERPRO 所解释的,Vuejs、Angular、Reactjs 等都是建立在单页应用程序 (SPA) 的概念之上的,所以我在 Apache 服务器上所做的只是告诉服务器加载 index.html原点之后的任何路径值。以下是对我有用的更改。 在我的虚拟主机文件上,我添加了一个简单的重写规则来始终加载 index.html 而不是重定向。

                        RewriteEngine On
                        RewriteRule "^/auth/account/confirm" "/index.html"
                        

                        因此,如果用户输入 http://my-origin/account/confirm,服务器将加载 index.html 并绑定 app.vue 文件,app.vue 文件路由器现在将选择路径帐户/确认并确定要渲染的适当组件

                        然后运行

                        apachectl restart
                        service httpd restart
                        

                        【讨论】:

                          【解决方案16】:

                          在我的例子中,404 错误不仅发生在页面重新加载时,还发生在使​​用浏览器的导航按钮时。
                          问题是路径中的特殊字符,如 äö 等。首先,路由与那些配合得很好,但是当使用浏览器导航按钮或在页面重新加载时,无法再找到该页面。在我用普通字母替换特殊字符后,路由再次起作用。
                          也许这对其他人有帮助。

                          【讨论】:

                            【解决方案17】:

                            就我而言,我使用 Vue 自己的配置来解决这个问题。这里的想法是利用pages 选项。所以在vue.config.js文件中,我们将添加如下代码示例:

                            module.exports = {
                              pages: {
                                // This is our main page which refers to the main Javascript file
                                index: "src/main.js", 
                                // Next, we list all other pages in the application, 
                                // and let all of them refer to the main Javascript file as well.
                                other_page: "src/main.js",
                              },
                            };
                            

                            通过这个实现,如果我们停留在other_page 并重新加载,应用程序仍然可以运行,而不会显示任何 404 错误。

                            【讨论】:

                              【解决方案18】:

                              只需将代码放在同一文件夹中的 .htaccess 文件中即可。无需重启或 Apache 重启。

                              RewriteEngine On
                              RewriteBase /
                              RewriteRule ^index\.html$ - [L]
                              RewriteCond %{REQUEST_FILENAME} !-f
                              RewriteCond %{REQUEST_FILENAME} !-d
                              RewriteRule . /index.html [L]
                              

                              【讨论】:

                                猜你喜欢
                                • 2018-12-03
                                • 2019-10-25
                                • 2019-02-19
                                • 2021-10-02
                                • 2020-10-05
                                • 2020-02-05
                                • 1970-01-01
                                • 1970-01-01
                                • 2021-06-05
                                相关资源
                                最近更新 更多