IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> JavaScript知识库 -> Node.js | express 获取请求参数 | 客户端渲染 | 服务端渲染 -> 正文阅读

[JavaScript知识库]Node.js | express 获取请求参数 | 客户端渲染 | 服务端渲染

在这里插入图片描述


🖥? NodeJS专栏:Node.js从入门到精通
🖥? 博主的前端之路(源创征文一等奖作品):前端之行,任重道远(来自大三学长的万字自述)
🖥? TypeScript知识总结:TypeScript 学习笔记(十万字超详细知识点总结)
🧑?💼 个人简介:大三学生,一个不甘平庸的平凡人🍬
👉 你的一键三连是我更新的最大动力??!
🏆分享博主自用牛客网🏆:一个非常全面的面试刷题求职网站,点击跳转🍬



🔽 前言

前面我们已经讲过express的路由和中间件,这一节我们将去介绍使用express时怎么获取请求的参数,以及客户端渲染服务端渲染的区别与作用,让我们开始吧!

1?? 获取请求参数

在讲解怎么获取请求参数之前,我们先定义好我们的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接口:

<!-- index.html -->
<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请求:

// 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-Typeapplication/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.urlencodedexpress.json

2?? 应用渲染

🔹 客户端渲染

什么是客户端渲染?

客户端渲染(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 => `<li>${item}</li>`)
            console.log(list);
            // 渲染数据到页面
            document.querySelector('.list').innerHTML = list.join('')
        }
    </script>
</body>

打开页面并尝试在浏览器查看网页源代码:

在这里插入图片描述

可以看到我们动态渲染的数据在浏览器上查看源代码时是看不到的,这就是客户端渲染最大的问题:不利于SEO!

SEO,全称Search Engine Optimization,也即搜索引擎优化。

因为我们使用客户端渲染时,动态渲染到页面上的数据浏览器是看不到的,所以这些动态数据就不可能被网络爬虫爬取到,又因为像百度这类搜索引擎本质就是通过爬虫来爬取网页信息来实现的,所以客户端渲染就会对搜索引擎不太友好。

客户端渲染的优缺点都非常明显,优点:

  • 完全的前后端分离。
  • 数据渲染发生在客户端,能减轻服务端(服务器)的压力。

缺点:

  • 不利于SEO
  • 请求量大时首屏渲染较慢(白屏问题)(因为前端需要时间去将数据绑定到页面上)。

🔹 服务端渲染

与客户端渲染对比来说,服务端渲染(SSR) 就很好理解了:

服务端渲染就是由后端(服务端)渲染数据,之后就直接将渲染数据后的页面发送给前端(客户端),前端只需进行展示即可。

简单理解就是,服务端渲染就是后端组装页面

后端渲染数据时常常是需要提前有一个页面模板的,当后端获取到需要展示的数据后,将数据填充到这个页面模板中,之后将填充过数据的模板页面给前端进行展示,这个模板称为模板引擎,下面是使用 ejs模板引擎 来演示服务端渲染的例子:

serverList.ejs模板:

<!-- views/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
  • 首屏渲染速度快(因为数据绑定到页面的过程在服务端已经完成,前端渲染时相当于是直接渲染了个静态页面)。

缺点:

  • 渲染数据过多时服务端的压力就会很大。
  • 前后端不能完全分离。

🔹 怎样选择?

服务端渲染和客户端渲染的优缺点正好相反,但其实这两者并不是完全独立的,在一些应用开发中可能会同时使用服务端渲染和客户端渲染, 并不是说一个项目就只能是服务端渲染或客户端渲染,我们可以根据项目中不同页面的需求去自由选择/搭配这两种方式。

VueReact等前端框架(SPA应用)默认也都是客户端渲染,但它们都有支持服务端渲染的上层框架(Nuxt.jsNext.js

🔼 结语

博主的Node.js从入门到精通专栏正在持续更新中,关注博主订阅专栏学习Node不迷路!

如果本篇文章对你有所帮助,还请客官一件四连!??

在这里插入图片描述

基础不牢,地动山摇! 快来和博主一起来牛客网刷题巩固基础知识吧!

  JavaScript知识库 最新文章
ES6的相关知识点
react 函数式组件 & react其他一些总结
Vue基础超详细
前端JS也可以连点成线(Vue中运用 AntVG6)
Vue事件处理的基本使用
Vue后台项目的记录 (一)
前后端分离vue跨域,devServer配置proxy代理
TypeScript
初识vuex
vue项目安装包指令收集
上一篇文章      下一篇文章      查看所有文章
加:2022-10-22 21:06:34  更:2022-10-22 21:08:57 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/17 17:04:12-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码