🖥? NodeJS专栏:Node.js从入门到精通 🖥? 博主的前端之路(源创征文一等奖作品):前端之行,任重道远(来自大三学长的万字自述) 🖥? TypeScript知识总结:TypeScript 学习笔记(十万字超详细知识点总结) 🧑?💼 个人简介:大三学生,一个不甘平庸的平凡人🍬 👉 你的一键三连是我更新的最大动力??! 🏆分享博主自用牛客网🏆:一个非常全面的面试刷题求职网站,点击跳转🍬
🔽 前言
前面我们已经讲过express 的路由和中间件,这一节我们将去介绍使用express 时怎么获取请求的参数,以及客户端渲染和服务端渲染的区别与作用,让我们开始吧!
1?? 获取请求参数
在讲解怎么获取请求参数之前,我们先定义好我们的API 接口路由:
const express = require("express");
const router = express.Router();
router.get("/list", (req, res) => {
console.log("参数为:", req.query);
res.send({ ok: req.query });
});
router.post("/list", (req, res) => {
console.log("参数为:",req.body);
res.send({ ok: req.body });
});
module.exports = router;
- 通过
req.query 获取URL 地址上的参数 - 通过
req.body 获取请求体中的参数
之后在服务器上挂载我们的API路由:
const express = require("express");
const apiRouter = require("./route/apiRouter");
const app = express();
app.use((req, res, next) => {
res.header({ "Access-Control-Allow-Origin": "*" });
next();
});
app.use(apiRouter);
app.listen(3000, () => {
console.log("服务器启动!");
});
启动服务器,然后我们创建一个html 文件用来调用测试我们的API 接口:
<body>
<button id="get">Get</button>
<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>
🔹 获取URL地址上的参数
先测试一下get 请求:
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 编码格式的参数:
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 格式的参数需要我们配置以下中间件:
app.use(express.urlencoded({ extended: false }));
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 格式的数据吗?
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' ,这个操作涉及到跨域被浏览器阻止了,我们只需要在服务端设置跨域时允许这个操作即可:
app.use((req, res, next) => {
res.header({ "Access-Control-Allow-Origin": "*" });
res.header({ "Access-Control-Allow-Headers": "Content-Type" });
next();
});
之后再进行测试会发现虽然不报错了,但服务端依旧无法获取到参数,这时像处理form 格式参数一样添加以下中间件即可:
app.use(express.json());
注意: 可以同时配置express.urlencoded 和express.json
2?? 应用渲染
🔹 客户端渲染
什么是客户端渲染?
客户端渲染(BSR) 又称 前端渲染,起源于JavaScript 的兴起,Ajax 网络请求技术的普及,真正意义上实现了前后端的分离,前端专注于UI ,后端专注于逻辑。
前端通过Ajax 请求获取服务端的数据,然后操作DOM 将数据动态渲染到页面,渲染页面数据的过程发生在前端也就是客户端,所以称其为客户端渲染。
简单理解就是,客户端渲染就是前端组装页面
下面这个前后端分离的例子就是构建了一个客户端渲染的页面:
<body>
<div class="main">
<h1>前后端分离形式:客户端渲染(前端调用ajax请求后端数据再动态渲染到页面上)</h1>
<ul class="list"></ul>
</div>
<script>
fetch('http://localhost:3000/list')
.then(res => res.json())
.then(res => {
render(res)
})
function render(data) {
let list = data.map(item => `<li>${item}</li>`)
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 服务器文件:
const express = require("express");
const app = express();
const Router = require("./route/router");
app.set("views", "./views");
app.set("view engine", "ejs");
app.use(Router);
app.listen(3000, () => {
console.log("服务器启动成功!");
});
route/router.js 路由文件:
const express = require("express");
const router = express.Router();
router.get("/serverList", (req, res) => {
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不迷路!
如果本篇文章对你有所帮助,还请客官一件四连!??
基础不牢,地动山摇! 快来和博主一起来牛客网刷题巩固基础知识吧!
|