️ NodeJS专栏:Node.js从入门到精通
️ 博主的前端之路(源创征文一等奖作品):前端之行,任重道远(来自大三学长的万字自述)
️ TypeScript知识总结:TypeScript 学习笔记(十万字超详细知识点总结)
个人简介:大三学生,一个不甘平庸的平凡人
你的一键三连是我更新的最大动力❤️!
分享博主自用牛客网:一个非常全面的面试刷题求职网站,点击跳转
前面我们已经讲过express
的路由和中间件,这一节我们将去介绍使用express
时怎么获取请求的参数,以及客户端渲染和服务端渲染的区别与作用,让我们开始吧!
在讲解怎么获取请求参数之前,我们先定义好我们的API
接口路由:
// apiRouter.js
const express = require("express");
// 使用路由级别中间件
const router = express.Router();
// 响应前端的get请求
router.get("/list", (req, res) => {
// 通过req.query获取URL地址上的参数(例如Get请求的参数)
console.log("参数为:", req.query);
res.send({ ok: req.query });
});
// 响应前端的post请求
router.post("/list", (req, res) => {
// 通过req.body获取请求体中的参数(例如post/put请求的参数)
console.log("参数为:",req.body);
res.send({ ok: req.body });
});
// 导出
module.exports = router;
req.query
获取URL
地址上的参数req.body
获取请求体中的参数之后在服务器上挂载我们的API路由:
// server.js
const express = require("express");
// 导入API路由文件
const apiRouter = require("./route/apiRouter");
const app = express();
// 配置跨域
app.use((req, res, next) => {
// 设置允许任何源能访问服务器
res.header({ "Access-Control-Allow-Origin": "*" });
next();
});
// 挂载api路由
app.use(apiRouter);
app.listen(3000, () => {
console.log("服务器启动!");
});
启动服务器,然后我们创建一个html
文件用来调用测试我们的API
接口:
<body>
<button id="get">Getbutton>
<button id="postF">Post:form编码参数button>
<button id="postJ">Post:JSON参数button>
<script>
const get = document.getElementById('get')
const postF = document.getElementById('postF')
const postJ = document.getElementById('postJ')
get.onclick = () => {
}
postF.onclick = () => {
}
postJ.onclick = () => {
}
script>
body>
先测试一下get
请求:
// index.html
get.onclick = () => {
fetch('http://localhost:3000/list?username=ailjx&age=18')
.then(res => res.json())
.then(res => {
console.log(res);
})
}
可以看到我们服务端直接使用req.query
就能获取URL地址上的参数,不需要做额外的处理。
调用 http://localhost:3000/list?a=1&b=2 时 req.query 为:{ a: ‘1’, b: ‘2’ }
先来试一下form
编码格式的参数:
// index.html
postF.onclick = () => {
fetch('http://localhost:3000/list', {
method: 'POST',
body: 'username=ailjx&age=18',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
})
.then(res => res.json())
.then(res => {
console.log(res);
})
}
form
编码格式对应的Content-Type
为application/x-www-form-urlencoded
,是html
form
表单的默认提交方式,其参数格式与URL
参数类似:'username=ailjx&age=18'
可以看到服务端并不能直接通过req.body
来获取请求体中的参数,想要获取请求体中form
格式的参数需要我们配置以下中间件:
// server.js
app.use(express.urlencoded({ extended: false }));
// 或app.use(express.urlencoded({ extended: true }));
urlencoded
方法解析form
编码格式的参数(Content-Type: application/x-www-form-urlencoded
),如:username=ailjx&age=18
urlencoded
中如果extended
设置为false
,那么对URL-encoded
的数据的解析采用querystring
库,解析结果为:[Object: null prototype] { username: 'ailjx', age: '18' }
urlencoded
中如果extended
设置为true
,那么采用qs
库,允许将富对象和数组编码为url
编码格式,允许使用url
编码的json
体验,解析结果为:{ username: 'ailjx', age: '18' }
上面两种解析结果都能直接通过req.body.username
来访问参数中具体的字段。
在post
这类请求中,往往传递的都是JSON
格式的数据,那我们的服务端能直接获取JSON
格式的数据吗?
// index.html
postJ.onclick = () => {
fetch('http://localhost:3000/list', {
method: 'POST',
body: JSON.stringify({
username: 'ailjx',
age: '18'
}),
headers: {
'Content-Type': 'application/json'
}
})
.then(res => res.json())
.then(res => {
console.log(res);
})
}
当我们点击按钮发送请求时报了这样的错误:
Request header field content-type is not allowed by Access-Control-Allow-Headers in preflight response.
译:预检前响应中的访问控制允许标头不允许请求标头字段内容类型。
这主要是因为我们前端发请求时修改了请求头的'Content-Type'
为'application/json'
,这个操作涉及到跨域被浏览器阻止了,我们只需要在服务端设置跨域时允许这个操作即可:
// server.js
// 配置跨域
app.use((req, res, next) => {
// 设置允许任何源能访问服务器
res.header({ "Access-Control-Allow-Origin": "*" });
// 设置访问控制允许标头,允许自定义header的Content-Type字段
res.header({ "Access-Control-Allow-Headers": "Content-Type" }); // 新增
next();
});
之后再进行测试会发现虽然不报错了,但服务端依旧无法获取到参数,这时像处理form
格式参数一样添加以下中间件即可:
// server.js
// json方法解析json编码格式的post参数(Content-Type: application/json),如:{"username": "ailjx","age": "18"}
app.use(express.json());
注意: 可以同时配置express.urlencoded
和express.json
什么是客户端渲染?
客户端渲染(BSR) 又称 前端渲染,起源于JavaScript
的兴起,Ajax
网络请求技术的普及,真正意义上实现了前后端的分离,前端专注于UI
,后端专注于逻辑。
前端通过Ajax
请求获取服务端的数据,然后操作DOM
将数据动态渲染到页面,渲染页面数据的过程发生在前端也就是客户端,所以称其为客户端渲染。
简单理解就是,客户端渲染就是前端组装页面
下面这个前后端分离的例子就是构建了一个客户端渲染的页面:
<body>
<div class="main">
<h1>前后端分离形式:客户端渲染(前端调用ajax请求后端数据再动态渲染到页面上)h1>
<ul class="list">ul>
div>
<script>
// 发送Ajax请求向后端获取数据
// http://localhost:3000/list返回的数据是[1, 2, 3, 4, 5, 6, 7, 8, 9]
fetch('http://localhost:3000/list')
.then(res => res.json())
.then(res => {
render(res)
})
function render(data) {
let list = data.map(item => `${item}`)
console.log(list);
// 渲染数据到页面
document.querySelector('.list').innerHTML = list.join('')
}
script>
body>
打开页面并尝试在浏览器查看网页源代码:
可以看到我们动态渲染的数据在浏览器上查看源代码时是看不到的,这就是客户端渲染最大的问题:不利于SEO!
SEO,全称Search Engine Optimization,也即搜索引擎优化。
因为我们使用客户端渲染时,动态渲染到页面上的数据浏览器是看不到的,所以这些动态数据就不可能被网络爬虫爬取到,又因为像百度这类搜索引擎本质就是通过爬虫来爬取网页信息来实现的,所以客户端渲染就会对搜索引擎不太友好。
客户端渲染的优缺点都非常明显,优点:
缺点:
SEO
。与客户端渲染对比来说,服务端渲染(SSR) 就很好理解了:
服务端渲染就是由后端(服务端)渲染数据,之后就直接将渲染数据后的页面发送给前端(客户端),前端只需进行展示即可。
简单理解就是,服务端渲染就是后端组装页面
后端渲染数据时常常是需要提前有一个页面模板的,当后端获取到需要展示的数据后,将数据填充到这个页面模板中,之后将填充过数据的模板页面给前端进行展示,这个模板称为模板引擎,下面是使用 ejs
模板引擎 来演示服务端渲染的例子:
serverList.ejs
模板:
<body>
<div class="main">
<h1>使用模板引擎:服务端渲染(后端将数据与模板结合后再将结合过的页面返回给前端)h1>
<ul class="list">
<% data.forEach(function(item){ %>
<li>
<%-item %>
li>
<% }); %>
ul>
div>
body>
ejs
模板文件是以.ejs
为后缀的文件,它完全兼容.html
文件(就是能写任何HTML
内容),并在此基础上添加了一些额外的ejs语法,如上面的<%%>
中能写流程控制代码(JS
代码),<%- %>
中能写需要输出到模板的数据。关于ejs
,博主之后会出单独的文章进行讲解,敬请期待!
server.js
服务器文件:
// server.js
const express = require("express");
const app = express();
// 导入路由
const Router = require("./route/router");
// npm i ejs下载ejs
// 配置模板引擎
app.set("views", "./views"); // 指定模板目录路径 (第一个参数views是固定写法)
app.set("view engine", "ejs"); // 指定模板后缀 (view engine是固定写法)
// 挂载路由
app.use(Router);
app.listen(3000, () => {
console.log("服务器启动成功!");
});
route/router.js
路由文件:
// route/router.js
const express = require("express");
const router = express.Router();
// 路由级别中间件
// 服务端渲染页面
router.get("/serverList", (req, res) => {
// 使用render渲染serverList模板后返回给前端
// res.send:能传递json数据和html页面
// res.json:只能传递json数据
// res.render:渲染模板
// 第一个参数:找到views下的serverList.ejs
// 第二个参数:需要传递给模板的数据
res.render("serverList", { data: [1, 2, 3, 4, 5, 6, 7, 8, 9] });
});
// 导出
module.exports = router;
启动服务器,打开http://localhost:3000/serverList
查看效果:
可以看到这时我们动态渲染到页面的数据在浏览器检查源代码时就能检查的到了,这就是服务端渲染的最大好处:有利于SEO!
但服务端渲染的优缺点也很明显,优点:
SEO
。缺点:
服务端渲染和客户端渲染的优缺点正好相反,但其实这两者并不是完全独立的,在一些应用开发中可能会同时使用服务端渲染和客户端渲染, 并不是说一个项目就只能是服务端渲染或客户端渲染,我们可以根据项目中不同页面的需求去自由选择/搭配这两种方式。
像
Vue
,React
等前端框架(SPA应用
)默认也都是客户端渲染,但它们都有支持服务端渲染的上层框架(Nuxt.js
和Next.js
)
博主的Node.js从入门到精通专栏正在持续更新中,关注博主订阅专栏学习Node不迷路!
如果本篇文章对你有所帮助,还请客官一件四连!❤️
基础不牢,地动山摇! 快来和博主一起来牛客网刷题巩固基础知识吧!