Node.JS 学习笔记8

目录

express获取请求体数据

防盗链

路由模块化

模板引擎

EJS

ejs列表渲染

ejs条件渲染

在express中使用ejs


express获取请求体数据

express可以使用body-parser包处理请求体

**应用场景:**试想,如果前端需要编写一个登录页面,在该页面可以填写登录账号与密码信息,点击提交之后,发送POST请求,并把数据以请求体的形式传递给服务器端,服务器端对POST请求体中的内容进行验证,以返回登录成功或者失败。

实现步骤:

构建前端页面:(前端页面放在服务器静态资源路径下,当访问/login路由时,返回该写好的页面即可)

a.html

html 复制代码
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <div>
        <form action="http://127.0.0.1:3002/login"
         method="post">
         username: <input type="text" name="username"><br/>
         password: <input type="password" name="password"><br/>
         <button>login</button>
        </form>
    </div>
</body>

</html>

构建服务器端响应:(并非完整代码,只是中间测试代码)

javascript 复制代码
const express = require('express')
const app = express()

app.get('/login', (req, res) => {
    console.log('1')
    res.sendFile(__dirname + '/public/a.html')
})

app.post('/login', (req, res) => {
    res.send('获取并处理用户信息')
})

app.listen(3002,()=>{
    console.log('server start!')
})

提交表单时:(payload信息即为请求体)

在处理表单信息的步骤中,即需要使用body-parse来获取请求体信息

安装:

javascript 复制代码
npm i body-parser

导入:

javascript 复制代码
const bodyParser = require('body-parser')

使用中间件:

(路由中间件,在需要处理请求体的路由中添加中间件)

body-parser提供的中间件:

javascript 复制代码
//用于解析JSON格式请求体的中间件
const jsonParser = bodyParser.json()

//用于解析querystring格式请求体的中间件
const urlencodedParser = bodyParser.urlencoded({extended: false})

当中间件执行完毕时,会往req参数上添加一个body,body中包含了处理好的请求体数据。

本例中请求体是querystring形式的,因此使用下面的中间件,最终的完整代码:

javascript 复制代码
const express = require('express')
const app = express()

const bodyParser = require('body-parser')

//用于解析querystring格式请求体的中间件
const urlencodedParser = bodyParser.urlencoded({extended: false})

app.get('/login', (req, res) => {
    res.sendFile(__dirname + '/public/a.html')
})

app.post('/login',urlencodedParser, (req, res) => {
    if(req.body.username==='admin' && req.body.password==='123456'){
        res.send('login success')
    }else{
        res.send('login fail')
    }
})

app.listen(3002,()=>{
    console.log('server start!')
})

防盗链

思考这样一种情形,我们想把一个网络上的图片放到自己的项目里,如果直接在img标签的src属性中粘贴图片地址,有时候图片可以显示,有时候却是空白的。如果图片显示空白,说明该图片的网站使用了防盗链技术,也就是说,该网站阻止了其他网站对其资源的访问。

**原理:**在实现上,防盗链通过禁止该域名之外的其他域名访问本域名的资源来实现。

防盗链的访问不是只限制图片,通常包括域名下的所有资源。

使用express实现防盗链:

在前端和服务端发送HTTP请求时,HTTP请求的请求头部分,referer请求头中包含了发送当前请求URL的协议、域名、端口。

根据防盗链的原理,可以在服务器端对referer进行判断:如果是本域名,则返回请求的资源,如果不是,则返回404。

具体代码:

目录结构:

在index.js中,访问根目录返回public下的a.html,在a.html中,访问静态资源11.png。

a.html:

html 复制代码
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <div>
        <h2>静态资源</h2>
        <img src="/11.png">
    </div>
</body>
<script>



</script>

</html>

index.js:

javascript 复制代码
const express = require('express')
const app = express()

app.use((req, res, next)=>{
    console.log('----')
    //获取referer
    let referer = req.get('referer')

    if(referer){
        let url = new URL(referer)

        let hostname = url.hostname

        console.log(hostname)

        if(hostname !== '127.0.0.1'){
            console.log('1')
            res.status(404).send(`<h1>404 not found</h1>`)
            return 
        }
    }
    next()
})

app.use(express.static(__dirname + '/public'))

app.get('/', (req, res) => {
    console.log("2")
    res.sendFile(__dirname + '/public/a.html')
})


app.listen(3002,()=>{
    console.log('server start!')
})

访问127.0.0.1:

访问localhost:

路由模块化

在之前的笔记介绍的方法中,所有的路由都是放在index.js下的,但是,随着项目功能的增多,路由逻辑可能变得非常多,如果都写在index.js下,代码量会非常大,不便于阅读和维护。

可以采用模块化的思想来解决这个问题。

把路由进行拆分,放在不同的模块(js)文件中。

步骤:

在服务器项目下创建routes文件(也可以不是这个名字,但常规是这样)。

在routes下创建多个js文件,每个js文件对应一部分路由。

在每个js内部,创建router实例,router的用法和app是一样的,只是把语法中的app替换成router,最后暴露router:

(homePageRouter.js)

javascript 复制代码
const express = require('express')

const router = express.Router()

router.get('/home', (req, res)=>{
    res.send('home page')
})

router.get('/search',(req, res)=>{
    res.send('search page')
})

module.exports = router

在index.js中引入这个模块,然后使用app.use让其生效,在该模块中配置的路由即可生效:

(index.js)

javascript 复制代码
const express = require('express')
const app = express()

const homeRouter = require('./routers/homePageRouter')

app.use(homeRouter)

app.use(express.static(__dirname + '/public'))


app.listen(3002,()=>{
    console.log('server start!')
})

目录结构:

在对路由进行模块化之后,主模块的体积会变小,也便于维护和阅读。在多人开发时,也会降低冲突。

router可以看成是小型app对象。

模板引擎

模板引擎是分离用户界面和业务数据的一种技术。通俗来说,是分离HTML和JS的技术。

为什么需要分割HTML和JS?对于Node.js来说,JS指的是服务器端的JS,而不是浏览器端的JS,对于前端来说,HTML和JS当然可以是混合的,但是对于服务器端来说,有时候,服务器需要响应一个HTML数据,而HTML数据中可能包含一些JS语句。如果把该HTML和其中的JS单独写在一个静态资源里,一般是不能够正确获取JS数据的:

比如,当访问/home时,返回一个HTML,HTML有一个h2标签,标签内容是一个指定的字符串:

(index.js)

javascript 复制代码
const express = require('express')
const app = express()

let homestring = 'hello home :)'

app.use(express.static(__dirname + '/public'))

app.get('/home', (req, res) => {
    res.send(`<!DOCTYPE html>
        <html lang="en">

        <head>
            <meta charset="UTF-8">
            <meta name="viewport" content="width=device-width, initial-scale=1.0">
            <title>Document</title>
        </head>

        <body>
            <div>
                <h2>${homestring}</h2>
            </div>
        </body>
        <script>
            let homestring = 'hello world :)'


        </script>

        </html>`)

})

app.get('/test',(req, res)=>{
    res.sendFile(__dirname + '/public/a.html')
})

app.listen(3002, () => {
    console.log('server start!')
})

(a.html)

html 复制代码
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <div>
        <h2>{{homestring}}</h2>
        <h2>${homestring}</h2>

    </div>
</body>
<script>
    let homestring = 'hello world :)'


</script>

</html>

访问/home:

访问/test:

模板引擎在很多语言中都具有,并不是js独有的。随着前后端分离,该技术使用较少,但仍然需要了解。

EJS

EJS是一个高效的js模板引擎。

使用EJS实现上述例子的步骤如下:

1.安装

javascript 复制代码
npm i ejs

2.引入

javascript 复制代码
const ejs = require('ejs')

3.使用ejs渲染

javascript 复制代码
ejs.render('xxxx <%= params %>',{params: params})

,其中,render方法会对内部的字符串参数(第一个参数)进行解析,遇到<%= 变量名 %>的标识时,会把内部的变量名替换成第二个对象参数中变量名key对应的value。

使用ejs,可以完成如下效果:

index.js

javascript 复制代码
const ejs = require('ejs')
const fs = require('fs')

let username = 'mashiro'

const renderHtml = fs.readFileSync('./public/a.html').toString()

console.log(
    ejs.render(renderHtml, {username: username})
)

a.html

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <h2>hello, <%= username %></h2>
</body>
</html>

使用这种方式,可以实现html和js的分离:html在本例中是a.html文件,而js在index.js中,在渲染时,把需要渲染的js数据传入ejs.render即可,可以根据不同的情况渲染不同的数据。

ejs列表渲染

列表渲染:批量输出列表内容。

**需求:**在html中渲染ul标签,ul内部的li对应一个数组,数组中每个值对应一个li。

不使用ejs时,普通的实现方法

javascript 复制代码
const color = ['orange', 'blue', 'green', 'white']

let str = '<ul>'

color.forEach((item)=>{
    str += `<li>${item}</li>`
})

str += '</ul>'

但是此时html代码和js代码是耦合在一起的。

使用ejs实现

index.js

javascript 复制代码
const ejs = require('ejs')
const fs = require('fs')

const color = ['orange', 'blue', 'green', 'white']

const html = fs.readFileSync('./public/a.html').toString()

let resule = ejs.render(
    html,
    { color }
)

console.log(resule)

a.html

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <ul>
        <% color.forEach(item => { %>
        <li><%= item %></li>
        <% }) %>
    </ul>
</body>
</html>

在本例中,使用<% JS语法 %>,可以在<%与%>之间的部分编写JS语法。

也就是说,对于ejs来说,碰到<% %>格式,会把其中的内容作为JS语句解析。碰到<%= %>部分,会把其中的内容作为变量解析。

ejs条件渲染

**需求:**通过isLogin决定前端页面输出的内容,如果isLogin为true,则显示 欢迎!,如果为false,显示登录注册页面。

使用原生JS实现

javascript 复制代码
let isLogin = false

if(isLogin){
    console.log(`<span>欢迎!</span>`)
}else{
    console.log(`<button>登录</button>
                <button>注册</button>`)
}

使用ejs实现

index.js

javascript 复制代码
const ejs = require('ejs')
const fs = require('fs')

const html = fs.readFileSync('./public/a.html').toString()

let isLogin = false

let result = ejs.render(
    html,
    {isLogin}
)

console.log(result)

a.html

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <ul>
        <% if(isLogin){ %>
            <span>欢迎!</span>
        <% }else{ %>
            <button>登录</button>
            <button>注册</button>
        <% } %>
    </ul>
</body>
</html>

在express中使用ejs

index.js

javascript 复制代码
const express = require('express')
const path = require('path')

const app = express()

app.set('view engine', 'ejs')

app.set('views', path.resolve(__dirname,'./views'))

app.get('/home', (req, res)=>{
    res.render('a', {title:':)'})
})

app.listen(3002,()=>{
    console.log('server start!')
})

a.ejs

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <h2>hello, <%= title %></h2>
</body>
</html>
相关推荐
weixin_462446231 小时前
使用 Docker / Docker Compose 部署 PdfDing —— 个人 PDF笔记
笔记·docker·pdf
知识分享小能手1 小时前
Oracle 19c入门学习教程,从入门到精通,Oracle 数据表对象 —— 语法知识点详解与案例实践(10)
数据库·学习·oracle
炽烈小老头2 小时前
【每天学习一点算法 2026/01/22】杨辉三角
学习·算法
枷锁—sha2 小时前
【CTF笔记篇】SQL 注入总结
数据库·笔记·sql·安全·网络安全
狐572 小时前
2026-01-19-论文阅读-Agentic-Reasoning-for-Large-Language-Models
论文阅读·笔记
APIshop2 小时前
示例代码解析:使用 item_get_video_pro 获取小红书笔记详情
数据库·笔记
电饭叔2 小时前
勾股定理简单学习
学习
wypywyp2 小时前
3.win快捷键
笔记
菜菜小狗的学习笔记2 小时前
黑马程序员java web学习笔记--后端实战(六)登录认证--JWT令牌、Filter
笔记·学习