• 案例:基于接口的图书管理功能


    图书相关的操作基于后台接口数据进行操作:

    需要调用接口的功能点:

    功能 请求方式 请求路由
    ① 图书列表数据加载 GET http://localhost:3000/books
    ② 添加图书 POST http://localhost:3000/books
    ③ 验证图书名称是否存在 GET http://localhost:3000/books/book/:name
    ④ 编辑图书-根据ID查询图书信息  GET http://localhost:3000/books/:id
    ⑤ 编辑图书-提交图书信息 PUT http://localhost:3000/books/:id
    ⑥ 删除图书 DELETE http://localhost:3000/books/:id

    接口文档:

    基准路径:http://localhost:3000/

    1. 获取图书列表数据

    • 路径:books
    • 请求方式:get
    • 请求参数:无
    • 响应结果
    [{
      "id": "4",
      "name": "红楼梦",
      "date": 2525609975000
    }, {
      "name": "三国演义",
      "date": 2525609975000,
      "id": 5
    }, {
      "name": "水浒传",
      "date": 2525609975000,
      "id": 6
    }, {
      "name": "西游记",
      "date": 2525609975000,
      "id": 7
    }]

    2. 添加图书-提交图书信息

    • 路径:books
    • 请求方式:post
    • 请求参数
      • name:图书名称
    • 响应结果
    {
        "status": 200  // (200表示成功;500表示失败)
    }

    3. 编辑图书-根据ID查询图书信息

    • 路径:books/:id
    • 请求方式:get
    • 请求参数:无
    • 响应结果
    {
        "name": "西游记",
        "date": 2525609975000,
        "id": 7
    }

    4. 编辑图书-提交图书信息

    • 路径:books/:id
    • 请求方式:put
    • 请求参数
      • name:图书名称
    • 响应结果
    {
        "status": 200  // (200表示成功;500表示失败)
    }

    5. 删除图书信息

    • 路径:books/:id
    • 请求方式:delete
    • 请求参数:无
    • 响应结果
    {
        "status": 200  // (200表示成功;500表示失败)
    }

    6. 验证图书名称是否存在

    • 路径:books/book/:name
    • 请求方式:get
    • 请求参数:无
    • 响应结果
    {
        "status": 1 // (1表示存在;2表示不存在)
    }

    初始化项目:npm init -y

    安装相应的第三方模块:

    npm install express --save
    npm install body-parser --save

    目录结构如下:

    文件之间的关系如下:

     

    使用nodemon index.js命令启动服务器后,在浏览器中输入下面地址即可查看到动态页面:

    books.html文件:

    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <title>Document</title>
      <link rel="stylesheet" type="text/css" href="/css/index.css">
    </head>
    <body>
      <div id="app">
        <div class="grid">
          <div>
            <h1>图书管理</h1>
            <div class="book">
              <div>
                <label for="id">
                  编号:
                </label>
                <input type="text" id="id" v-model='id' disabled="false" v-focus>
                <label for="name">
                  名称:
                </label>
                <input type="text" id="name" v-model='name'>
                <button @click='handle' :disabled="submitFlag">提交</button>
              </div>
            </div>
          </div>
          <div class="total">
            <span>图书总数:</span>
            <span>{{total}}</span>
          </div>
          <table>
            <thead>
              <tr>
                <th>编号</th>
                <th>名称</th>
                <th>时间</th>
                <th>操作</th>
              </tr>
            </thead>
            <tbody>
              <tr :key='item.id' v-for='item in books'>
                <td>{{item.id}}</td>
                <td>{{item.name}}</td>
                <td>{{item.date | format('yyyy-MM-dd hh:mm:ss')}}</td>
                <td>
                  <a href="" @click.prevent='toEdit(item.id)'>修改</a>
                  <span>|</span>
                  <a href="" @click.prevent='deleteBook(item.id)'>删除</a>
                </td>
              </tr>
            </tbody>
          </table>
        </div>
      </div>
      <script type="text/javascript" src="js/vue.js"></script>
      <script type="text/javascript" src="js/axios.js"></script>
      <script type="text/javascript">
        /*
          图书管理-添加图书
        */
        axios.defaults.baseURL = 'http://localhost:3000/';
        // 设置响应拦截请求
        axios.interceptors.response.use(function(res){
          return res.data;
        }, function(error){
          console.log(error)
        });
        // 设置自定义指令v-focus
        Vue.directive('focus', {
          inserted: function (el) {
            el.focus();
          }
        });
        // 设置日期过滤器
        Vue.filter('format', function(value, arg) {
          function dateFormat(date, format) {
            if (typeof date === "string") {
              var mts = date.match(/(/Date((d+))/)/);
              if (mts && mts.length >= 3) {
                date = parseInt(mts[2]);
              }
            }
            date = new Date(date);
            if (!date || date.toUTCString() == "Invalid Date") {
              return "";
            }
            var map = {
              "M": date.getMonth() + 1, //月份 
              "d": date.getDate(), //
              "h": date.getHours(), //小时 
              "m": date.getMinutes(), //
              "s": date.getSeconds(), //
              "q": Math.floor((date.getMonth() + 3) / 3), //季度 
              "S": date.getMilliseconds() //毫秒 
            };
            format = format.replace(/([yMdhmsqS])+/g, function(all, t) {
              var v = map[t];
              if (v !== undefined) {
                if (all.length > 1) {
                  v = '0' + v;
                  v = v.substr(v.length - 2);
                }
                return v;
              } else if (t === 'y') {
                return (date.getFullYear() + '').substr(4 - all.length);
              }
              return all;
            });
            return format;
          }
          return dateFormat(value, arg);
        })
        var vm = new Vue({
          el: '#app',
          data: {
            flag: false,
            submitFlag: false,
            id: '',
            name: '',
            books: []
          },
          methods: {
            handle: async function(){
              if(this.flag) {
                // 编辑图书
                var ret = await axios.put('books/' + this.id, {
                  name: this.name
                });
                if(ret.status == 200){
                  // 重新加载列表数据
                  this.queryData();
                }
                this.flag = false;
              }else{
                // 添加图书
                var ret = await axios.post('books', {
                  name: this.name
                })
                if(ret.status == 200) {
                  // 重新加载列表数据
                  this.queryData();
                }
              }
              // 清空表单
              this.id = '';
              this.name = '';
            },
            toEdit: async function(id){
              // flag状态位用于区分编辑和添加操作
              this.flag = true;
              // 根据id查询出对应的图书信息
              var ret = await axios.get('books/' + id);
              this.id = ret.id;
              this.name = ret.name;
            },
            deleteBook: async function(id){
              // 删除图书
              var ret = await axios.delete('books/' + id);
              if(ret.status == 200) {
                // 重新加载列表数据
                this.queryData();
              }
            },
            queryData: async function(){
              // 调用后台接口获取图书列表数据
              // var ret = await axios.get('books');
              // this.books = ret.data;
    
              this.books = await axios.get('books');
            }
          },
          computed: {
            total: function(){
              // 计算图书的总数
              return this.books.length;
            }
          },
          watch: {
            name: async function(val) {
              // 验证图书名称是否已经存在
              // var flag = this.books.some(function(item){
              //   return item.name == val;
              // });
              var ret = await axios.get('/books/book/' + this.name);
              if(ret.status == 1) {
                // 图书名称存在
                this.submitFlag = true;
              }else{
                // 图书名称不存在
                this.submitFlag = false;
              }
            }
          },
          mounted: function(){
            // var that = this;
            // axios.get('books').then(function(data){
            //   console.log(data.data)
            //   that.books = data.data;
            // })
    
            // axios.get('books').then((data)=>{
            //   console.log(data.data)
            //   this.books = data.data;
            // })
    
            this.queryData();
          }
        });
      </script>
    </body>
    </html>

    index.js文件:

    const express = require('express');
    const path = require('path');
    const router = require('./router.js');
    const bodyParser = require('body-parser');
    const app = express();
    
    // 启动静态资源服务
    app.use(express.static('public'));
    
    // 处理请求参数
    app.use(bodyParser.urlencoded({ extended: false }));
    app.use(bodyParser.json());
    
    // 配置路由
    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('/books', service.getAllBooks);
    // 添加图书(提交表单)
    router.post('/books', service.addBook);
    // 跳转到编辑图书信息页面
    router.get('/books/:id', service.toEditBook);
    // router.get('/toEditBook',service.toEditBook);
    // 编辑图书提交表单
    router.put('/books/:id', service.editBook);
    // 删除图书信息
    router.delete('/books/:id', service.deleteBook);
    // 验证图书名称是否存在
    router.get('/books/book/:name', service.checkName);
    
    module.exports = router;

    service.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 writeDataToFile = (res) => {
        fs.writeFile(path.join(__dirname,'data.json'),JSON.stringify(data,null,4),(err)=>{
            if(err){
                res.json({
                    status: 500
                });
            }
            res.json({
                status: 200
            });
        });
    }
    // 验证图书名称是否存在
    exports.checkName = (req,res) => {
        let name = req.params.name;
        let flag = false;
        data.some(item=>{
            if(name == item.name) {
                flag = true;
                return true;
            }
        })
        if(flag) {
            res.json({
                status: 1
            })
        }else{
            res.json({
                status: 2
            })
        }
    }
    
    // 获取图书列表数据
    exports.getAllBooks = (req,res) => {
        res.json(data);
    }
    
    // 添加图书保存数据
    exports.addBook = (req,res) => {
        // 获取表单数据
        let info = req.body;
        let book = {};
        for(let key in info){
            book[key] = info[key];
        }
        book.date = 2525609975000;
        book.id = maxBookCode() + 1;
        data.push(book);
        // 把内存中的数据写入文件
        writeDataToFile(res);
    }
    // 跳转编辑图书页面
    exports.toEditBook = (req,res) => {
        let id = req.params.id;
        let book = {};
        data.some((item)=>{
            if(id == item.id){
                book = item;
                return true;
            }
        });
        res.json(book);
    }
    // 编辑图书更新数据
    exports.editBook = (req,res) => {
        let info = req.body;
        info.id = req.params.id;
        data.some((item)=>{
            if(info.id == item.id){
                for(let key in info){
                    item[key] = info[key];
                }
                return true;
            }
        });
        // 把内存中的数据写入文件
        writeDataToFile(res);
    }
    // 删除图书信息
    exports.deleteBook = (req,res) => {
        let id = req.params.id;
        data.some((item,index)=>{
            if(id == item.id){
                // 删除数组的一项数据
                data.splice(index,1);
                return true;
            }
        });
        // 把内存中的数据写入文件
        writeDataToFile(res);
    }

    data.json数据文件:

    [
        {
            "id": "4",
            "name": "红楼梦",
            "date": 2525609975000
        },
        {
            "name": "三国演义",
            "date": 2525609975000,
            "id": 5
        },
        {
            "name": "水浒传",
            "date": 2525609975000,
            "id": 6
        },
        {
            "name": "西游记",
            "date": 2525609975000,
            "id": 7
        },
        {
            "name": "明朝那些事儿",
            "date": 2525609975000,
            "id": "8"
        }
    ]

           

  • 相关阅读:
    CHOCBase
    iOS 12中无法获取WiFi的SSID了?
    如何打开Assets.car文件
    博客园美化资源网站链接
    xcode工程配置绝对路径与相对路径
    UIControl事件
    UIButton属性
    UIAlertView
    UIActivityIndicatorView
    NSAttributedString
  • 原文地址:https://www.cnblogs.com/zcy9838/p/13162000.html
Copyright © 2020-2023  润新知