结合客户端 jQuery 和服务器端 Express

Posted

技术标签:

【中文标题】结合客户端 jQuery 和服务器端 Express【英文标题】:Combining client-side jQuery and server - side Express 【发布时间】:2021-07-30 18:35:03 【问题描述】:

我正在学习 Express / Node。我正在尝试构建一个简单的 html form 来验证客户端(例如,使用 jQuery / AJAX),但我也从服务器端(使用 Express.js)提供服务。需要明确的是,该应用程序现在非常简单,我可以在客户端做所有事情,但我想构建服务器端行为来学习整个管道。

这是表格。注意button 类型为button 的名称为change-color;这是我用于调试目的的button,稍后解释。我还包括jquery v.3.6.0 和我自己的client.js 文件。

<!DOCTYPE html>
<html lang="en" dir="ltr">
  <head>
    <meta charset="utf-8">
    <title>A MWE</title>
    <link rel="stylesheet" href="styles.css">
  </head>
  <body>
    <h1>A simple form.</h1>
    <form action="/" method="post">
      <input type="text" name="num1" placeholder = "First Number" value=""> <br>
      <input type="text" name="num2" placeholder = "Second Number" value=""> <br>
      <button type="submit" name="submit">Calculate</button>
      <button type="button" name="change-color">Change color</button>
    </form>

    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
    <script src="client.js" charset="utf-8"></script>
  </body>
</html>

在表单中,用户应该给我两个数字,然后服务器将求和并返回。服务器代码位于名为 server.js 的文件中,概述如下:

const express = require("express");
const bodyParser = require("body-parser");
const app = express();
app.use(bodyParser.urlencoded(extended:true));

app.listen(3000, () => 
  console.log("Server spun on port 3000.");
);

app.get("/", (req, res) => 
  console.log("Serving a GET request at root route.");
  res.sendFile(absoluteDirPath() + "index.html");
);

app.post("/", (req, res) => 
  console.log("Serving a POST request at root route.");
  const num1 = Number(req.body.num1);
  const num2 = Number(req.body.num2);
  res.send("<h3>Result: " + (num1 + num2) + "</h3>");
);

function absoluteDirPath() 
  const path = require('path');
  return __dirname + path.sep;

当我们第一次访问根端点(GET 调用)时,服务器使用res.sendFile() 将上述 HTML 文件发送给用户。当用户在form 上输入两个数字并单击form 内的submit 类型的button 时,server.js 方法的app.post() 计算和send()s 请求的总和。

显然我需要在应用总和之前进行一些验证;如果我没有得到号码怎么办?根据对this post 的回答,为避免复杂和突然的重定向,我似乎必须在客户端执行此操作,例如在单独的.js 文件中。在同一篇文章中,有人建议我编写类似以下函数的内容并将其分配给事件侦听器:

function submitFormWithoutReloading() 
   $.ajax(
      type: "POST",
      url: "/",
      data: 
         num1: $('#idOfYourFirstInput').val(),
         num2: $('#idOfYourSecondInput').val()
      ,
      success: function(res) 
         alert(res); // This is what the server returns
      
   );

但是,我似乎在这里偶然发现了一个更大的问题。当我使用app.get() 方法中的 HTML 文件为用户提供服务时,我在运行所有 jQuery 时遇到了一些问题!好像每次我访问http://localhost:3000/ 时,HTML 文件都会发送给我,但链接的client.js 文件没有被读取(我猜同样的事情也适用于 jQuery)。

为了确保这是我的问题,我暂时忘记了验证例程,制作了上面提到的change-color HTML button 并在client.js 中添加了一些虚拟代码:

$(document).ready(function() 
  alert("Hi!");
);

$('button[name="change-color"]').click(function() 
  $("body").toggleClass("colored-background");
);

因此,change-color 按钮仅用于切换 body 元素以根据此 CSS 规则将 yellow 作为其背景:

.colored-background 
  background-color: yellow;

如果我从我的文件系统打开index.html,一切正常; jQuery 和我的 client.js 文件已加载,alert() 很好,按钮按预期工作。但是当我访问localhost:3000 并且GET 端点为客户端提供HTML 文件时,就好像DOM 扫描没有读取client.js 并且我不能做任何客户端的事情,包括我非常想要的验证!

对我做错了什么有任何想法吗?我知道我可以在这里在客户端做一切,但我想学习如何在客户端和服务器端拆分关注点。服务器端可能要访问数据库,客户端不能做任何事情。

// 编辑:如果有帮助,Chrome 控制台会在我加载 localhost:3000 时说一些有趣的事情:

【问题讨论】:

【参考方案1】:

你没有做错任何事。这只是使用 node.js 的每个人的常见问题(包括我!Cant access other files in Node.js)。

您必须告诉 express 客户端可以查看哪些文件。让我们创建一个名为public 的文件夹。在您的文件夹中,放置您的 .js.css 文件,以及您希望客户端访问的其他图片或其他资产。

您网站上的这个公共文件夹将替换为您的域。考虑这些文件/文件夹:

index.js (server)
/ views
   - index.html
/ public
   - style.css
   - client.js
   - jquery.min.js

客户端只能访问public内的文件,例如:http://localhost:3000/style.css,或http://localhost:3000/client.js,或http://localhost:3000/jquery.min.js。但是,我们将无法访问其他文件(不在公共文件夹中),除非服务器明确获取它:

app.get('/index.html', function(req, res) 
   res.sendFile(path.join(__dirname, '/views/index.html'));
);

解决方案:

// ...
const path = require('path');
const app = express();
app.use(express.static(path.join(__dirname, '/public')));
// You routes here

这样,客户端就可以访问public目录下的所有文件。你的问题应该已经解决了。

记住:服务器仍然可以访问所有文件。这只会限制客户端。

【讨论】:

哈,是的,我实际上得到了一位朋友的相同解决方案,我回来回答我自己的问题,但最好给别人加分。这工作正常,现在我在一种语言中实现了客户端和服务器端的关注点分离,就像宣传的那样。谢谢! 耶!我很高兴你解决了你的问题。我很乐意帮助您解决其他问题(我可以回答)

以上是关于结合客户端 jQuery 和服务器端 Express的主要内容,如果未能解决你的问题,请参考以下文章

如何在github上将客户端和服务器端项目文件夹作为一个项目(api +前端)一起推送?

node.js学习目录

如何在逻辑上结合 react-router 和 redux 进行客户端和服务器端渲染

将服务器端和客户端身份验证与 WebAPI 相结合

使用bootstrap-table的客户端分页(结合ajax)和服务端分页渲染表格

如何同时使用 jquery 和服务器端验证客户端?