09-Node.js—express框架

news2024/11/26 14:41:31

目录

  • 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端口中');
      })
      
    2. 命令行下执行该脚本

      node <文件名>
      # 或者
      nodemon <文件名>
      
    3. 然后在浏览器就可以访问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

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

echarts 环形图_圆环动画

Echarts 常用各类图表模板配置 注意&#xff1a; 这里主要就是基于各类图表&#xff0c;更多的使用 Echarts 的各类配置项&#xff1b; 以下代码都可以复制到 Echarts 官网&#xff0c;直接预览&#xff1b; 图标模板目录 Echarts 常用各类图表模板配置一、环形动画二、环形图…

(原创)Flutter基础入门:手把手教你搭建Flutter混合项目:AAR方式集成

前言 上一篇博客讲了如何用“模块代码依赖模式”这种方式去搭建Flutter混合项目 因为篇幅原因&#xff0c;AAR集成方式来搭建项目的步骤和注意点放到这篇博客来讲 如果你没看过上篇博客&#xff0c;建议先阅读上一篇&#xff1a; &#xff08;原创&#xff09;Flutter基础入门…

快来看看这些前端开发技巧你掌握多少吧

文章目录 一、代码整洁推荐1.1 三元(三目)运算符1.2 短路判断简写1.3 变量声明简写1.4 if真值判断简写1.5 For循环简写1.6 对象属性简写1.7 箭头函数简写1.8 隐式返回简写1.9 模板字符串1.10 默认参数值1.11 解构赋值简写1.12 多条件判断简写1.13 多变量赋值简写1.14 解构时重命…

easyExcel动态导出,合并指定单元格

如上图所示&#xff0c;需要使用easyExcel动态导出上述表格并指定合并其中的单元格&#xff0c;日期是动态的&#xff0c;每个月不相同&#xff0c;直接上实现代码&#xff0c;以demo形式展现&#xff0c;更好理解 /** * 考勤记录动态导出测试 */ GetMapping(&q…

【Kotlin学习】R2DBC与MyBatis性能对比

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、测试框架选取Spring Webflux VS Spring MVCSpring Data R2DBC VS MyBatis 二、测试代码编写1. 项目1核心代码1.1 引入依赖1.2 接口代码 2. 项目2核心代码2.…

Layui图片上传

前端代码&#xff1a; <div class"layui-upload"> <button type"button" class"layui-btn" id"test1">上传图片</button> <div class"layui-upload-list"> <img class"lay…

如何一次性生成大量结构相同、内容不同的二维码

使用 批量模板数据 的方式&#xff0c;可 一次性生成大量结构相同&#xff0c;内容不同的活码 &#xff0c;大幅提升制码效率。 模板的样式&#xff0c;关联的表单状态等所有内容均可进行修改&#xff0c;修改后所有子码都将批量更新&#xff0c;且模板可重复使用&#xff0c;让…

页面加载进度条(VUE3)

通常我们希望在页面跳转加载中&#xff0c;页面顶部出现进度条。 &#xff08;1&#xff09; 下载依赖 npm install nprogress --save &#xff08;2&#xff09;在router中得index.js中引入 import NProgress from nprogress import nprogress/nprogress.css &#xff08;…

C++——类和对象(2)

作者&#xff1a;几冬雪来 时间&#xff1a;2023年4月25日 内容&#xff1a;C类和对象讲解 目录 前言&#xff1a; 1.this指针&#xff1a; 2.默认成员函数&#xff1a; 3.构造函数&#xff1a; 4.析构函数&#xff1a; 5.构造函数的问题&#xff1a; 结尾&#xff…

Transformer 代码详细解析

Transformer 代码详细解析 文章目录 Transformer 代码详细解析一、Transformer 背景介绍1.1 Transformer 的诞生1.2 Transformer 的优势1.3 Transformer 的市场 二、Transformer架构解析2.1 认识 Transformer 架构2.1.1 Transformer模型的作用2.1.2 Transformer 总体架构图 2.2…

全国计算机等级三级网络技术试卷详解(一)

请点击↑关注、收藏&#xff0c;本博客免费为你获取精彩知识分享&#xff01;有惊喜哟&#xff01;&#xff01; 1.下列关于RPR技术的描述中&#xff0c;错误的是&#xff08;&#xff09;。 A) RPR与FDDI一样使用双环结构 B) 在RPR环中&#xff0c;源节点向目的节点成功发出…

2023常用的10款电力电子系统仿真分析软件推荐

市场上有许多电子仿真器&#xff0c;那么对于电力电子项目来说&#xff0c;哪种仿真器最好呢&#xff1f;或者因为期望任何软件包在各个方面都是最好的是不合理的&#xff0c;那么用户如何确定哪个软件是项目的最佳选择&#xff1f; PSIM PSIM是一种模块化封装&#xff0c;专为…

华为认证实验篇-ENSP的安装(附下载地址)

ENSP&#xff08;Enterprise Network Simulation Platform&#xff09;是华为公司开发的一款网络仿真软件&#xff0c;它可以帮助网络工程师进行网络拓扑设计、网络配置、网络测试等工作。本篇文章将介绍如何在Windows操作系统上安装ENSP。后续会在专栏陆续更新ENSP的实验&…

MACH SYSTEMS操作手册 SAEJ2716(SENT) to RS-232/CAN Gateway怎么使用?

双通道SAE J2716 (SENT)至RS-232/CAN总线网关&#xff0c;具有两个双向SENT通道和RS-232 (SENT-RS232) 或CAN总线 (SENT-CAN) 接口。两种变体还提供两个模拟输出&#xff0c;可以直接将输入SENT数据转换为模拟电压。该网关配备了一个免费的PC应用程序&#xff0c;用于SENT通信分…

VS同时调试主程序和子程序工具

VS要想要实现同时调试主程序和子程序&#xff0c;可使用工具 Microsoft Child Process Debugging power Tool 来实现。 我的环境和官方使用说明 环境&#xff1a;VS2019 官方使用说明&#xff1a;Introducing the Child Process Debugging Power Tool - Azure DevOps Blogh…

Swagger 版本控制 注释展示(.NET)

版本控制 项目创建 以Visual Studio 2022为例&#xff0c;创建Web API项目&#xff0c;如下图所示。 在创建时勾选启用OpenAPI支持&#xff0c;默认安装Swashbuckle.AspNetCore库&#xff0c;并配置相关信息。 创建版本枚举类 /// <summary>/// 版本枚举/// </su…

新版Fluent默认保存的h5文件无法用Tecplot打开的解决办法(亲试有效,评论区是重点)

文章目录 Ansys Fluent简介Fluent 输入/出 文件格式新版Fluent的输出压缩文件&#xff08;.cas.h5文件&#xff09;解决办法 Ansys Fluent简介 Ansys Fluent &#xff0c;是国际上比较流行的商用CFD软件包&#xff0c;在美国的市场占有率为60%&#xff0c;凡是和流体、热传递和…

IP地址的分配

一、ip地址的作用 用IP地址来标识Internet的主机&#xff1b;IP协议可以根据路由选择协议提供的路由信息对IP数据报进行转发&#xff0c;直至抵达目的主机。IP地址和MAC地址的匹配&#xff1b;数据链路层使用MAC地址来发送数据帧&#xff0c;因此在实际发送IP报文时&#xff0…

分布式消息队列Kafka(四)- 消费者

1.Kafka消费方式 2.Kafka消费者工作流程 &#xff08;1&#xff09;总体工作流程 &#xff08;2&#xff09;消费者组工作流程 3.消费者API &#xff08;1&#xff09;单个消费者消费 实现代码 package com.zrclass.kafka.consumer; import org.apache.kafka.clients.consum…

【Golang项目实战】手把手教你写一个备忘录程序|附源码——建议收藏

博主简介&#xff1a;努力学习的大一在校计算机专业学生&#xff0c;热爱学习和创作。目前在学习和分享&#xff1a;数据结构、Go&#xff0c;Java等相关知识。博主主页&#xff1a; 是瑶瑶子啦所属专栏: Go语言核心编程近期目标&#xff1a;写好专栏的每一篇文章 前几天瑶瑶子…