评论

收藏

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

开发技术 开发技术 发布于:2021-07-08 15:32 | 阅读数:335 | 评论:0

  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)})
DSC0000.png 运行node app.js效果图  可以看到,我们填充的数据都被渲染出来了,这就是模板引擎
综合案例
  下面写一个综合小案例,先简单罗列下涉及的点,做到心中有数


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

DSC0001.png 工程目录  step2--依赖安装
npm i expressnpm 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 formidableconst 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.htmlrouter.post('/post', (req, res) => {    const form = new formidable.IncomingForm();    form.parse(req, (err, fields, files) => {        res.render('show.html', {            fields        });    })})//导出路由module.exports = router
  此时的项目目录

DSC0002.png 项目目录

  •   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--测试逻辑

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

  •   点击链接,跳转到/form
DSC0004.png /form

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

  •   点击返回首页,跳转到首页/
  •   静态资源开放,访问/avatar.jpg,显示图片
    DSC0006.png avatar
  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,,选择一张图片
DSC0007.png /upload

  •   上传效果图
DSC0008.png 上传成功效果图 DSC0009.png 上传成功效果图  文件下载
  到这里就是最后一个功能点了,下载的逻辑其实很好实现,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
DSC00010.png /download

  •   点击
DSC00011.png 下载

  
关注下面的标签,发现更多相似文章