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

Node18.x基础使用总结(二)

Node18.x基础使用总结

  • 1、Node.js模块化
    • 1.1、模块暴露数据
    • 1.2、引入模块
  • 2、包管理工具
    • 2.1、npm
    • 2.2、npm的安装
    • 2.3、npm基本使用
    • 2.4、搜索包
    • 2.5、下载安装包
    • 2.6、生产环境与开发环境
    • 2.7、生产依赖与开发依赖
    • 2.8、全局安装
    • 2.9、修改windows执行策略
    • 2.10、安装包依赖
    • 2.11、安装指定版本的包
    • 2.12、删除依赖
    • 2.13、配置命令别名
  • 3、cnpm
    • 3.1、安装cnpm
    • 3.2、操作命令
    • 3.2、npm配置淘宝镜像
      • 3.2.1、直接配置
      • 3.2.2、工具配置
  • 4、yarn
    • 4.1、yarn安装
    • 4.2、yarn常用命令
    • 4.3、yarn配置淘宝镜像
    • 4.4、npm 和 yarn 选择
  • 5、nvm
    • 5.1、下载安装
    • 5.2、常用命令
  • 6、Express框架
    • 6.1、下载使用
    • 6.2、express路由
    • 6.3、获取请求参数
    • 6.4、获取路由参数
    • 6.5、express响应设置
    • 6.6、express中间件
      • 6.6.1、定义全局中间件
      • 6.6.2、定义路由中间件
      • 6.6.3、静态资源中间件
    • 6.7、获取请求体
    • 6.8、Router
    • 6.9、模板引擎EJS
      • 6.9.1、分离用法
    • 6.10、express-generator
      • 6.10.1、补充知识

配套视频: 尚硅谷2023版Node.js零基础视频教程,nodejs新手到高手
配套代码: https://gitee.com/Augenstern-creator/kuang-study-nodejs
在这里插入图片描述

1、Node.js模块化

1.1、模块暴露数据

  1. 创建 me.js
//声明函数
function tiemo(){
console.log('贴膜....');
}
//暴露数据
module.exports = tiemo;
  1. 创建 index.js
//导入模块
const tiemo = require('./me.js');//调用函数
tiemo();

模块暴露数据的方式有两种:

  1. module.exports = value
  2. exports.name = value

使用时有几点注意:

  • module.exports 可以暴露任意数据

1.2、引入模块

在模块中使用 require 传入文件路径即可引入文件

//导入模块
const tiemo = require('./me.js');

require 使用的一些注意事项:

  1. 对于自己创建的模块,导入时路径建议写相对路径,且不能省略./../

  2. 导入 node.js 内置模块时,直接 require 模块的名字即可,无需加 ./../

  3. jsjson 文件导入时可以不用写后缀

  4. 如果导入其他类型的文件,会以 js文件进行处理

  5. 如果导入的路径是个文件夹,则会首先检测该文件夹下 package.json 文件中 main 属性对应的文件,如果存在则导入,反之如果文件不存在会报错。如果 main 属性不存在,或者 package.json 不存在,则会尝试导入文件夹下的 index.jsindex.json,如果还是没找到,就会报错

2、包管理工具

下面列举了前端常用的包管理工具:

  • npm
  • yarn
  • cnpm

2.1、npm

npm 全称 Node Package Manager ,翻译为中文意思是 Node 的包管理工具

2.2、npm的安装

node.js 在安装时会自动安装 npm ,所以如果你已经安装了 node.js,可以直接使用 npm,可以通过 npm -v 查看版本号测试,如果显示版本号说明安装成功,反之安装失败

查看版本时与nodejs版本号不一样是正常的

2.3、npm基本使用

创建一个空目录,然后以此目录作为工作目录启动命令行工具,执行 npm init

  • npm init 命令的作用是将文件夹初始化为一个包,交互式创建 package.json 文件
  • package.json 是包的配置文件,每个包都必须要有
  • package.json 内容示例:
{"name": "01_npm","version": "1.0.0","description": "","main": "index.js","scripts": {"test": "echo \"Error: no test specified\" && exit 1"},"author": "","license": "ISC"
}

翻译:

{"name": "1-npm",   #包的名字"version": "1.0.0", #包的版本"description": "", #包的描述"main": "index.js", #包的入口文件"scripts": { #脚本配置"test": "echo \"Error: no test specified\" && exit 1"},"author": "", #作者"license": "ISC" #开源证书
}

初始化的过程中还有一些注意事项:

  1. package name ( 包名) 不能使用中文、大写,默认值是文件夹的名称,所以文件夹名称也不能使用中文和大写
  2. version ( 版本号)要求 x.x.x 的形式定义, x 必须是数字,默认值是 1.0.0
  3. package.json 可以手动创建与修改
  4. 使用 npm init -y 或者 npm init --yes 极速创建 package.json

在这里插入图片描述

2.4、搜索包

网址搜索:https://www.npmjs.com/

2.5、下载安装包

我们可以通过 npm installnpm i 命令安装包,例如我们要使用 unqi 包

在这里插入图片描述

# 格式
npm install <包名>
npm i <包名># 示例
npm install uniq
npm i uniq

步骤如下:

  1. 首先要执行 npm init -y 初始化包
  2. npm i uniq 安装uniq包

在这里插入图片描述

可以参照 npm 的 uniq 官网使用说明进行使用:

// 1.导入 uniq 包
const uniq = require('uniq');// 2.使用函数
let arr = [1,2,3,4,5,4,3,2,1];// [ 1, 2, 3, 4, 5 ]
console.log(uniq(arr));

这里说一下注意点:

  • 注意更换淘宝源码
  • npm cache clean --force 可以清楚npm缓存

运行之后文件夹下会增加两个资源:

  • node_modules 文件夹 :存放下载的包
  • package-lock.json 包的锁文件 : 用来锁定包的版本

安装 uniq 之后, uniq 就是当前这个包的一个依赖包,有时会简称为依赖

思考:require 到底导入的是什么?require的工作流程如下:

  1. 在当前文件夹下 node_modules 中寻找同名的文件夹
  2. 在上级目录中下的 node_modules 中寻找同名的文件夹,直至找到磁盘根目录

2.6、生产环境与开发环境

  • 开发环境是程序员专门用来写代码的环境,一般是指程序员的电脑,开发环境的项目一般只能程序员自己访问
  • 生产环境是项目代码正式运行的环境,一般是指正式的服务器电脑,生产环境的项目一般每个客户都可以访问

2.7、生产依赖与开发依赖

我们可以在安装时设置选项来区分依赖的类型,目前分为两类:

类型命令补充
生产依赖npm i --save uniq
npm i -S uniq
-S 等效于 --save, -S 是默认选项
包信息保存在 package.json 中 dependencies 属性
开发依赖npm i --save-dev less
npm i -D less
-D 等效于 --save-dev
包信息保存在 package.json 中 devDependencies 属性

所以开发依赖是只在开发阶段使用的依赖包,而生产依赖是开发阶段和最终上线运行阶段都用到的依赖包

在这里插入图片描述

因为 uniq 和 less 包都是局部安装,并不是全局安装,所以只能在 06_npm 文件夹下使用

2.8、全局安装

我们可以执行安装选项 -g 进行全局安装

npm i -g nodemon

在这里插入图片描述

全局安装完成之后就可以在命令行的任何位置运行 nodemon 命令,该命令的作用是 自动重启 node 应用程序

说明:

  • 全局安装的命令不受工作目录位置影响
  • 可以通过 npm root -g 可以查看全局安装包的位置
  • 不是所有的包都适合全局安装, 只有全局类的工具才适合,可以通过查看包的官方文档来确定安装方式

在这里插入图片描述

Tips:可能碰到如下问题的解决方案

  • nodemon : 无法加载文件 C:\Users\User\AppData\Roaming\npm\nodemon.ps1,因为在此系统上禁止运行脚本。_nodemon : 无法加载文件 c:\users\x\appdata\roaming\npm\no_薛定谔的猫87的博客-CSDN博客
  • 下方 2.9 也就是解决办法

在这里插入图片描述

2.9、修改windows执行策略

windows 默认不允许 npm 全局命令执行脚本文件,所以需要修改执行策略

  1. 管理员身份打开 powershell 命令行
  2. 键入命令 set-ExecutionPolicy remoteSigned
  3. 键入 A 然后敲回车
  4. 如果不生效,可以尝试重启 vscode/webstrom

2.10、安装包依赖

在项目协作中有一个常用的命令就是 npm i ,通过该命令可以依据 package.jsonpackagelock.json 的依赖声明安装项目依赖

npm inpm install

node_modules 文件夹大多数情况都不会存入版本库

2.11、安装指定版本的包

项目中可能会遇到版本不匹配的情况,有时就需要安装指定版本的包,可以使用下面的命令:

## 格式
npm i <包名@版本号>## 示例
npm i jquery@1.11.2

2.12、删除依赖

项目中可能需要删除某些不需要的包,可以使用下面的命令:

## 局部删除
npm remove uniq
npm r uniq## 全局删除
npm remove -g nodemon

2.13、配置命令别名

通过配置命令别名可以更简单的执行命令:配置 package.json 中的 scripts 属性

{"scripts": {"server": "node server.js","start": "node index.js",}
}

配置完成之后,可以使用别名执行命令:

npm run servernpm run start

不过 start 别名比较特别,使用时可以省略run : npm start

  • npm start 是项目中常用的一个命令,一般用来启动项目
  • npm run 有自动向上级目录查找的特性,跟 require 函数一样
  • 对于陌生的项目,我们可以通过查看 scripts 属性来参考项目的一些操作

3、cnpm

cnpm 是一个淘宝构建的 npmjs.com 的完整镜像,也称为 淘宝镜像,网址:https://npmmirror.com/

  • cnpm 服务部署在国内阿里云服务器上, 可以提高包的下载速度
  • 官方也提供了一个全局工具包 cnpm ,操作命令与 npm 大体相同

3.1、安装cnpm

我们可以通过 npm 来安装 cnpm 工具

npm install -g cnpm --registry=https://registry.npmmirror.com

3.2、操作命令

功能命令
初始化cnpm init
安装包cnpm i uniq
cnpm i -S uniq
cnpm i -D uniq
cnpm i -g nodemon
安装项目依赖cnpm i
删除uniq依赖cnpm r uniq

3.2、npm配置淘宝镜像

用 npm 也可以使用淘宝镜像,配置的方式有两种:

  • 直接配置
  • 工具配置

3.2.1、直接配置

执行如下命令即可完成配置:

npm config set registry https://registry.npmmirror.com/

3.2.2、工具配置

使用 nrm 配置 npm 的镜像地址 npm registry manager

  1. 安装 nrm
npm i -g nrm		
  1. 修改镜像
# 查看所有的镜像
nrm ls # 选择淘宝镜像
nrm use taobao# 切换到官方地址
nrm use npm
  1. 检查是否配置成功
npm config list

检查 registry 地址是否为 https://registry.npmmirror.com/ , 如果是则表明成功

  1. 建议使用第二种方式进行镜像配置,因为后续修改起来会比较方便
  2. 虽然 cnpm 可以提高速度,但是 npm 也可以通过淘宝镜像进行加速,所以npm 的使用率还是高于 cnpm

4、yarn

yarn 是由 Facebook 在 2016 年推出的新的 Javascript 包管理工具,官方网址: https://yarnpkg.com/

4.1、yarn安装

我们可以使用 npm 安装 yarn

npm i -g yarn

4.2、yarn常用命令

功能命令
初始化yarn init / yarn init -y
安装包yarn add uniq 生产依赖
yarn add less --dev 开发依赖
yarn global add nodemon 全局安装
删除包yarn remove uniq 删除项目依赖包
yarn global remove nodemon 全局删除包
安装项目依赖yarn
运行命令别yarn <别名> # 不需要添加 run

4.3、yarn配置淘宝镜像

可以通过如下命令配置淘宝镜像:

yarn config set registry https://registry.npmmirror.com/

可以通过 yarn config list 查看 yarn 的配置项

4.4、npm 和 yarn 选择

大家可以根据不同的场景进行选择:如果是公司要根据项目代码来选择,可以通过锁文件判断项目的包管理工具

  • npm 的锁文件为 package-lock.json
  • yarn 的锁文件为 yarn.lock

5、nvm

nvm 全称 Node Version Manager 顾名思义它是用来管理 node 版本的工具,方便切换不同版本的Node.js

5.1、下载安装

  1. 进入下载地址:https://github.com/coreybutler/nvm-windows/releases
  2. 选择 nvm-setup.exe 下载

在这里插入图片描述

5.2、常用命令

命令说明
nvm list available显示所有可以下载的 Node.js 版本
nvm list显示已安装的版本
nvm install 18.17.1安装 18.12.1 版本的 Node.js
nvm install latest安装最新版的 Node.js
nvm uninstall 18.17.1删除某个版本的 Node.js
nvm use 18.17.1切换 18.12.1 的 Node.js

Tips: 很鬼扯,安装了 nvm 后 node -v 提示报错,并且 nvm list 提示没有已安装的node版本,安装 nvm 时没有给我提示要管理已安装的 node 版本的指示,所以这里我是将 node 卸载后,先装 nvm ,之后通过 nvm 装 node 18.17.1

在这里插入图片描述

在这里插入图片描述

  1. 安装完成后找到 nvm的安装路径 - 找到 settings.txt 文件 - 配置下载源
root: D:\Develop\nvm
path: D:\Develop\nodejsnode_mirror: https://npm.taobao.org/mirrors/node/
npm_mirror: https://npm.taobao.org/mirrors/npm/
  1. 然后打开命令行窗口
# 显示所有可以下载的 Node.js 版本
nvm list available# 安装 18.12.1 版本的 Node.js
nvm install 18.17.1

在这里插入图片描述

  1. 使用这个版本的 node
nvm use 18.17.1# 查看node版本
node -v# 查看 npm 版本
npm -v# 全局安装 nrm
npm i -g nrm# 查看所有的镜像
nrm ls # 选择淘宝镜像
nrm use taobao# 全局安装nodemon
npm i -g nodemon

6、Express框架

express 是一个基于 Node.js 平台的极简、灵活的 WEB 应用开发框架,官方网址:Express - 基于 Node.js 平台的 web 应用开发框架 - Express 中文文档 | Express 中文网 (expressjs.com.cn)

  • 简单来说,express 是一个封装好的工具包,封装了很多功能,便于我们开发 WEB 应用(HTTP 服务)

6.1、下载使用

  1. 通过 npm 安装
# 先对一个空文件夹进行初始化
npm init -y
# 安装express包
npm i express 
# 查看express版本
npm list express
  1. 创建 JS 文件
// 1.导入 express
const express = require('express');//2. 创建应用对象
const app = express();//3. 创建路由规则
app.get('/home', (req, res) => {res.end('hello express server');
});//4. 监听端口 启动服务
app.listen(3000, () =>{console.log('服务已经启动, 端口监听为 3000...');
});
  1. 命令行下执行该脚本
node <文件名>
# 或者
nodemon <文件名>
  1. 然后在浏览器就可以访问 http://127.0.0.1:3000/home

6.2、express路由

路由确定了应用程序如何响应客户端对特定端点的请求,一个路由的组成有请求方法路径回调函数组成,使用格式如下:

app.<method>(path,callback)

示例:

// 1.导入 express
const express = require('express');//2. 创建应用对象
const app = express();//3. 创建get路由
app.get('/', (req,res) => {res.send('首页路由');
});app.get('/home', (req, res) => {res.end('home页路由');
});//创建 post 路由
app.post('/login', (req, res) => {res.send('登录成功');
});//匹配所有的请求方法(请求方法无所谓,只要路径是 /test)
app.all('/search', (req, res) => {res.send('1 秒钟为您找到相关结果约 100,000,000 个');
});//自定义 404 路由
app.all("*", (req, res) => {res.send('<h1>404 Not Found</h1>')
});//4. 监听端口 启动服务
app.listen(3000, () =>{console.log('服务已经启动, 端口监听为 3000...');
});

在这里插入图片描述

6.3、获取请求参数

express 框架封装了一些 API 来方便获取请求报文中的数据,并且兼容原生 HTTP 模块的获取方式:

  • 访问: http://127.0.0.1:3000/request?usernmae=qinxiaolin&age=21 ,如下注释即为获取的请求参数
// 1.导入 express
const express = require('express');//2. 创建应用对象
const app = express();//3. 获取请求的路由规则
app.get('/request', (req,res) => {//1. 获取报文的方式与原生 HTTP 获取方式是兼容的console.log(req.method); // getconsole.log(req.url); // /requestconsole.log(req.httpVersion); // 1.1console.log(req.headers);//2. express 独有的获取报文的方式//获取查询字符串console.log(req.query); // 『相对重要』 { usernmae: 'qinxiaolin', age: '21' }// 获取指定的请求头console.log(req.get('host')); // 127.0.0.1:3000res.send('请求报文的获取');
});//自定义 404 路由
app.all("*", (req, res) => {res.send('<h1>404 Not Found</h1>')
});//4. 监听端口 启动服务
app.listen(3000, () =>{console.log('服务已经启动, 端口监听为 3000...');
});

6.4、获取路由参数

路由参数指的是 URL 路径中的参数

// 1.导入 express
const express = require('express');//2. 创建应用对象
const app = express();// 获取路由参数
app.get('/:id.html', (req, res) => {console.log(req.params.id); // 123res.send('商品详情' );
});//4. 监听端口 启动服务
app.listen(3000, () =>{console.log('服务已经启动, 端口监听为 3000...');
});

我们访问:

  • http://127.0.0.1:3000/123.htmlreq.params.id 为 123
  • http://127.0.0.1:3000/456.htmlreq.params.id 为 456

6.5、express响应设置

express 框架封装了一些 API 来方便给客户端响应数据,并且兼容原生 HTTP 模块的获取方式

// 1.导入 express
const express = require('express');//2. 创建应用对象
const app = express();// 获取路由参数
app.get('/response', (req, res) => {//1. express 中设置响应的方式兼容 HTTP 模块的方式res.statusCode = 404;res.statusMessage = 'xxx';res.setHeader('abc','xyz');res.write('响应体');res.end('xxx');//2. express 的响应方法res.status(500); //设置响应状态码res.set('xxx','yyy');//设置响应头res.send('中文响应不乱码');//设置响应体//连贯操作res.status(404).set('xxx','yyy').send('你好朋友')});//4. 监听端口 启动服务
app.listen(3000, () =>{console.log('服务已经启动, 端口监听为 3000...');
});

express的其他响应方法:

// 1.导入 express
const express = require('express');//2. 创建应用对象
const app = express();// 获取路由参数
app.get('/other', (req, res) => {//跳转响应//res.redirect('http://atguigu.com')//重定向下载响应//res.download(__dirname + './package.json');//JSON响应//res.json({//  username : "秦晓",//  age: 21//});响应文件内容,把 home.html 响应res.sendFile(__dirname + '/home.html')});//4. 监听端口 启动服务
app.listen(3000, () =>{console.log('服务已经启动, 端口监听为 3000...');
});
  • res.redirect('http://atguigu.com') 跳转响应,若访问 http://127.0.0.1:3000/response 则会跳转到 http://atguigu.com

  • res.download(__dirname + './package.json') 下载响应,若访问 http://127.0.0.1:3000/response 则会下载 项目工程的package.json 文件

  • json 响应到浏览器

  • home.html网页响应到浏览器

在这里插入图片描述

在这里插入图片描述

6.6、express中间件

中间件(Middleware)本质是一个回调函数,中间件函数可以像路由回调一样访问请求对象(request)响应对象(response)

  • 中间件的作用就是使用函数封装公共操作,简化代码

  • 中间件的类型

    • 全局中间件
    • 路由中间件

6.6.1、定义全局中间件

每一个请求到达服务端之后都会执行全局中间件函数

全局中间件就相当于 进站口,而路由中间件就相当于 检票口

先进 进站口,再进 检票口

例如我们下面的代码是访问任何路由时我们都对url和id作记录,并写入 access.log 文件中:

// 1.导入 express
const express = require('express');
const fs = require('fs');
const path = require('path');//2. 创建应用对象
const app = express();// 声明中间件函数(函数名随便写)
// req是请求报文的对象,res是响应报文的对象
function recordMiddleware(req,res,next){// 获取url 和 idlet {url,ip} = req;// 将信息保存在文件的 access.log// path.resolve() 第一个参数是文件的绝对路径,第二个参数是写入文件的内容fs.appendFileSync(path.resolve(__dirname,'./access.log'),`${url} ${ip}\r\n`);//调用next(当如果希望执行完中间件函数之后,仍然继续执行路由中的回调函数,必须调用next)next();
}//使用中间件函数
app.use(recordMiddleware);//3. 创建路由规则
app.get('/home', (req, res) => {res.send('前台首页');
});app.get('/admin', (req, res) => {res.send('后台首页');
});app.all('*', (req, res) => {res.send('<h1>404</h1>>');
});//4. 监听端口 启动服务
app.listen(3000, () =>{console.log('服务已经启动, 端口监听为 3000...');
});
  • 依次访问:
    • http://127.0.0.1:3000/home
    • http://127.0.0.1:3000/admin
    • ``http://127.0.0.1:3000/1234`

在这里插入图片描述

所以定义全局中间件的步骤如下:

  1. 声明中间件函数
function recordMiddleware(req,res,next){// 实现功能的代码...// 执行next函数next();
}
  1. 应用中间件
app.use(recordMiddleware);// 或者如下写法
app.use(function recordMiddleware(req,res,next){// 实现功能的代码...// 执行next函数next();
})

6.6.2、定义路由中间件

如果只需要对某一些路由进行功能封装,则就需要路由中间件,调用格式如下:

app.get('/路径',中间件函数1,中间件函数2,(request,response) => {})

例如:

// 1.导入 express
const express = require('express');//2. 创建应用对象
const app = express();// 声明中间件函数
let recordMiddleware = (req,res,next) => {// 判断url中是否code参数等于521,若满足条件,则进行路由回调if(req.query.code === '521'){next();}else{res.send('暗号错误')}
}//使用中间件函数
app.use(recordMiddleware);//3. 创建路由规则
app.get('/home',recordMiddleware, (req, res) => {res.send('前台首页');
});app.get('/admin',recordMiddleware, (req, res) => {res.send('后台首页');
});//4. 监听端口 启动服务
app.listen(3000, () =>{console.log('服务已经启动, 端口监听为 3000...');
});

6.6.3、静态资源中间件

express 内置处理静态资源的中间件

// 1.导入 express
const express = require('express');//2. 创建应用对象
const app = express();// 静态资源中间件的设置,将当前文件夹下的public目录作为网站的根目录
app.use(express.static(__dirname + './public'));//3. 创建路由规则
app.get('/index.html', (req, res) => {res.send('前台首页');
});//4. 监听端口 启动服务
app.listen(3000, () =>{console.log('服务已经启动, 端口监听为 3000...');
});

这样我们就可以访问 public 下的资源文件了

  • http://127.0.0.1:3000/css/app.css
  • http://127.0.0.1:3000/index.html

注意事项:

  1. index.html 文件为默认打开的资源
    • 访问public/index.html,既可以http://127.0.0.1:3000/index.html ,也可以 http://127.0.0.1:3000
  2. 如果静态资源与路由规则同时匹配,谁先匹配谁就响应
    • 如果路径规则是一个 / , 则路由规则和静态资源都可以匹配
  3. 路由响应动态资源,静态资源中间件响应静态资源

6.7、获取请求体

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

  1. 安装
npm i body-parser
  1. 导入包
const bodyParser = require('body-parser');
  1. 获取中间件函数
    • 一个是解析 querystring 格式请求体的中间件
    • 另一个是解析 JSON 格式请求体的中间件
    • 需要使用哪个就用哪个中间件
//解析 querystring 格式请求体的中间件
let urlParser = bodyParser.urlencoded({extended:false}));
//解析 JSON 格式请求体的中间件
let jsonParser = bodyParser.json();
  1. 设置路由中间件,然后使用 request.body 来获取请求体数据
// 1.导入 express
const express = require('express');
const bodyParser = require('body-parser');//2. 创建应用对象
const app = express();// 声明中间件函数
//解析 querystring 格式请求体的中间件
let urlParser = bodyParser.urlencoded({extended:false});
//解析 JSON 格式请求体的中间件
let jsonParser = bodyParser.json();//3. 创建路由规则
// 使用解析 querystring 格式请求体的中间件
app.post('/login',urlParser,(request,response) => {// 获取请求体数据console.log(request.body);// 用户名console.log(request.body.username);// 密码console.log(request.body.password);response.send('获取请求体数据');
})//4. 监听端口 启动服务
app.listen(3000, () =>{console.log('服务已经启动, 端口监听为 3000...');
});

6.8、Router

express 中的 Router 是一个完整的中间件和路由系统,可以看做是一个小型的 app 对象。Router的作用是对路由进行模块化,更好的管理路由。

  1. 创建独立的Js文件:homeRouter.js
//1. 导入 express
const express = require('express');//2. 创建路由器对象
const router = express.Router();//3. 在 router 对象身上添加路由
router.get('/', (req, res) => {res.send('首页');
})
router.get('/cart', (req, res) => {res.send('购物车');
});//4. 暴露
module.exports = router;
  1. 在其他文件引用
const express = require('express');
const app = express();
//引入子路由文件
const homeRouter = require('../router/homeRouter');
//设置和使用中间件
app.use(homeRouter);
app.listen(3000,()=>{console.log('3000 端口启动....');
})

这样依然可以像之前访问一样

  • http://127.0.0.1:3000/cart

6.9、模板引擎EJS

  • 中文站:EJS – 嵌入式 JavaScript 模板引擎 | EJS 中文文档 (bootcss.com)
  • 官网:EJS – Embedded JavaScript templates
  1. 下载安装EJS
npm i ejs --save
  1. 引入包
// 导入ejs
const ejs = require('ejs');// 字符串
let china = '中国';
let str = '我爱你 <%= china%>'
// 使用ejs渲染
let result = ejs.render(str,{china: china});
console.log(result); // 我爱你 中国

6.9.1、分离用法

// 导入ejs
const ejs = require('ejs');
const fs = require('fs');// 字符串
let china = '中国';let str = fs.readFileSync('./00_ejs.html').toString();
// 使用ejs渲染
let result = ejs.render(str,{china: china});
console.log(result); // 我爱你 中国

我们的00_ejs.html 的内容如下:

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body>
<h2> <%= china%> </h2>
</body>
</html>

这样运行 js ,就会渲染

在这里插入图片描述

以此来达到 html 和 js 进行分离

6.10、express-generator

  • 官网:Express 应用程序生成器 - Express中文文档 | Express中文网 (expressjs.com.cn)
  1. 下载 Express 应用程序生成器
npx express-generator
  1. 生成代码骨架后安装依赖
npm i
  1. 运行项目
npm start
  1. 浏览器访问:http://127.0.0.1:3000/

在这里插入图片描述

6.10.1、补充知识

  • app.use() 也可以设置路由前缀
// 设置路由前缀
app.use('/users', users.js);// users.js 如下
router.get('/test', function(req, res, next) {res.send('用户测试');
});

如上代码,由于加了 /users 前缀,所以访问url就变成了 http://127.0.0.1:3000/users/test

相关文章:

Node18.x基础使用总结(二)

Node18.x基础使用总结 1、Node.js模块化1.1、模块暴露数据1.2、引入模块 2、包管理工具2.1、npm2.2、npm的安装2.3、npm基本使用2.4、搜索包2.5、下载安装包2.6、生产环境与开发环境2.7、生产依赖与开发依赖2.8、全局安装2.9、修改windows执行策略2.10、安装包依赖2.11、安装指…...

LCD 的RGB接口(SYNC Mode/ SYNC-DE Mode/ DE Mode)

1、 SYNC Mode Timing Diagram 2、 SYNC-DE Mode Timing Diagram 3、 DE Mode Timing Diagram RGB接口&#xff08;SYNC Mode/ SYNC-DE Mode/ DE Mode&#xff09;-CSDN博客...

flink生成水位线记录方式--周期性水位线生成器

背景 在flink基于事件的时间处理中&#xff0c;水位线记录的生成是一个很重要的环节&#xff0c;本文就来记录下几种水位线记录的生成方式的其中一种&#xff1a;周期性水位线生成器 周期性水位线生成器 1.1 BoundedOutOfOrdernessTimeStampExtractor 他会接收一个表示最大延…...

百度资源搜索平台出现:You do not have the proper credential to access this page.怎么办?

Forbidden site not allowed You do not have the proper credential to access this page. If you think this is a server error, please contact the webmaster. 如果你的百度资源平台&#xff0c;点进去出现这个提示&#xff0c;说明您的网站已经被百度清退了。如果你的网站…...

树莓派CM4开启I2C与UART串口登录同时serial0映射到ttyS0 开启多串口

文章目录 前言1. 树莓派开启I2C与UART串口登录2. 开启多串口总结&#xff1a; 前言 最近用CM4的时候使用到了I2C以及多个UART的情况。 同时配置端口映射也存在部分问题。 这里集中记录一下。 1. 树莓派开启I2C与UART串口登录 输入指令sudo raspi-config 跳转到如下界面&#…...

【租车骑绿道】python实现-附ChatGPT解析

1.题目 租车骑绿道 时间限制:1s 空间限制:256MB 限定语言:不限 题目描述: 部门组织绿道骑行团建活动。租用公共双人自行车骑行,每辆自行车最多坐两人、做大载重M。 给出部门每个人的体重,请问最多需要租用多少双人自行车 输入描述 第一行两个数字m、n,自行车限重m,代表部门总…...

【ONE·Linux || 多线程(一)】

总言 多线程&#xff1a;进程线程基本概念、线程控制、互斥与同步。 文章目录 总言1、基本概念1.1、补充知识1.1.1、堆区细粒度划分1.1.2、虚拟地址到物理空间的转化 1.2、如何理解线程、进程1.2.1、如何理解线程&#xff1f;1.2.2、如何理解进程&#xff1f; 1.3、实践操作1.…...

华为智能企业上网行为管理安全解决方案(1)

华为智能企业上网行为管理安全解决方案&#xff08;1&#xff09; 课程地址方案背景需求分析企业上网行为概述企业上网行为安全风险分析企业上网行为管理需求分析 方案设计组网架构设备选型设备简介行为管理要点分析方案功能概述 课程地址 本方案相关课程资源已在华为O3社区发…...

Acwing 240. 食物链

Acwing 240. 食物链 题目描述思路讲解代码展示 题目描述 思路讲解 代码展示 #include <iostream>using namespace std;const int N 50010;int n, m; int p[N], d[N]; //p[]是并查集的father,d[]是距离int find(int x) {if (p[x] ! x) { //如果说x不是树根的话int t f…...

c++ 容器适配器

Container //创建一个命名空间&#xff0c;避免和库里的冲突 namespace chen {//写一个模版template<class T, class Container deque<T>>//开始写我们的类class stack{public:void push(const T& x){_con.push_back(x);}void pop(){_con.pop_back();}const …...

正则表达式的应用领域及基本语法解析

目录 一、正则表达式的应用领域 1. 文本搜索和替换 2. 表单验证 3. 数据提取和分析 4. 数据清洗和处理 5. URL路由和路由匹配 二、正则表达式的基本语法 1. 字符匹配 2. 元字符和字符类 3. 量词和边界 4. 分组和捕获 5. 转义字符 三、常见正则表达式示例 1. 邮箱…...

CIP或者EtherNET/IP中的PATH是什么含义?

目录 SegmentPATH举例 最近在学习EtherNET/IP&#xff0c;PATH不太明白&#xff0c;翻了翻规范&#xff0c;在这里记个笔记。下面的叙述可能是中英混合&#xff0c;有一些是规范中的原文我直接搬过来的。我翻译的不准确。 Segment PATH是CIP Segment中的一个分类。要了解PATH…...

使用lombok进行bulider之后调取HashMap的自定义方法进行对象操作报空指针异常(pojo也适用)

概论 这主要的问题就是bulider的特性的问题&#xff0c;就是他只能给你搭建了一个脚手架&#xff0c;里面的东西其实他没动你的&#xff0c;你得自己去给他实体化&#xff0c;如果你使用了类似HashMap等集合的话&#xff0c;你得自己去bulid一个在那个里面作为初始化对象你才可…...

矩阵-day14

...

上古神器:十六位应用程序 Debug 的基本使用

文章目录 参考环境上古神器 DebugBug 与 DebuggingDebugDebug 应用程序淘汰原因使用限制 DOSBox学习 Debug 的必要性DOSBox-X Debug 的基本使用命令 R查看寄存器的状态修改寄存器的内容 命令 D显示内存中的数据指定起始内存空间地址指定内存空间的范围 命令 A使用命令语法错误查…...

[学习笔记]ARXML - Data Format

参考AUTOSAR文档&#xff1a; https://www.autosar.org/fileadmin/standards/R22-11/FO/AUTOSAR_TPS_ARXMLSerializationRules.pdfhttps://www.autosar.org/fileadmin/standards/R22-11/FO/AUTOSAR_TPS_ARXMLSerializationRules.pdf 编码 arxml只允许使用UTF-8编码&#xff…...

Go_原子操作和锁

原子操作和锁 本文先探究并发问题&#xff0c;再探究锁和原子操作解决问题的方式&#xff0c;最后进行对比。 并发问题 首先&#xff0c;我们看一下程序 num该程序表面看上去一步就可以运行完成&#xff0c;但是实际上&#xff0c;在计算机中是分三步运行的&#xff0c;如下…...

初识Java 12-1 流

目录 Java 8对流的支持 流的创建 随机数流 int类型的区间范围 generate() iterate() 流生成器 Arrays 正则表达式 本笔记参考自&#xff1a; 《On Java 中文版》 ||| 流的概念&#xff1a;流是一个与任何特定的存储机制都没有关系的元素序列。 流与对象的成批处理有关…...

【软件工程_UML—StartUML作图工具】startUML怎么画interface接口

StartUML作图工具怎么画interface接口 初试为圆形 &#xff0c;点击该接口在右下角的设置中->Format->Stereotype Display->Label&#xff0c;即可切换到想要的样式 其他方式 在class diagram下&#xff0c;左侧有interface图标&#xff0c;先鼠标左键选择&#xff0…...

单片机之瑞萨RL78定时计数器

单片机之瑞萨RL78定时计数器 使用瑞萨RL78定时计数器的简单例程。这个例程使用定时器0来产生一个以秒为单位的定时器中断&#xff0c;并在中断服务程序中增加一个全局变量以跟踪中断的发生。 首先&#xff0c;我们需要了解RL78的定时器0是一个16位的定时器&#xff0c;它的时钟…...

手机号码格式校验:@Phone(自定义参数校验注解)

需求 新增接口 和 修改接口 中&#xff0c;手机号码的格式校验是普遍需要的。 在每个手机号码字段上添加正则表达式校验注解来实现校验&#xff0c;重复书写&#xff0c;容易出错&#xff1b;在不同的手机号码字段上&#xff0c;可能使用了不同的校验规则&#xff0c;无法有效…...

ORACLE Redo Log Buffer 重做日志缓冲区机制的设计

最近和朋友包括一些国产数据库的研发人员交流&#xff0c;很多程序员认为 Oracle 已经过时&#xff0c;开源数据库或者他们研发的国产数据库才代表数据库发展的未来。甚至在很多交流会议上拿出自家产品的某一个功能点和 Oracle 对比就觉得已经遥遥领先。 实际上数据库系统的发展…...

PWN Test_your_nc Write UP

目录 PWN 00 解题过程 总结归纳 PWN 01 解题过程 总结归纳 PWN 02 解题过程 总结归纳 PWN 03 解题过程 总结归纳 PWN 04 解题过程 总结归纳 CTF PWN 开始&#xff01; 冲就完了 PWN 00 解题过程 ssh远程链连接 ssh ctfshowpwn.challenge.ctf.show -p28151 输…...

Centos7配置firewalld防火墙规则

这里写自定义目录标题 欢迎使用Markdown编辑器一、简单介绍二、特点和功能2.1、区域&#xff08;Zone&#xff09;2.2、运行时和永久配置2.3、服务和端口2.4、动态更新2.5、连接跟踪2.6、D-Bus接口 三、设置规则3.1、启动防火墙服务3.2、新建防火墙规则的服务&#xff0c;添加端…...

【新版】系统架构设计师 - 未来信息综合技术

个人总结&#xff0c;仅供参考&#xff0c;欢迎加好友一起讨论 文章目录 架构 - 未来信息综合技术考点摘要信息物理系统CPS的体系架构CPS 的技术体系CPS应用场景 人工智能分类关键技术机器学习 机器人发展分类机器人4.0 边缘计算概念与特点边云协同安全应用场景 数字孪生关键技…...

CAD二次开发LineSegment2d

在C#的CAD二次开发中&#xff0c;LineSegment2d 是AutoCAD的.NET API中的一个类&#xff0c;用于表示二维空间中的线段。它包含了起点和终点的坐标信息&#xff0c;并提供了一些方法用于进行线段之间的计算和判断。 LineSegment2d 类具有以下常用属性和方法&#xff1a; Star…...

Linux shell编程学习笔记5:变量命名规则、变量类型、使用变量时要注意的事项

跟其他的高级开发语言一样&#xff0c;Linux Shell编程中使用的数据也需要保存在变量中。 Shell使用变量来控制其行为&#xff0c;并且可以通过更改变量值来更改Shell和其他程序的行为。 我们先来了解一下变量命令的规则、变量类型和使用变量时要注意的事项。 一、变量命名规…...

如何把word的页眉页脚改为图片

前言 亲戚A&#xff1a; 听说你是计算机专业&#xff1f; 沐风晓月&#xff1a; 是啊 亲戚A&#xff1a; 那正好&#xff0c;来看看我这个页眉怎么改成图片 沐风晓月&#xff1a; 一万匹马奔腾而过 亲戚B&#xff1a; 听说你是英语专业&#xff1f; 沐风晓月&#xff1a; 是啊…...

spring6-实现简易版IOC容器

手写简易版IOC容器 1、回顾Java反射2、实现Spring的IoC 我们都知道&#xff0c;Spring框架的IOC是基于Java反射机制实现的&#xff0c;下面我们先回顾一下java反射。 1、回顾Java反射 Java反射机制是在运行状态中&#xff0c;对于任意一个类&#xff0c;都能够知道这个类的所…...

Feign接口调用GET请求@RequestParam传参丢失

文章目录 问题现象排查解决GET加注解解决使用POST方式解决 时间戳传参失败 问题现象 项目使用的是Spring Cloud微服务&#xff0c;服务间调用使用的是Feign在一次服务调用时&#xff0c;发现GET传参丢失&#xff0c;没有传递过去任何参数加了RequestParam注解&#xff0c;发现…...

天津建设工程信息网网/湖南企业竞价优化服务

代  码 #输出元组变量 tuple (1,2,3,4,5,a,b,c) print(tuple) 运行结果 (1, 2, 3, 4, 5, a, b, c) 代  码 #输出字典变量 dict {a:1, b:2,c:3} print(dict) 运行结果 {a: 1, b: 2, c: 3...

网站建设流程案例/拓客团队怎么联系

我在github上写的文章&#xff0c;复制过来格式太乱&#xff0c;还是直接用链接吧。 http://sunmh207.github.io/2016/02/01/recommendcourses/...

临沂做网站选盛誉/网站优化建设

曾经有人说过&#xff0c;世界上有两种编辑器&#xff0c;好用和不好用的&#xff1b;而在好用的编辑器中&#xff0c;又分两种&#xff0c;免费的和死贵死贵的。譬如说 VIM 和 TextMate&#xff0c;就是免费和死贵的典型。很不幸&#xff0c;今天的主角 Sublime Text 2 也是个…...

网站论坛页怎么做/seo网站关键词快速排名

文章目录Numpy学习目标4.1 Numpy优势学习目标4.1.1 Numpy介绍4.1.2 ndarray介绍4.1.3 ndarray与Python原生list运算效率对比4.1.4 ndarray的优势4.1.4.1内存块风橙4.1.4.2 ndarray支持并行化运算&#xff08;向量化运算&#xff09;4.1.4.3效率远高于纯Python代码4.1.5小结4.2 …...

网站访客qq获取原理/seo有什么作用

转载&#xff1a;http://www.cnblogs.com/xly1208/archive/2011/11/19/2255500.html http://www.cnblogs.com/duqiao/archive/2012/11/06/2756447.html 首先了解下OGNL的概念&#xff1a; OGNL是Object-Graph Navigation Language的缩写&#xff0c;全称为对象图导航语言&#…...

自己创建网站/网络推广seo公司

一个.net写的木马样本&#xff0c;内嵌了两个资源&#xff0c;分别是&#xff1a; LAN_Core &#xff08;.net dll程序&#xff0c;用于解密png中的assembly&#xff09;ESgFXCQfRbAmmGdIaVSZ.png &#xff08;用图片隐写技术嵌入了另一个.net程序&#xff09; 主程序通过调用…...