当前位置: 首页 > news >正文

学习记录:DAY34

Nodejs 学习之旅:模块化与 Express 框架入门

前言


早起又失败了,我定了8点的闹钟啊,这闹钟怎么没声呢。简单给昨天的blog收个尾,今天继续学Nodejs。

日程


6.25

晚上6点,感觉没什么学习的动力,跳了一部分内容。目前进度来到了一半。

6.27

今天进行完成express剩下的部分。

学习内容


省流

  1. Nodejs 模块化
  2. express框架入门

1. Nodejs 模块化

模块化,也可以被认为是通俗的多文件设计。在Nodejs中,通过module.exports来暴露模块。

const doTest = () => {console.log('I do a Test');
}
// exports.doTest = doTest; //与module.exports的功能相同
module.exports = {doTest,
}

通过require导入模块:

const mode1 = require('./test')
console.log(mode1);
mode1.doTest();

注意:自定义模块需要写明是相对路径,如./test,而test不被允许,因为这是内部模块的写法。

默认可导入的文件是js和JSON,导入其他文件会作为js文件进行处理。也可以导入一个文件夹:

const mode2 = require('./testdir')
console.log(mode2);
mode2.doTest();

默认会导入文件夹中package.jsonmain指向的模块:

{"main": "test.js"
}

以下是更完整的寻找过程:

导入文件夹路径
是否存在 package.json?
是否有 main 字段?
D
加载 main 指定的文件
是否存在 index.js?
加载 index.js
是否存在 index.json?
加载 index.json
抛出错误: Cannot find module

2. express框架入门

基于nodejs的WEB应用开发框架。npmjs.com/package 查询关于依赖的api以及其他信息。

0)引入依赖

初始化npm包:

npm init

导入express 4包(目前最新是5,但是兼容性没有4好):

npm install express@4
1)入门程序
//导入express
const express = require('express')//创建应用对象
const app = express();//创建路由
app.get('/', (req, rep) => {rep.end('hello express');
})app.get('/*', (req, rep) => {rep.status(404).end('404 Not Found');
})//监听端口
app.listen(9000, () => {console.log('start')
})

路由是一个重要的概念,它确定了应用程序应该怎样响应请求。

2)参数获取

express支持大部分nodejs原生的http请求api,如:

console.log(req.method);
console.log(req.url);
console.log(req.httpVersion);
console.log(req.headers);

获取请求参数:

app.get('/', (req, res) => {console.log(req.path); //请求路径console.log(req.query); //请求参数console.log(req.body); //请求体console.log(req.get('host')); //请求头res.end();
})

获取请求体:
使用console.log(req.body)获取请求体时得到的是undefined,此时需要使用body-parser工具。

安装依赖:

npm i body-parser

导入模块:

const bodyParser = require('body-parser');

解析JSON:

const jsonParser = bodyParser.json()

解析queryString --对应 HTML 表单提交或 axios 发送 URL-encoded 数据:

const urlencodedParser = bodyParser.urlencoded({extended:false})

作为路由中间件使用:

app.post('/body',urlencodedParser,(req,res) =>{console.log('post');console.log(req.body);
})

获取路由参数 :id是一个占位符,可以匹配一个字符串,如test1234

app.get('/:id/html', (req, res) => {console.log(req.params.id)res.end();
})
3)响应设置
app.get('/', (req, res) => {res.status(203); //设置响应码res.set('test', 'header'); //响应头res.send('自动设置中文字符集'); //响应体
})

也可以写成链式编程的模式:

res.status(203).set('test', 'header').send('自动设置中文字符集');

重定向redirect:会将请求路径重定向。

app.get('/home', (req, res) => {res.redirect('/test')
});

也可以是一个外部连接:

app.get('/baidu', (req, res) => {res.redirect('http://baidu.com')
});

下载响应:触发浏览器的下载行为。

res.download(__dirname + '/test.txt');

JSON响应

res.json({name: 'heyi',age: 18
});

文件响应

res.sendFile(__dirname + '/test.txt');
4)中间件

本质是一个回调函数,在机制上类似于过滤器。

定义中间件:

const middleWare = (req, res, next) => {console.log('doing middleWare');next(); //放行
}

类似于一个函数,(req, res, next)是固定的参数,最后要通过next放行。

全局中间件:将函数交给app使用,任何路由的匹配都会触发。

app.use(middleWare);

路由中间件:作为指定路由的参数,匹配时触发。

app.get('/', middleWare, (req, res) => {res.end();
})

静态中间件:响应静态资源。

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

注意

  1. 默认打开index.html
  2. 会尝试匹配根路径,如果有匹配根路径的路由,谁先匹配谁响应(代码从上到下)。
5)防盗链

在图片等带连接的网页资源,在请求头中会带有referer:请求源的IP地址。

<body><h1>朋友你好</h1><img src="http://127.0.0.1:9000/66c6138a0385170fc1d0f42a33e7547b326268855.jpg" alt="">
</body>

可以设置全局中间件,对referer进行检查,来达到设置访问权限的效果。

app.use((req,res,next)=>{let referer = req.get('referer');if(referer){let url = new URL(referer);let hostname = url.hostname;if(hostname !== '127.0.0.1'){res.send(`<h1>你不是我指定的访问源<h1>`)return;} }next();
})
6)模板引擎

模板引擎用于分离用户界面和业务数据,EJS是其中一种。

安装EJS:

npm i ejs

简单示例:

const ejs = require('ejs');
let data = '测试数据';
let result = ejs.render('我是<%= data %>',{data:data});

在EJS模块中,<% %>标签内的代码会被视为Js代码执行(它支持完全的JS语法)。

  • <%= %>输出转义后的值
  • <%- %>输出原始的HTML
  • <%# %>注释
  • <%%输出字面量'<%'

示例:if-else语法

let isLogin = true;
console.log(ejs.render(`<% if(isLogin){ %><span>已经登录</span><% }else{ %><span>你需要登录</span><% }%>  `,{isLogin:isLogin})
)

ejs也可以使用外部导入的html文件:

const fs = require('fs');
let arr = [1,2,3,4,5,6,7,8]
let html = fs.readFileSync(__dirname+'/6-test.html').toString();console.log(ejs.render(html,{arr:arr})
)

6-test.html

<!DOCTYPE html>
.....
<body><ul><% arr.forEach(item=>{ %><li><%= item %></li><% })%></ul>
</body>
</html>

本质是使用了String格式html,与直接使用没有太大区别。

ejs也支持在express中使用:

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)=>{let title = '测试标题';//模板文件名,数据res.render('test',{title});
});app.listen(9000,()=>{
})
7)express-generator

express的应用生成工具,用于快速生成应用模板。

全局安装:

npm i -g express-generator

初始化npm包:

npm init

创建模板,并添加对ejs的支持:

express -e

启动命令:

npm run start
8)文件上传处理

upload.ejs

<!DOCTYPE html>
<html lang="en">
......
<body><form action="/upload" method="post" enctype="multipart/form-data">用户名:<input type="text" name="username"><br/>头像:<input type="file" name="uploadedfile"><button>提交</button></form>
</body>
</html>

注意要将设置enctype为多文件数据。

这里使用了formidable工具进行文件处理:

npm i formidable

upload.js

const express = require('express');
const router = express.Router();router.get('/',(req,res)=>{res.render('upload');
})//处理文件上传
const {formidable} = require('formidable');
router.post('/',(req,res,next)=>{const form = formidable({multiples: true,//保存目录uploadDir:__dirname+'./../public/images',//保持文件后缀keepExtensions: true})//解析请求报文form.parse(req,(err,fields,files)=>{if(err) {next(err);return;}console.log(fields);console.log(files);//保存urllet url = '/images/' + files.uploadedfile[0].newFilename;console.log(url)res.send(url); })
})module.exports = router;

结语


6.27结的尾,又躺了两天🫥

http://www.lqws.cn/news/540181.html

相关文章:

  • 树的重心(双dfs,换根)
  • 目标跟踪存在问题以及解决方案
  • 算法第54天| 并查集
  • 【Redis】解码Redis中的list类型,基本命令,内部编码方式以及适用的场景
  • 分布式ID生成SnowflakeId雪花算法和百度UidGenerator工具类
  • 深入解析:Vue 中的 Render 函数、JSX 与 @vitejs/plugin-vue-jsx 实践指南
  • DeepSeek 部署中的常见问题及解决方案:从环境配置到性能优化的全流程指南
  • Merkle Tree原理与Python实现
  • RabbitMQ RPC模式Python示例
  • 【RabbitMQ】基于Spring Boot + RabbitMQ 完成应用通信
  • Idea中Docker打包流程记录
  • C++11 <chrono> 库特性:从入门到精通
  • 线程与协程的比较
  • 【机器学习与数据挖掘实战 | 医疗】案例18:基于Apriori算法的中医证型关联规则分析
  • 《表白模版之聊天记录,前端js,html学习》
  • 2025暑期学习计划​参考
  • CPT204-Advanced OO Programming: Lists, Stacks, Queues, and Priority Queues
  • 026 在线文档管理系统技术架构解析:基于 Spring Boot 的企业级文档管理平台
  • Moxa 加入 The Open Group 的开放流程自动化™论坛,推动以开放、中立标准强化工业自动化
  • AI优化SEO关键词精进
  • 工作台-01.需求分析与设计
  • Django ORM 1. 创建模型(Model)
  • 安全运营中的漏洞管理和相关KPI
  • 桌面小屏幕实战课程:DesktopScreen 13 HTTP SERVER
  • PHP Protobuf 手写生成器,
  • BERT架构详解
  • 智能温差发电杯(项目计划书)
  • LinuxBridge的作用与发展历程:从基础桥接到云原生网络基石
  • AIOps与人工智能的融合:从智能运维到自适应IT生态的革命
  • 【Linux指南】压缩、网络传输与系统工具