zoukankan      html  css  js  c++  java
  • 基于node.js的express框架的图书管理功能(1)

    1.准备工作:

    新建一个文件夹mybook

    准备一个入口文件:index.js

    初始化该项目:npm init -y

    安装需要的依赖的包:

    npm install express --save
    
    npm install art-template --save   //第三方中间件:模板引擎
    
    npm install body-parser --save  //对参数的处理,主要用于处理post参数
    
    npm install express-art-template --save

    2.功能模块:

    主要功能为:

    *添加图书

    *修改图书

    *删除图书

    将数据存储在json文件中,通过路由的路径分发功能实现对不同页面的处理

    目录结构如下:

    前端页面都存放在views目录下,注意views目录下的文件后缀都要改成(.art)取决于你设置模板引擎时的后缀。

    index.js是入口文件。

    data.json用来存放图书的数据。

    router.js是将路由模块的功能单独抽取出来作为一个独立的功能模块。

    services.js是将router.js中的回调函数功能全部抽取出来作为业务处理的功能模块。

    test目录下的功能是将data.json的数据转换为sql的insert语句,方便以后将数据转移到数据库中使用。

    入口文件index.js:

    /**
     * 图书管理功能-入口文件
     */
    const express = require('express');
    const tempalte = require('art-template');
    const bodyParser = require('body-parser');
    const path = require('path');
    const router = require('./router.js');
    const app = express();
    
    //启动静态资源服务,添加了一个虚拟路径/www
    app.use('/www',express.static('./public'));
    
    //设置模板引擎
    //1.设置模板的路径:设定views变量,意为视图存放的目录
    app.set('views',path.join(__dirname,'views'));
    //2.设置模板引擎:后缀名为art
    app.set('view engine','art');
    //3.使express兼容art-template
    app.engine('art',require('express-art-template'));
    
    //处理请求参数
    //挂载参数处理中间件
    app.use(bodyParser.urlencoded({extended:false}));
    //处理json格式的参数
    app.use(bodyParser.json());
    
    //启动服务器功能:1.配置路由  2.监听端口
    //配置路由
    app.use(router);
    //监听端口
    app.listen(3000,()=>{
        console.log('running...');
    });

     路由模块router.js:

    /**
     * 路由模块
     */
    const express = require('express');
    const router = express.Router();
    const service = require('./service.js');
    
    //路由处理:通过路由绑定路径
    //渲染主页
    //'/'表示根目录
    router.get('/',service.showIndex);
    //添加图书:跳转到添加图书的页面
    //跳转到虚拟路径:http://localhost:3000/toAddBook
    router.get('/toAddBook',service.toAddBook);
    //添加图书:提交表单
    router.post('/addBook',service.addBook);
    //跳转到编辑图书信息页面:跳转页面用get就可以
    router.get('/toEditBook',service.toEditBook);
    //编辑图书提交表单:修改页面用post提交
    router.post('/editBook',service.editBook);
    //删除图书信息
    router.get('/deleteBook',service.deleteBook);
    //必须导出,否则在index页面使用不了
    module.exports = router;

    业务模块services.js:

    /**
     * 业务模块
     */
    const data = require('./data.json');
    const path = require('path');
    const fs = require('fs');
    
    //自动生成图书编号(自增)
    let maxBookCode = () => {
        let arr = [];
        data.forEach(item => {
            arr.push(item.id);
        });
        return Math.max.apply(null,arr);
    }
    
    //把内存数据写入到文件
    let writeDataFile = (res) => {
        //需要把内存中的数据写入文件
        //JSON.stringify(data)仅传data一个参数的话,data.json文件是压缩形式的
        fs.writeFile(path.join(__dirname,'data.json'),JSON.stringify(data,null,4),(err) => {
            if(err){
                res.send('server err');  
            }
            //文件写入成功之后重新跳转到主页面
            res.redirect('/');
        });
    }
    
     //渲染主页面
     exports.showIndex = (req,res) => {
        res.render('index',{list:data});
     }
    
     //跳转到添加图书的页面
     exports.toAddBook = (req,res) => {
         //render将会根据views中的模板文件进行渲染,渲染的是空对象{}
         res.render('addBook',{});
     }
    
     //添加图书保存数据
     exports.addBook = (req,res) => {
         //获取表单数据
         let info = req.body;
         let book = {};
         for (const key in info) {
             book[key] = info[key];
         }
         book.id = maxBookCode()+1;
         data.push(book);
         //需要把内存中的数据写入文件
         writeDataFile(res);
     }
    
     //跳转到编辑页面
     exports.toEditBook = (req,res) => {
        let id = req.query.id;
        let book = null;
        data.forEach((item)=>{
            if(id == item.id){
                book = item;
                //break;
                //forEach循环中不能有break,用return终结即可
                return;
            }
        });
        //render将会根据views中的模板文件进行渲染,渲染的是对应图书的完整信息
        res.render('editBook',book);
     }
    
     //编辑图书更新数据:
     //1.先查询出对应的数据并渲染到页面上
     //2.然后再提交表单,再重新保存,写入文件
     //编辑的时候要告诉服务器编辑的是哪条数据
     exports.editBook = (req,res) => {
         //获取表单的数据
         let info = req.body;
         data.forEach((item)=>{
             if(info.id == item.id){
                 for (const key in info) {
                     item[key] = info[key];
                 }
                 return;
             }
         });
         //需要把内存中的数据写入文件
         writeDataFile(res);
     }
    
     //删除图书信息
     exports.deleteBook = (req,res) => {
         //先获取到传过来的id
         let id = req.query.id;
         data.forEach((item,index)=>{
             if(item.id == id){
                //删除数组的一项数据
                data.splice(index,1);  
             }
             return;
         });
         //需要把内存中的数据写入文件
         writeDataFile(res);
     }

    数据文件data.json:

    [
        {
            "id": "1",
            "name": "三国演义",
            "author": "罗贯中",
            "category": "文学",
            "desc": "一个杀伐纷争的年代"
        },
        {
            "id": "2",
            "name": "水浒传",
            "author": "施耐庵",
            "category": "文学",
            "desc": "108条好汉的故事"
        },
        {
            "id": "3",
            "name": "西游记",
            "author": "吴承恩",
            "category": "文学",
            "desc": "佛教与道教的斗争"
        },
        {
            "id": "4",
            "name": "红楼梦",
            "author": "曹雪芹",
            "category": "文学",
            "desc": "一个封建王朝的缩影"
        },
        {
            "name": "明朝那些事",
            "author": "当年明月",
            "category": "文学",
            "desc": "明朝的历史",
            "id": 5
        }
    ]

    图书管理页面index.art:

    <!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>图书管理功能</title>
        <link rel="stylesheet" type="text/css" href="/www/style.css">
    </head>
    <body>
        <div class="title">图书管理功能<a href="/toAddBook">添加图书</a></div>
        <div class="content">
            <table cellpadding="0" cellspacing="0">
                <thead>
                    <tr>
                        <th>编号</th>
                        <th>名称</th>
                        <th>作者</th>
                        <th>分类</th>
                        <th>描述</th>
                        <th>操作</th>
                    </tr>
                </thead>
                <tbody>
                {{each list}}
                    <tr>
                        <td>{{$value.id}}</td>
                        <td>{{$value.name}}</td>
                        <td>{{$value.author}}</td>
                        <td>{{$value.category}}</td>
                        <td>{{$value.desc}}</td>
                        <td><a href="/toEditBook?id={{$value.id}}">修改</a>|<a href="/deleteBook?id={{$value.id}}">删除</a></td>
                    </tr>
                    {{/each}}
                </tbody>
            </table>
        </div>
    </body>
    </html>

    添加图书页面addBook.art:

    <!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>添加图书</title>
    </head>
    <body>
        <form action="/addBook" method="post">
            名称:<input type="text" name="name"><br>
            作者:<input type="text" name="author"><br>
            分类:<input type="text" name="category"><br>
            描述:<input type="text" name="desc"><br>
            <input type="submit" value="提交"><br>
        </form>
    </body>
    </html>

    修改图书页面editBook.art:

    <!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>修改图书</title>
    </head>
    <body>
        <form action="/editBook" method="post">
            <input type="hidden" name="id" value="{{id}}">
            名称:<input type="text" name="name" value="{{name}}"><br>
            作者:<input type="text" name="author" value="{{author}}"><br>
            分类:<input type="text" name="category" value="{{category}}"><br>
            描述:<input type="text" name="desc" value="{{desc}}"><br>
            <input type="submit" value="提交"><br>
        </form>
    </body>
    </html>

    样式表:style.css

    .title{
        text-align: center;
        background-color: lightblue;
        height: 50px;
        line-height: 50px;
        font-size: 24px;
    }
    .content{
        background-color: lightgray;
        border-right: 1px solid blanchedalmond;
        border-bottom: 1px solid blanchedalmond;
    }
    .content table{
        width: 100%;
        text-align: center;
    }
    .content th,td{
        border-left: 1px solid blanchedalmond;
        border-top: 1px solid blanchedalmond;
        height: 40px;
        line-height: 40px;
    }

    初始化sql语句文件initsql.js:

    /**
     * 把data.js文件中的数据拼接成insert语句
     */
    const path = require('path');
    const fs = require('fs');
    
    fs.readFile(path.join(__dirname,'../data.json'),'utf8',(err,content) => {
        if(err) return;
        let list = JSON.parse(content);
        let arr = [];
        list.forEach(item => {
            //字符串拼接,用反引号
            let sql = `insert into book(name,author,category,description) VALUES('${item.name}','${item.author}','${item.category}','${item.desc}');`
            //获取的只是一条sql语句,依此将sql语句存入数组中
            arr.push(sql);
        });
        fs.writeFile(path.join(__dirname,'data.sql'),arr.join(' '),'utf8',(err) => {
            console.log('init data finished!');
        });
    });

    3.功能展示:

  • 相关阅读:
    Linux下修改时间时区的方法介绍
    IIS启用GZip压缩的详细教程(图文)
    jquery定时器的简单代码
    IIS启用GZIP压缩js、css无效的原因及解决方法
    python批量导出导入MySQL用户的方法
    mysql执行计划介绍
    js+json用表格实现简单网站左侧导航
    React Native 二维码扫描组件
    mysql如何修改开启允许远程连接
    react native中的聊天气泡以及timer封装成的发送验证码倒计时
  • 原文地址:https://www.cnblogs.com/zcy9838/p/11626673.html
Copyright © 2011-2022 走看看