简体   繁体   English

ExpressJS: res.redirect() 不起作用。 如何在单页应用程序中重定向?

[英]ExpressJS: res.redirect() does not work. How to redirect in single page app?

Issue:问题:

I have a static single page application in which I press on a Submit input that sends a POST request using Axios from a Vue component to an Express server in which I handle the POST and try to redirect to another page, but res.redirect("/home") and/or res.sendFile(path.join(__dirname, "../dist/index.html"));我有一个 static 单页应用程序,在其中我按下提交输入,该输入使用 Axios 从 Vue 组件向 Express 服务器发送 POST 请求,在该服务器中我处理 POST 并尝试重定向到另一个页面,但是res.redirect("/home")和/或res.sendFile(path.join(__dirname, "../dist/index.html")); do not redirect.不要重定向。

Expected behaviour:预期行为:

I would like to redirect to /home after submit.我想在提交后重定向到/home Everything else works just fine.其他一切都很好。

Server File:服务器文件:

const history = require('connect-history-api-fallback');
const path = require("path");

// serve the Vue Interface
const buildLocation = path.join(__dirname, "../dist");
app.use(express.static(buildLocation));
app.use(history({
  disableDotRule: true,
  verbose: true
}));
app.use(express.static(buildLocation));

app.get('/home', function(req, res) {
  res.sendFile(path.join(__dirname, "../dist/index.html"));
});


app.post("/dhcpIP", function (req, res) {
  // check if request body is empty
  if (req.body.constructor === Object && Object.keys(req.body).length === 0)
    return;
  // doing things that work
  res.redirect('/'); // this doesn't work
});

const http_server = http.createServer(app);

http_server.listen(http_port);

I build the Vue CLI application so that I can obtain the dist folder.我构建了 Vue CLI 应用程序,以便获得dist文件夹。 In the dist folder I have an index.html that contains the whole application.dist文件夹中,我有一个index.html包含整个应用程序。

Vue component that sends the POST request:发送 POST 请求的 Vue 组件:

<template>
  <form action="javascript:void(0);" @submit="sendData" novalidate="true">
    <input type="text"/>
    <input type="password"/>
    <input type="submit"/>
  </form>
</template>

<script>
import axios from "axios";

const serverURL = location.origin;
const server = axios.create({ baseURL: serverURL });

export default {
  name: "DHCP",
  data() {
    return {
      visible: false,
      ssid: "",
      password: ""
    };
  },
  methods: {
    sendData: function() {
      if (this.ssid === "" || this.password === "") return;
      let currentUrl = window.location.pathname;
      console.log("currentUrl:");
      console.log(currentUrl);
      server
        .post(currentUrl, { ssid: this.ssid, password: this.password })
        .then(res => {
          console.log(res);
        })
        .catch(err => {
          console.log(err);
        });
    }
  }
};
</script>

Router File路由器文件

import Vue from "vue";
import VueRouter from "vue-router";
import Home from "../views/Home.vue";

Vue.use(VueRouter);

const routes = [
  {
    path: "/",
    redirect: "/home",
    component: Home,
  },
  {
    path: "/home",
    name: "Home",
    component: Home,
  },
  {
    path: "/dhcpIP",
    name: "DHCP",
    component: () => import(/* webpackChunkName: "dhcpIP" */ "../views/DHCP.vue")
  },
];

const router = new VueRouter({
  mode: "history",
  // base: process.env.BASE_URL,
  routes,
});

export default router;

I have tried writing as little code as possible.我尝试编写尽可能少的代码。

In your post route you are already returning something在您的发布路线中,您已经返回了一些东西

app.post("/dhcpIP", function (req, res) {
  // check if request body is empty
  if (req.body.constructor === Object && Object.keys(req.body).length === 0)
    return;
  // doing things that work
  res.redirect('/'); // this doesn't work
});

The return statement ends the function execution. return 语句结束 function 执行。 That being said: You are returning " some things that work " and after that you use the res.redirect method, which is ignored because the function has already returned a value .话虽这么说:您正在返回“一些有效的东西”,然后使用res.redirect方法,该方法被忽略,因为function 已经返回了 value

use router.push() instead, since you're not redirecting, but using the router改用router.push() ,因为您不是重定向,而是使用路由器

https://router.vuejs.org/guide/essentials/navigation.html https://router.vuejs.org/guide/essentials/navigation.html

if what you want to achieve is to move away from the SPA by the redirect, then you can change the window.location depending on the server response, in that case, send a 301 or 302 from the server, and add an axios interceptor for it.如果您想要通过重定向离开 SPA,那么您可以根据服务器响应更改 window.location,在这种情况下,从服务器发送 301 或 302,并添加 axios 拦截器它。

https://simplecheatsheet.com/axios-interceptors/ https://simplecheatsheet.com/axios-interceptors/

I have figured out the problem using this SO thread .我已经使用这个 SO 线程解决了问题。 Apparently, if you are doing an AXIOS post, you can't redirect from the Express server and you must handle the redirect in the AXIOS method.显然,如果您正在执行 AXIOS 帖子,则无法从 Express 服务器重定向,您必须在 AXIOS 方法中处理重定向。
I haven't found any explanation or documentation on this subject yet.我还没有找到关于这个主题的任何解释或文档。 When I do I will update this answer.当我这样做时,我会更新这个答案。

I did it like this:我是这样做的:

Server file:服务器文件:

app.post("/dhcpIP", function (req, res) {
  // check if request body is empty
  if (req.body.constructor === Object && Object.keys(req.body).length === 0)
    return;
  // doing things that work

  if(errors.length != 0) {
    res.sendStatus(500);
  } else
  res.sendStatus(200);
});

Vue component: Vue组件:

    sendData: function() {
      if (this.ssid === "" || this.password === "") return;
      let currentUrl = window.location.pathname;
      server
        .post(currentUrl, { ssid: this.ssid, password: this.password })
        .then(res => {
          if(res.status == 200) {
            alert("Settings have been saved.");
            window.location = currentUrl;
          } else {
            alert("Something went wrong. Please try again");
          }
        })
        .catch(err => {
          console.log(err);
        });
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM