欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Node.js从入门到放弃(四)

程序员文章站 2022-04-30 20:18:07
...

Node.js从入门到放弃(四)

前言

这是该系列文章的第四篇,主要介绍如何使用express+模板引擎做一个完整的案例

模板引擎

模板引擎是为了使用户界面与业务数据(内容)分离而产生的,最初源自服务端,后来发展到前端。如果你学过java,应该知道jsp,用过springboot 应该知道thyemleaf,这都属于模板引擎。当然,这东西现在不是很火了,对前端而言,react,angular,vue的出现,是根本上的变革,react以js为模板,vue和angular以html为模板。目前主流的模板引擎有underscore,art-template,jade,ejs… 使用方法大同小异,这里只介绍art-template

art-template

这里举个例子,简单介绍下art-template在node中的应用

  • 项目初始化:新建一个项目,进入后输入npm init -y
  • 安装: npm i art-template
  • 根目录写下新建index.html(名称可自定义),写入如下内容
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>title</title>
</head>
<body>

     <p>姓名->{{ name }}</p>
     <p>年龄 ->{{ age }} 岁</p>
     <p>涉猎语言->{{each language}} {{ $value }} {{/each}}</p>

</body>
</html>

  • 根目录写下新建app.js(名称可自定义),写入如下内容
var template = require('art-template')//加载模板引擎
var fs = require('fs')//加载fs文件操作模块
//读取html文件
fs.readFile('index.html', function (err, data) {//引入模板文件
  if (err) {
    return console.log('读取文件失败');
  }
  //模板引擎不支持二进制,需要转成字符串
  var result = template.render(data.toString(), {//用render方法填充数据
    name: '冷月心',
    age: 18,
    language: [
      'JAVA',
      'PHP',
      'Node.js'
    ]
  })

  console.log(result)
})

  • 运行node app.js
  • 效果图

Node.js从入门到放弃(四)

  • 可以看到,我们填充的数据都被渲染出来了,这就是模板引擎

综合案例

下面写一个综合小案例,先简单罗列下涉及的点,做到心中有数

  • 工程规范
  • 模板引擎和express整合,数据渲染
  • 中间件处理post请求
  • 404拦截处理
  • 忽略favicon.ico请求
  • 路由配置
  • 静态资源开放
  • 文件上传
  • 文件下载
  • 路由重定向
  • 其他…

step 1–工程目录

Node.js从入门到放弃(四)

step2–依赖安装

npm i express
npm i art-template  express-art-template 
npm i formidable //处理post请求和文件上传

step3–整合配置

这里主要干了五件事,整合模板引擎,导入并挂载路由,404拦截,忽略favicon.ico请求,开放静态资源

app.js

//1. 引包
const express = require('express')
//2. 获取服务器对象
const app = express()
//3. 引入路由
const router = require("./routes")
//4. 整合模板引擎
app.engine('html', require('express-art-template'))

//5. 开放静态资源
app.use(express.static("public"))

//6. 挂载路由
app.use(router)

//7. 404拦截 写在最后一个路由后边


app.use( (req, res)=> {
  if(req.url==="/favicon.ico") {
    res.send(null)
  } else{
    res.render("404.html")
  }
})

//设置监听
app.listen(3000, () => {
  console.log('run server___')
})



routes/index.js

这里是路由配置的细节

//引入express formidable
const express = require("express");
const formidable = require('formidable');
//创建路由实例
const router = express.Router()

//路由配置--渲染首页
router.get('/', (req, res) => {
    //注意,这个index.html直接对应views文件夹下的index.html
    res.render('index.html', {
        title: "hello world"
    });
})

//路由配置--渲染form表单
router.get('/form', (req, res) => {
    res.render('form.html');
})

//路由配置--渲染form表单
router.get('/backHome', (req, res) => {
    //重定向到首页
    res.redirect("/")
})



//路由配置--处理form表单的post请求,并将处理后数据渲染到show.html
router.post('/post', (req, res) => {
    const form = new formidable.IncomingForm();

    form.parse(req, (err, fields, files) => {

        res.render('show.html', {
            fields
        });
    })
})



//导出路由
module.exports = router

此时的项目目录

Node.js从入门到放弃(四)

  • index.html
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>index</title>
</head>

<body>

    <h2>{{title}}</h2>

    <!-- 注意,这时候的链接是后端路由 -->
    <a href="/form">点击去填写form表单</a>
</body>

</html>


  • 404.html
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>404</title>
</head>

<body>

    404 not found
</body>

</html>


  • show.html

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>show</title>
</head>

<body>

    <h2>数据渲染</h2>
    <div>
        <p>name--{{fields.name}}</p>
        <p>age--{{fields.age}}</p>
        <!-- 其实可以直接href="/",这里是为了演示重定向 -->
        <a href="/backHome">返回首页</a>
    </div>
</body>

</html>
  • form.html
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>form</title>
</head>

<body>
    <h2>填写表单</h2>
    <!-- 这里/post也对应后端路由 -->
    <form action="/post" method="POST">
        <p> <input type="text" name="name" value="冷月心"></p>
        <p> <input type="text" name="age" value="18"></p>
        <input type="submit" value="提交">
    </form>
</body>
</html>

step4–测试逻辑

  • 访问根目录,跳转到首页/

Node.js从入门到放弃(四)

  • 点击链接,跳转到/form

Node.js从入门到放弃(四)

  • 点击提交,表单数据在/show显示

Node.js从入门到放弃(四)

  • 点击返回首页,跳转到首页/

  • 静态资源开放,访问/avatar.jpg,显示图片
    Node.js从入门到放弃(四)

step5–上传下载

到这里功能点就实现了一大半,剩下的是上传和下载,先介绍上传

  • views下新建upload.html,写入如下内容

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>upload</title>
</head>

<body>
    <h2>文件上传</h2>
    <form action="/upload" method="POST" enctype="multipart/form-data">
        <p> <input type="file" name="pic"></p>
        <input type="submit" value="上传">
    </form>
</body>

</html>
  • 后台接口处理

//路由配置--渲染上传表单
router.get('/upload', (req, res) => {

    res.render("upload.html")
})

// 路由配置--处理文件上传
router.post('/upload', (req, res) => {
    const fs = require('fs');
    const path = require('path');

    const form = new formidable.IncomingForm();
    //设置文件上传存放地址
    form.uploadDir = "./public";
    //保持拓展名
    form.keepExtensions = true;
    //执行里面的回调函数的时候,表单已经全部接收完毕。
    form.parse(req, (err, fields, files) => {

        //可以在这里改个名
        const oldpath = path.resolve(__dirname, "../public/" + path.basename(files.pic.path));
        const newpath = path.resolve(__dirname, "../public/" + files.pic.name)

        fs.renameSync(oldpath, newpath)

        if (err) {
            res.send("上传失败", err.message)
            return
        } else {
            res.send("上传成功")
        }



    });
})



  • 访问/upload,,选择一张图片

Node.js从入门到放弃(四)

  • 上传效果图

Node.js从入门到放弃(四)


Node.js从入门到放弃(四)

文件下载

到这里就是最后一个功能点了,下载的逻辑其实很好实现,views下新建download.html

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>download</title>
</head>

<body>

    <a href="/downAvatar">点我下载avatar.jpg</a>


</body>

</html>

  • 后台编写 downAvatar接口

//路由配置--下载头像
router.get('/downAvatar', (req, res) => {
    const path = require("path")
    res.download(path.resolve(__dirname, "../public/avatar.jpg"), (err) => {
        if (err) {
            res.send("下载失败")
        }
    })
})

  • 测试,访问/download

Node.js从入门到放弃(四)

  • 点击

Node.js从入门到放弃(四)