46

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

以下是我的Vue路由器配置

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

19 回答 19

52

我认为您错过了 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>

希望它可以帮助某人!

于 2017-08-20T02:47:16.547 回答
49

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

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

于 2016-04-04T10:04:08.897 回答
9

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

阿帕奇

<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;
}

就这样

欲了解更多信息,请访问此链接

于 2020-12-06T00:40:10.830 回答
8

如果您具有 root 访问权限,则更好(在 Ubuntu 上)是 modify /etc/apache2/apache2.conf,因为即使 Apache 自己也不鼓励.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 创建的路由重定向回/,而且实际上将网站刷新到相同的路由,因此刷新后您仍然处于相同的视图中。

于 2020-02-04T15:13:42.177 回答
7

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

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

vue 中默认提供哈希模式,因此即使您留空而不是mode: 'hash'.

于 2019-05-27T09:12:15.150 回答
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

于 2017-10-30T19:16:00.460 回答
2

如果即使在尝试上述解决方案后任何一个都面临问题,请查找以下方法。如果你有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"],
};
于 2020-08-01T15:36:38.827 回答
1

对于使用 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)
})

两者都是文档中的建议。

于 2018-07-04T04:05:28.870 回答
1

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

/*    /index.html   200

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

于 2019-10-13T23:06:19.510 回答
1

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

于 2020-11-20T09:55:24.243 回答
1

就我而言,我是通过虚拟主机处理的:

阿帕奇

转到并使用您的域名/etc/apache2/sites-available进行克隆,即打开它,然后将其放在下面的代码段:000-default.confapp.abc.com.confsudo nano app.abc.com.conf

Vue 文档参考: 点击这里
StackOverflow 参考: 点击这里
<VirtualHost *:80>

ServerName app.abc.com
DocumentRoot /var/www/html/project_name/dist/

ErrorLog ${APACHE_LOG_DIR}/app.abc.com.error.log
CustomLog ${APACHE_LOG_DIR}/app.abc.com.access.log combined

  <Directory /var/www/html/project_name/dist>
        FallbackResource /index.html  
  </Directory>

</VirtualHost>
Niginx Vue Cli (SPA) 虚拟主机:
Vue 文档参考: 点击这里
server {
        listen 80;
        root /var/www/html/project_name/dist;
        server_name app.abc.com;
        index index.html index.htm index.php;
        location / {
             try_files $uri $uri/ /index.html;
        }
}

注意: 在ubuntu服务器上测试

于 2022-02-16T15:22:02.663 回答
0

其他人面临同样的问题,我刚刚意识到

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

这是不同的

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

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

于 2019-02-16T08:53:36.427 回答
0

我正在使用带有 .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" });

        });
于 2019-07-26T17:55:38.730 回答
0

来晚了,但是......

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

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

  2. 为根 vue 元素添加一个属性

    <div id="content" redirect_to="{{redirect_to}}"></div>

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

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

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

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

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

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

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

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

于 2020-01-21T07:12:13.367 回答
0

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

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

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

于 2021-07-29T08:01:03.097 回答
0

正如@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 文件路由器现在将选择路径 account/确认并确定要渲染的适当组件

然后运行

apachectl restart
service httpd restart
于 2021-09-27T09:50:01.597 回答
0

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

于 2021-10-18T22:23:41.173 回答
0

就我而言,我使用 Vue 自己的配置来解决这个问题。这里的想法是利用页面选项。因此,在文件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 错误。

于 2021-11-22T15:17:16.553 回答
0

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

RewriteEngine On
RewriteBase /
RewriteRule ^index\.html$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.html [L]
于 2021-11-26T12:43:40.080 回答