09-Node.js—express框架

目录

  • 1、express 介绍
  • 2、express 使用
    • 2.1 express 下载
    • 2.2 express 初体验
  • 3、express 路由
    • 3.1 什么是路由
    • 3.2 路由的使用
      • 3.2.1使用Ajax发送一次post请求
    • 3.3 获取请求参数
  • 3.4 获取路由参数
    • 3.5 路由参数练习
  • 4、express 响应设置
  • 5、express 中间件
    • 5.1 什么是中间件
    • 5.2 中间件的作用
    • 5.3 中间件的类型
    • 5.4 全局中间件
      • 5.4.1定义全局中间件
      • 5.4.2 多个全局中间件
      • 5.4.3 具体实现全局中间件
    • 5.5 路由中间件
    • 5.5.1 定义路由中间件
    • 5.6 静态资源中间件
      • 5.6.1 静态资源中间件练习
    • 5.7 获取请求体数据 body-parser
      • 5.7.1 练习
  • 6、防盗链
    • 6.1 什么是防盗链
    • 6.2 防盗链的实现
    • 6.3 具体实现
  • 7、Router
    • 7.1 什么是 Router
    • 7.2 Router 作用
    • 7.3 Router 使用
  • 8、EJS 模板引擎
    • 8.1 什么是模板引擎
    • 8.2 什么是 EJS
    • 8.3 EJS 初体验
    • 8.4 EJS 常用语法
    • 8.5 EJS 渲染列表
    • 8.6 ejs条件渲染
    • 8.7 express中使用ejs
  • 9、Express 应用程序生成器

1、express 介绍

  • express 是一个基于 Node.js 平台的极简、灵活的 WEB应用开发框架,官方网址:https://www.expressjs.com.cn/
  • 简单来说,express 是一个封装好的工具包,封装了很多功能,便于我们开发 WEB 应用(HTTP 服务)

大家都应该玩过我的世界,在我的世界中如果纯靠手去砍树或者挖矿,效率是很低的,所以我们在玩的时候会去做个斧头和⛏子,然后再去砍树和挖矿,这样提高了获取资源的效率。
我们开发web应用也是如此,如果纯靠原生去开发,效率是很低的,所以我们就需要用到一些框架来辅助我们提高开发效率。

2、express 使用

2.1 express 下载

  • express 本身是一个 npm 包,所以可以通过 npm 安装

  • 先让文件夹初始化为一个『包』, 交互式创建 package.json 文件。

    npm init
    
  • 安装express包

    npm i express
    

2.2 express 初体验

  • 大家可以按照这个步骤进行操作:
    1. 创建 JS 文件,输入如下代码
		//1、导入包
		const express = require('express')
		//2、创建应用对象
		const app= express()
		//3、创建路由规则
		app.get('/home', (req, res) => {
		    res.end('Hello Express')
		})
		//4、监听端口 启动服务
		app.listen(9000,()=>{
		    console.log('服务已启动,监听9000端口中');
		})
  1. 命令行下执行该脚本
		node <文件名>
		# 或者
		nodemon <文件名>
  1. 然后在浏览器就可以访问http://127.0.0.1:9000/home

    在这里插入图片描述

3、express 路由

3.1 什么是路由

  • 官方定义: 路由确定了应用程序如何响应客户端对特定端点的请求

    简单来说就是浏览器发送了请求,然后路由决定这个请求由谁去处理;
    它会根据请求的路径来决定哪个回调函数去执行。

3.2 路由的使用

  • 一个路由的组成有 请求方法路径回调函数 组成

  • express 中提供了一系列方法,可以很方便的使用路由,使用格式如下:

    app.<method>(path,callback)
    

代码示例:

//1、导入包
const express = require('express')
//2、创建应用对象
const app = express()
//3、创建路由规则
//创建get路由
app.get('/home', (req, res) => {
    res.end('Hello Express')
})
// 首页路由
app.get('/', (req, res) => {
    res.setHeader('content-type', 'text/html;charset=utf-8')
    res.end('网站首页')
})
// 创建post路由
app.post('/login', (req, res) => {
    res.end('登录成功')
})
// 创建匹配所有的请求方法
app.all('/search', (req, res) => {
    res.setHeader('content-type', 'text/html;charset=utf-8')
    res.end('我爱你')
})
//自定义 404 路由
app.all('*', (req, res) => {
res.end('404 Not Found')
})
//4、监听端口 启动服务
app.listen(9000, () => {
    console.log('服务已启动,监听9000端口中');
})

3.2.1使用Ajax发送一次post请求

由于浏览器默认发送的是GET请求,所以我们需要用Ajax发送post请求。当然用form表单也可以发送post请求。

代码示例:
1.HTML文件

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        button {
            width: 60px;
            height: 30px;
            background-color: aqua;
            cursor: pointer;
            border: none;
        }
    </style>
</head>
<body>
    <button class="post"></button>
    <script>
        document.querySelector('.post').addEventListener('click', () => {
            const xhr = new XMLHttpRequest()
            xhr.open("POST", " http://127.0.0.1:9000/login")
            xhr.onreadystatechange = function () {
                if (xhr.readyState === 4 && /^2\d{2}$/.test(xhr.status)) {
                    console.log(xhr.responseText)
                }
            }
            xhr.send()
        })
    </script>
</body>
</html>

2.使用express框架

// 导入express包
const express = require('express')
//导入cors包
const cors = require('cors')
// 创建应用对象
const app = express()
// 调用cors包解决跨域问题
app.use(cors())
// 设置路由规则
app.post('/login',(req,res)=>{
    res.end('登录成功')
})
// 监听端口,启动服务
app.listen(9000,()=>{
    console.log('服务已启动,监听9000端口中......');
})

3.3 获取请求参数

  • express 框架封装了一些 API 来方便获取请求报文中的数据,并且兼容原生 HTTP 模块的获取方式
	//导入 express
	const express = require('express')
	//创建应用对象
	const app = express()
	//获取请求的路由规则
	app.get('/path', (req, res) => {
	    //1. 获取报文的方式与原生 HTTP 获取方式是兼容的
	    // 获取请求方法
	    console.log(req.method);
	    //获取url
	    console.log(req.url);
	    // 获取版本号
	    console.log(req.httpVersion);
	    // 获取请求头
	    console.log(req.headers);
	    //2. express 独有的获取报文的方式
	    // 获取路径
	    console.log(req.path);
	    // 获取查询字符串
	    console.log(req.query);
	    // 获取ip
	    console.log(req.ip);
	    // 获取请求头
	    console.log(req.headers);
	    // 获取指定的请求头
	    console.log(req.get('host'));
	    res.end('hello')
	})
	// 监听端口,启动服务
	app.listen(9000, () => {
	    console.log('服务已启动,监听端口9000中.....');
	})

3.4 获取路由参数

  • 路由参数指的是 URL 路径中的参数(数据)
	// 导入express包
	const express = require('express')
	// 创建应用对象
	const app = express()
	// 设置路由规则
	// :id占位符
	app.get('/:id', (req, res) => {
	    res.setHeader('content-type', "text/html;charset=utf-8")
	    res.end(`商品详情,商品的id为${req.params.id}`)
	})
	// params用来存储所有的路由参数
	// 监听端口,启动服务
	app.listen(9000, () => {
	    console.log('服务已启动,监听9000端口中......');
	})
	

3.5 路由参数练习

  • 要求:根据路由参数响应歌手的信息
	路径结构如下
	
	/singer/1.html
	
	显示歌手的`姓名``图片`
	
	//json文件
	{
	  "singers": [
	    {
	      "singer_name": "周杰伦",
	      "singer_pic": "http://y.gtimg.cn/music/photo_new/T001R150x150M0000025NhlN2yWrP4.webp",
	      "other_name": "Jay Chou",
	      "singer_id": 4558,
	      "id": 1
	    },
	    {
	      "singer_name": "林俊杰",
	      "singer_pic": "http://y.gtimg.cn/music/photo_new/T001R150x150M000001BLpXF2DyJe2.webp",
	      "other_name": "JJ Lin",
	      "singer_id": 4286,
	      "id": 2
	    },
	    {
	      "singer_name": "G.E.M. 邓紫棋",
	      "singer_pic": "http://y.gtimg.cn/music/photo_new/T001R150x150M000001fNHEf1SFEFN.webp",
	      "other_name": "Gloria Tang",
	      "singer_id": 13948,
	      "id": 3
	    },
	    {
	      "singer_name": "薛之谦",
	      "singer_pic": "http://y.gtimg.cn/music/photo_new/T001R150x150M000002J4UUk29y8BY.webp",
	      "other_name": "",
	      "singer_id": 5062,
	      "id": 4
	    }
	  ]
	}
  • 代码实现:
	// 导入express包
	const express = require('express')
	//导入json文件
	const { singers } = require('./singers.json')
	// 创建应用服务
	const app = express()
	// 设置路由规则
	app.get('/singer/:id.html', (req, res) => {
	    let { id } = req.params
	    let result = singers.find(item => {
	        if (item.id === Number(id)) {
	            return true
	        }
	    })
	    if (!result) {
	        req.statusCode = 404
	        res.end('404 Not Found')
	        return
	    }
	    res.end(`
	    <!DOCTYPE html>
	    <html lang="en">
	    <head>
	        <meta charset="UTF-8">
	        <meta http-equiv="X-UA-Compatible" content="IE=edge">
	        <meta name="viewport" content="width=device-width, initial-scale=1.0">
	        <title>Document</title>
	    </head>
	    <body>
	        <div>${result.singer_name}</div>
	        <div><img src="${result.singer_pic}" alt=""></div>
	    </body>
	    </html>`)
	
	    })
	//监听端口,启动服务
	app.listen(9000, () => {
		 console.log('服务已启动,监听9000端口中.....');
		})

4、express 响应设置

  • express 框架封装了一些 API 来方便给客户端响应数据,并且兼容原生 HTTP 模块的获取方式
	// 导入express包
	const express = require('express')
	// 创建应用对象
	const app = express()
	// 设置路由规则
	
	app.get('/response', (req, res) => {
	    /*  
	    // 1. express 中设置响应的方式兼容 HTTP 模块的方式
	     // 设置状态码
	     res.statusCode = 404
	     // 设置响应状态码描述
	     res.statusMessage = 'I love you'
	     // 设置响应头
	     res.setHeader('server','Node.js')
	     // 设置响应体
	     res.write('I love love love ')
	     res.end(`hello response`) */
	    //2. express 的响应方法
	    // 设置响应状态码
	    /* res.status(404)
	    // 设置响应头
	    res.set('server','Node.js')
	    // 设置响应体
	    res.send('I love you 我爱你') */
	    //send会自动加上Content-Type: text/html; charset=utf-8解决中文乱码问题
	    // 这些方法可以进行连贯操作
	    res.status(404).set('server','Node.js').send('I love you 我爱你')
	    //3. 其他响应
	})
	// 监听端口,启动服务
	app.listen(9000, () => {
	    console.log('服务已启动,监听9000端口中......');
	})
	
  • 其他响应
	// 导入express包
	const express = require('express')
	const path = require('path')
	// 创建应用对象
	const app = express()
	// 设置路由规则
	app.get('/response', (req, res) => {
	    //其他响应
	    // 1.重定向也称//跳转响应
	    // res.redirect('http://baidu.com')
	    //2.下载响应
	    // res.download(path.resolve(__dirname + '/1.html'))
	    //3.响应JSON
	    /* res.json({
	        name: '张三',
	        age: 18
	    }); */
	    //4.响应文件内容
	    res.sendFile(path.resolve(__dirname + '/1.html'))
	})
	// 监听端口,启动服务
	app.listen(9000, () => {
	    console.log('服务已启动,监听9000端口中......');
	})
	

5、express 中间件

5.1 什么是中间件

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

5.2 中间件的作用

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

5.3 中间件的类型

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

5.4 全局中间件

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

5.4.1定义全局中间件

  • 声明中间件函数
		let recordMiddleware = function(request,response,next){
		//实现功能代码
		//.....
		//执行next函数(当如果希望执行完中间件函数之后,仍然继续执行路由中的回调函数,必须调用next)
		next();
		}

在这里插入图片描述

  • 应用中间件
	app.use(recordMiddleware);
  • 声明时可以直接将匿名函数传递给 use
	app.use(function (request, response, next) {
	console.log('定义第一个中间件');
	next();
	})

5.4.2 多个全局中间件

  • express 允许使用 app.use() 定义多个全局中间件
	app.use(function (request, response, next) {
	console.log('定义第一个中间件');
	next();
	})
	app.use(function (request, response, next) {
	console.log('定义第二个中间件');
	next();
	})

5.4.3 具体实现全局中间件

// 导入express包
const express = require('express')
const path = require('path')
const fs = require('fs')
// 创建应用对象
const app = express()
// 声明全局中间件函数
function recordMiddleware(req, res, next) {
    // 记录url和ip
    let { url, ip } = req;
      //将信息保存在文件中 access.log日志里面
    fs.appendFileSync(path.resolve(__dirname + '/access.log'), `${new Date().toLocaleString()}  ${url} ${ip}\r\n`)
    next()
}
//调用全局中间件函数
app.use(recordMiddleware)
// 设置路由规则
app.get('/home', (req, res) => {
    res.send('前台首页')
})
app.get('/admin', (req, res) => {
    res.send('后台首页')
})
app.all('*', (req, res) => {
    res.send('<h1>404NotFound</h1>')
})
// 监听端口,启动服务
app.listen(9000, () => {
    console.log('服务已启动,监听9000端口中......');
})

5.5 路由中间件

  • 如果 只需要对某一些路由进行功能封装 ,则就需要路由中间件

5.5.1 定义路由中间件

  • 要求:针对 /admin /setting 的请求, 要求 URL 携带 code=521 参数, 如未携带提示『暗号错误』
  • 具体实现:
	
	//导入 express
	const express = require('express');
	
	//创建应用对象
	const app = express();
	
	//创建路由
	app.get('/home', (req, res) => {
	    res.send('前台首页');
	});
	
	//声明路由中间件
	function routeMiddleware(req, res, next) {
	    if (req.query.code === '521') {
	        next()
	    } else {
	        res.send('暗号错误')
	    }
	}
	
	//后台
	app.get('/admin', routeMiddleware, (req, res) => {
	    res.send('后台首页');
	});
	
	//后台设置
	app.get('/setting', routeMiddleware, (req, res) => {
	    res.send('设置页面');
	});
	
	app.all('*', (req, res) => {
	    res.send('<h1>404 Not Found</h1>')
	})
	
	//监听端口, 启动服务
	app.listen(9000, () => {
	    console.log('服务已经启动, 端口 3000 正在监听中....')
	})
	

5.6 静态资源中间件

  • express 内置处理静态资源的中间件
	//引入express框架
	const express = require('express');
	//创建服务对象
	const app = express();
	//静态资源中间件的设置,将当前文件夹下的public目录作为网站的根目录
	app.use(express.static('./public')); //当然这个目录中都是一些静态资源
	//如果访问的内容经常变化,还是需要设置路由
	//但是,在这里有一个问题,如果public目录下有index.html文件,单独也有index.html的路由,
	//则谁书写在前,优先执行谁
	app.get('/index.html',(request,response)=>{
	respsonse.send('首页');
	});
	//监听端口
	app.listen(3000,()=>{
	console.log('3000 端口启动....');
	});

注意事项:
1. index.html 文件为默认打开的资源
2. 如果静态资源与路由规则同时匹配,谁先匹配谁就响应
3. 路由响应动态资源,静态资源中间件响应静态资源

5.6.1 静态资源中间件练习

  • 要求:局域网内可以访问品优购的网页

  • 品优购项目在我主页的资源里可以下载。

  • 文件目录

    在这里插入图片描述
    代码实现:

    //导入 express
    const express = require('express');
    //创建应用对象
    const app = express();
    //设置静态资源中间件
    app.use(express.static(__dirname + '/shoping'));
    //一句话搞定
    //监听端口, 启动服务
    app.listen(3000, () => {
      console.log('服务已经启动, 端口 3000 正在监听中....')
    })
    

在这里插入图片描述

只要在同一个局域网里都可以访问,不过要知道你本机的IP地址是多少。
我的IP地址是 192.168.154.16
如手机访问:192.168.154.16:3000就可以了,大家可自行测试。

5.7 获取请求体数据 body-parser

  • 获取请求体数据 body-parser
  • 第一步:安装
	npm i body-parse
  • 第二步:导入 body-parser 包
	const bodyParser = require('body-parser');
  • 第三步:获取中间件函数
	//处理 querystring 格式的请求体
	let urlParser = bodyParser.urlencoded({extended:false}));
	//处理 JSON 格式的请求体
	let jsonParser = bodyParser.json();
  • 第四步:设置路由中间件,然后使用 req.body 来获取请求体数据
	app.post('/login', urlParser, (req,res)=>{
	//获取请求体数据
	//console.log(req.body);
	//用户名
	console.log(req.body.username);
	//密码
	console.log(req.body.userpass);
	response.send('获取请求体数据');
	});
  • 获取到的请求体数据:
	[Object: null prototype] { username: 'admin', userpass: '123456' }

5.7.1 练习

  • 要求:
	 * 按照要求搭建 HTTP 服务
	 * GET   /login  显示表单网页
	 * POST  /login  获取表单中的『用户名』和『密码』
  • 代码实现:
	// 导入express包
	const express = require('express')
	// 导入path模块
	const path = require('path')
	// 导入body-parser包
	const bodyParser = require('body-parser')
	//解析 JSON 格式的请求体的中间件
	// const jsonParser = bodyParser.json()
	//解析 querystring 格式请求体的中间件
	const urlencodedParser = bodyParser.urlencoded({ extended: false })
	// 创建应用对象
	const app = express()
	// 设置get路由规则
	app.get('/login', (req, res) => {
	    // res.send('表单页面')
	   //响应 HTML 文件内容
	    res.sendFile(path.resolve(__dirname + '/1.html'))
	})
	//设置post路由规则
	app.post('/login', urlencodedParser, (req, res) => {
	  //获取 用户名 和 密码
	  console.log(req.body);
	  res.send('获取用户的数据')
	});
	// 监听端口,启动服务
	app.listen(9000, () => {
	    console.log('服务已启动,监听端口9000中.....');
	})

6、防盗链

6.1 什么是防盗链

防盗链其实就是采用服务器端编程,通过url过滤技术实现的防止盗链的软件。

  • 比如:xxxxxxxxxxxxx 这个下载地址,如果没有装防盗链,别人就能轻而易举的在他的网站上引用这个地址。

6.2 防盗链的实现

  • 要实现防盗链,我们就必须先理解盗链的实现原理,提到防盗链的实现原理就不得不从HTTP协议说起,在HTTP协议中,有一个表头字段叫referer,采用URL的格式来表示从哪儿链接到当前的网页或文件。
  • 换句话说,通过referer,网站可以检测目标网页访问的来源网页,如果是资源文件,则可以跟踪到显示它的网页地址。
  • 有了referer跟踪来源就好办了,这时就可以通过技术手段来进行处理,一旦检测到来源不是本站即进行阻止或者返回指定的页面

6.3 具体实现

//导入 express
const express = require('express');

//创建应用对象
const app = express();

//声明中间件
app.use((req, res, next) => {
  //检测请求头中的 referer 是否为 127.0.0.1
  //获取 referer
  let referer = req.get('referer');
  console.log(referer);
  if(referer){
    //实例化,得到referer的url
    let url = new URL(referer);
    console.log(url);
    //获取 hostname
    let hostname = url.hostname;
    //判断
    if(hostname !== '127.0.0.1'){
      //响应 404 
      res.status(404).send('<h1>404 Not Found</h1>');
      return;
    }
  }
  next();
});

//静态资源中间件设置
app.use(express.static(__dirname + '/public'));

//监听端口, 启动服务
app.listen(9000, () => {
  console.log('服务已经启动, 端口 9000 正在监听中....')
})

7、Router

7.1 什么是 Router

  • express 中的 Router 是一个完整的中间件和路由系统,可以看做是一个小型的 app 对象。

7.2 Router 作用

  • 对路由进行模块化,更好的管理路由

7.3 Router 使用

  • 创建独立的 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;
	
  • 主文件
	const express = require('express');
	const app = express();
	//5.引入子路由文件
	const homeRouter = require('./routes/homeRouter');
	//6.设置和使用中间件
	app.use(homeRouter);
	app.listen(3000,()=>{
	console.log('3000 端口启动....');
	})

8、EJS 模板引擎

8.1 什么是模板引擎

  • 模板引擎是分离 用户界面和业务数据 的一种技术
  • 简单来说就是:分离HTML和JS

注:分离的是服务端的JS而不是浏览器端的JS

8.2 什么是 EJS

  • EJS 是一个高效的 Javascript 的模板引擎
    • 官网: https://ejs.co/
    • 中文站:https://ejs.bootcss.com/

8.3 EJS 初体验

  • 下载安装EJS

    npm i ejs --save
    

    代码示例:
    html文件

	<!DOCTYPE html>
	<html lang="en">
	<head>
	  <meta charset="UTF-8">
	  <meta http-equiv="X-UA-Compatible" content="IE=edge">
	  <meta name="viewport" content="width=device-width, initial-scale=1.0">
	  <title>Document</title>
	</head>
	<body>
	  //<%= %> 是ejs解析内容的标记,作用是输出当前表达式的执行结构
	  <h2>我爱你 <%= china %></h2>
	  <p><%= weather %></p>
	</body>
	</html>
`js文件`
	 //1. 安装 EJS
	//2. 导入 EJS
	const ejs = require('ejs');
	const fs = require('fs');
	//字符串
	let china = '中国';
	let weather = '今天天气不错~';
	//声明变量
	let str = fs.readFileSync('./01_html.html').toString();
	//使用 ejs 渲染
	let result = ejs.render(str, {china, weather});
	console.log(result);

8.4 EJS 常用语法

  • 执行JS代码

    <% code %>
    
  • 输出转义的数据到模板上

    <%= code %>
    
  • 输出非转义的数据到模板上

    <%- code %>
    

8.5 EJS 渲染列表

  • js文件
	// 导入ejs包
	const ejs = require('ejs')
	//西游记
	const xy = ['唐僧', '孙悟空', '猪八戒', '沙僧'];
	/* // 原生js渲染
	let str = `<ul>`
	xy.forEach(item => {
	    str += `<li>${item}</li>`
	})
	str += '</ul>'
	console.log(str); */
	
	// ejs渲染
	/* let html = ejs.render(`
	<ul>
	<% xy.forEach(item=>{%>
	    <Li><%= item%></Li>
	<%})%>
	</ul>`,{xy})
	console.log(html); */
	//外链HTML文件ejs实现
	const fs = require('fs');
	let html = fs.readFileSync('./02.html').toString()
	let result = ejs.render(html, { xy })
	console.log(result);
  • html文件
	<!DOCTYPE html>
	<html lang="en">
	
	<head>
	    <meta charset="UTF-8">
	    <meta http-equiv="X-UA-Compatible" content="IE=edge">
	    <meta name="viewport" content="width=device-width, initial-scale=1.0">
	    <title>Document</title>
	</head>
	
	<body>
	    <ul>
	        <% xy.forEach(item=>{%>
	            <Li>
	                <%= item%>
	            </Li>
	            <%})%>
	    </ul>
	</body>
	
	</html>

8.6 ejs条件渲染

  • 要求:
	 * 通过 isLogin 决定最终的输出内容
	 * true   输出『<span>欢迎回来</span>* false  输出『<button>登录</button>  <button>注册</button>
  • 代码实现:

  • js文件

	// 导入ejs包
	const ejs = require('ejs')
	const fs = require('fs')
	let isLogin = true
	/* // 原生js渲染
	if (isLogin) {
	    console.log(`<span>欢迎回来</span>`);
	} else {
	    console.log(`<button>登录</button>  <button>注册</button>`);
	} */
	// ejs实现
	
	/* let html = ejs.render(`
	<%if(isLogin) {%>
	    <span>欢迎回来</span>
	    <%}else {%>
	        <button>登录</button>  <button>注册</button>
	    <%}%>
	`,{isLogin:isLogin})
	console.log(html); */
	// 外链HTML ejs实现
	let body = fs.readFileSync('./03.html').toString()
	let html = ejs.render(body,{isLogin:isLogin})
	console.log(html); 
  • html文件
	<!DOCTYPE html>
	<html lang="en">
	
	<head>
	    <meta charset="UTF-8">
	    <meta http-equiv="X-UA-Compatible" content="IE=edge">
	    <meta name="viewport" content="width=device-width, initial-scale=1.0">
	    <title>Document</title>
	</head>
	
	<body>
	    <%if(isLogin) {%>
	        <span>欢迎回来</span>
	        <%}else {%>
	            <button>登录</button> <button>注册</button>
	            <%}%>
	</body>
	
	</html>

8.7 express中使用ejs

  • js文件
	//导入 express
	const express = require('express');
	//导入 path
	const path = require('path');
	//创建应用对象
	const app = express();
	//1. 设置模板引擎
	app.set('view engine', 'ejs');// pug  twing
	//2. 设置模板文件存放位置   模板文件: 具有模板语法内容的文件
	app.set('views', path.resolve(__dirname, './view'));
	
	//创建路由
	app.get('/home', (req, res) => {
	  //3. render 响应
	  // res.render('模板的文件名', '数据');
	  //声明变量
	  let title = '云翔集团 - 让天下没有难学的技术';
	  res.render('home', {title});
	  //4. 创建模板文件
	});
	
	//监听端口, 启动服务
	app.listen(9000, () => {
	  console.log('服务已经启动, 端口 9000 正在监听中....')
	})
  • ejs文件
	<!DOCTYPE html>
	<html lang="en">
	<head>
	  <meta charset="UTF-8">
	  <meta http-equiv="X-UA-Compatible" content="IE=edge">
	  <meta name="viewport" content="width=device-width, initial-scale=1.0">
	  <title>Document</title>
	</head>
	<body>
	  <h2><%= title %></h2>
	</body>
	</html>

9、Express 应用程序生成器

  • 通过应用生成器工具 express-generator 可以快速创建一个应用的骨架。

  • 详情介绍官网里面都有:https://www.expressjs.com.cn/starter/generator.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/15377.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Linux 利用网络同步时间

yum -y install ntp ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime ntpdate ntp1.aliyun.com 创建加入crontab echo "*/20 * * * * /usr/sbin/ntpdate -u ntp.api.bz >/dev/null &" >> /var/spool/cron/rootntp常用服务器 中国国家授…

活动目录(Active Directory)安全审计

延迟响应变化的影响可能会使原本应该微不足道的颠簸滚雪球变成无法弥补的损害。这在 Windows Active Directory 环境中更为重要&#xff0c;因为这种延迟造成的损害可能会使组织损失数百万美元&#xff01;在这种情况下&#xff0c;需要一个警惕的警报系统&#xff0c;该系统可…

(下)苹果有开源,但又怎样呢?

一开始&#xff0c;因为 MacOS X &#xff0c;苹果与 FreeBSD 过往从密&#xff0c;不仅挖来 FreeBSD 创始人 Jordan Hubbard&#xff0c;更是在此基础上开源了 Darwin。但是&#xff0c;苹果并没有给予 Darwin 太多关注&#xff0c;作为苹果的首个开源项目&#xff0c;它算不上…

【多线程】线程安全问题

1. 一段线程不安全的代码 我们先来看一段代码&#xff1a; public class ThreadDemo {public static int count 0;public static void main(String[] args) {for (int i 0; i < 10_0000; i) {count;}System.out.println("count " count);} } // 打印结果&…

MySql中执行计划如何来的——Optimizer Trace | 京东云技术团队

作者&#xff1a;京东物流 籍磊 1.前言 当谈到MySQL的执行计划时&#xff0c;会有很多同学想&#xff1a;“我就觉得使用其他的执行方案比EXPLAIN语句输出的方案强&#xff0c;凭什么优化器做的决定与我得不一样&#xff1f;”。这个问题在MySQL 5.6之前或许自己很难解决&…

滑动奇异频谱分析:数据驱动的非平稳信号分解工具(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

每天一道算法练习题--Day15 第一章 --算法专题 --- -----------二叉树的遍历

概述 二叉树作为一个基础的数据结构&#xff0c;遍历算法作为一个基础的算法&#xff0c;两者结合当然是经典的组合了。很多题目都会有 ta 的身影&#xff0c;有直接问二叉树的遍历的&#xff0c;有间接问的。比如要你找到树中满足条件的节点&#xff0c;就是间接考察树的遍历…

【Java校招面试】基础知识(一)——Java常用类库

目录 前言一、编程时常用的Java类库1. 异常捕获模块(try-catch-finally, Error, Exception)2. boolean / short / int / long / float / double / char / byte及其对应的引用类型 二、面试时常考的Java类库1. 一切类型的父类Object及其equals / hashCode / toString方法2. 常用…

scratch拆礼物游戏 中国电子学会图形化编程 少儿编程 scratch编程等级考试三级真题和答案解析2023年3月

目录 scratch拆礼物游戏 一、题目要求 1、准备工作 2、功能实现 二、案例分析 <

perf工具报错,升级ubuntu子系统linux内核

文章目录 1&#xff0c;运行perf工具报错1.1&#xff0c;可能的原因有&#xff1a; 2&#xff0c;我选择升级linux内核&#xff0c;和当前perf工具版本保持一致2.1&#xff0c;下载6.2.12内核源码2.2&#xff0c;安装6.2.12内核 1&#xff0c;运行perf工具报错 1.1&#xff0c;…

网络安全基础入门学习路线

在大多数的思维里总觉得学习网络安全得先收集资料、学习编程、学习计算机基础&#xff0c;这样不是不可以&#xff0c;但是这样学效率太低了&#xff01; 你要知道网络安全是一门技术&#xff0c;任何技术的学习一定是以实践为主的。也就是说很多的理论知识其实是可以在实践中…

十、ElasticSearch 实战 - 源码运行

一、概述 想深入理解 Elasticsearch&#xff0c;了解其报错机制&#xff0c;并有针对性的调整参数&#xff0c;阅读其源码是很有必要的。此外&#xff0c;了解优秀开源项目的代码架构&#xff0c;能够提高个人的代码架构能力 阅读 Elasticsearch 源码的第一步是搭建调试环境&…

Qt5下Qxlsx模块安装及使用

Qt5下Qxlsx模块安装及使用 一、Qt5下Qxlsx模块安装及使用1. 未安装Qxlsx的程序效果2. 安装Perl&#xff08;编译Qxlsx源码用&#xff09;2.1 下载 ActivePerl 5.282.2 安装 ActivePerl 5.28 3. 下载并编译Qxlsx源码3.1 下载Qxlsx源码3.2 编译Qxlsx源码 4. 将编译好的文件复制到…

26- OCR 基于PP-OCRv3的液晶屏读数识别

要点&#xff1a; 液晶屏识别示例github 地址 1. 简介 本项目基于PaddleOCR开源套件&#xff0c;以PP-OCRv3检测和识别模型为基础&#xff0c;针对液晶屏读数识别场景进行优化。主要是针对各种仪表进行识别&#xff1a; 2 安装环境 安装Git&#xff1a;Git 详细安装教程 # 首…

Git基础

文章目录 1. Git基础1.1 版本管理1.1.1 什么是版本管理1.1.2 人为维护文档版本的问题 1.2 Git 是什么1.3 Git 安装1.4 Git基本工作流程1.5 Git 的使用1.5.1 Git 使用前配置1.5.2 提交步骤1.5.3 撤销 2. Git进阶2.1 分支2.1.1 分支细分2.1.2 分支命令 2.2 暂时保存更改 1. Git基…

鸿蒙Hi3861学习三-第一个实例程序Hello_world

一、简介 前两章介绍了环境搭建、烧录和编译。这一节&#xff0c;来介绍实现第一个经典代码“hello world”。 先介绍小熊派的目录结构&#xff0c;该目录结构延续了OpenHarmony官方目录结构。 二、实操 1.搭建代码架构 1).新建项目文件夹hello_world cd bearpi-hm_nano/appli…

【VM服务管家】VM4.0平台SDK_2.3 控件嵌入类

目录 2.3.1 渲染结果&#xff1a;通过绑定流程或模块获取渲染结果的方法2.3.2 渲染控件&#xff1a;渲染控件加载本地图像的方法2.3.3 渲染控件&#xff1a;渲染控件上自定义图形的方法2.3.4 参数控件&#xff1a;参数配置控件绑定模块的方法2.3.5 控件颜色&#xff1a;控件颜色…

Java新提案,最终还是靠近C#了

Java是一门非常优秀的编程语言&#xff0c;特别是生态繁荣&#xff0c;成熟的轮子很多&#xff0c;各种解决方案都有&#xff0c;要开发一个项目&#xff0c;只需把轮子组装&#xff0c;并根据自己的项目&#xff0c;进行自定义修改&#xff0c;可以极大地提升开发效率。 曾经…

【算法】【算法杂谈】判断点是否在三角形内部(面积法和向量法)

目录 前言问题介绍解决方案代码编写java语言版本c语言版本c语言版本 思考感悟写在最后 前言 当前所有算法都使用测试用例运行过&#xff0c;但是不保证100%的测试用例&#xff0c;如果存在问题务必联系批评指正~ 在此感谢左大神让我对算法有了新的感悟认识&#xff01; 问题介…

react-antd-procomponents组件库 ProTable表格实现跨页多选。

table表格多选时所需要的api 1.onSelect - 单行选择(用户手动选择/取消选择某行的回调) 2.onSelectMultiple - 多行选择&#xff08;用户使用键盘 shift 选择多行的回调&#xff09; 3.onSelectAll - 全选全不选(用户手动选择/取消选择所有行的回调) 4.onChange - 每次选择行都…