英雄列表:前端:jquery、后端:node.js

需求分析:英雄列表

  1. 后端项目运行地址:http://127.0.0.1:5000
  2. 前端项目运行地址:http://127.0.0.1:3000
  3. 前后端分离开发模式的注意点:
  • 跨域问题

  • 如果不考虑 表单的 Post 提交,则 可以使用 JSONP 的形式来请求接口

  • 但是,我们的项目中,涉及到了 英雄表单的 提交,表单提交一般都是Post

  • 经过分析,由于JSONP,不支持Post,所以,我们的后端接口,无法设计成JSONP的接口;

  • 前端项目 Jquery + 模板引擎 + Semantic UI

    Semantic 官网:https://semantic-ui.com/introduction/getting-started.html

前端web项目

  1. 初始化项目:npm init -y

  2. 安装Semantic UI

    npm install -g gulp

    npm install semantic-ui --save
    cd semantic/
    gulp build

package.json

{
  "name": "web",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "art-template": "^4.12.2",
    "express": "^4.16.3",
    "jquery": "^3.3.1",
    "semantic-ui": "^2.3.2"
  }
}

views

index.js
$(function () {
  // 获取英雄列表的方法
  function getHeroList () {
    $.ajax({
      url: 'http://127.0.0.1:5001/getallhero',
      type: 'get',
      success: function (result) {
        console.log(result)
        var str = template('row', result)
        $('#tbd').html(str)
      }
    })
  }

  getHeroList()

  $('#add').on('click', function () {
    $('.ui.modal').modal('show')
  })

  // 初始化下拉框的样式
  $('.ui.dropdown').dropdown()

  $('#btnAdd').on('click', function () {
    $.ajax({
      url: 'http://127.0.0.1:5001/addhero',
      data: $('form').serialize(),
      type: 'post',
      dataType: 'json',
      success: function (result) {
        if (result.status === 200) {
          getHeroList()
        }
      }
    })
  })
})

index.css
body{
  padding: 20px;
}
h1 {
  padding: 20px 0;
  text-align: center;
}

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>Document</title>
  <link rel="stylesheet" href="/semantic/dist/semantic.min.css">
  <script src="/node_modules/jquery/dist/jquery.min.js"></script>
  <!-- 注意:semantic.min.js 依赖于 Jquery -->
  <script src="/semantic/dist/semantic.min.js"></script>
  <script src="/node_modules/art-template/lib/template-web.js"></script>
  <link rel="stylesheet" href="./index.css">
  <script src="./index.js"></script>
</head>

<body>
  <h1>英雄列表</h1>

  <button class="ui primary button" id="add">添加英雄</button>

  <!-- 表格区域 -->
  <table class="ui celled striped blue table">
    <thead>
      <tr>
        <th>编号</th>
        <th>英雄名称</th>
        <th>性别</th>
        <th>创建时间</th>
        <th>操作</th>
      </tr>
    </thead>
    <tbody id="tbd">
    </tbody>
  </table>

  <!-- 对话框 -->
  <div class="ui tiny modal">
    <div class="header">
      添加新英雄
    </div>
    <div class="content">
      <form class="ui form">
        <div class="field">
          <label>名称:</label>
          <input type="text" name="name" placeholder="请输入英雄名称">
        </div>
        <div class="field">
          <label>性别:</label>
          <select name="gender" class="ui fluid dropdown">
            <option value=""></option>
            <option value=""></option>
          </select>
        </div>
      </form>
    </div>
    <div class="actions">
      <div class="ui black deny button">
        取消
      </div>
      <div class="ui positive right button" id="btnAdd">
        添加
      </div>
    </div>
  </div>

  <script type="text/template" id="row">
    {{each data}}
    <tr>
      <td>
        <div class="ui ribbon label {{$value.isdel === '000' ? 'blue' : 'red'}}">{{$value.isdel === '000' ? '正常' : '删除'}}</div>
        {{$value.id}}
      </td>
      <td>{{$value.name}}</td>
      <td>{{$value.gender}}</td>
      <td>{{$value.ctime}}</td>
      <td>
        <a href="javascript:;">编辑</a>
        <a href="javascript:;">删除</a>
      </td>
    </tr>
    {{/each}}
  </script>
</body>

</html>

web.js

创建express服务器,实现静态资源托管

// 导入 express 模块
const express = require('express')

// 创建 express 的服务器实例
const app = express()

// 静态资源托管
app.use(express.static('./views'))
app.use('/semantic', express.static('./semantic'))
app.use('/node_modules', express.static('./node_modules'))

// 调用 app.listen 方法,指定端口号并启动web服务器
app.listen(3001, function () {
  console.log('Express server running at http://127.0.0.1:3001')
})

数据库设计 - heros

字段名字段类型字段描述
idint主键Id(自增)
namevarchar英雄名称
gendervarchar性别
ctimevarchar创建时间
isdeltinyint(布尔值)是否被删除 0 表示未删除;1 表示已经被删除

在 mysql 中的 tinyint 等同于 bool 值

api_server项目

  1. 初始化项目:npm init -y
  2. 安装express服务器:npm install express -S
  3. 安装mysql数据库:npm install mysql -S
  4. 开启CORS跨域:npm install cors -S
  5. 安装body-parser解析表单数据:npm install body-parser -S

db.js 数据操作模块


// 导入 mysql 模块
const mysql = require('mysql')

// 创建数据库连接,获取数据库连接对象
const conn = mysql.createConnection({
  host: '127.0.0.1',
  user: 'root',
  password: 'root',
  database: 'mysql_001'
})

module.exports = conn

router.js 路由模块

路由模块 本质:就是 URL 地址到 处理函数之间的对应关系


const express = require('express')

const router = express.Router()

// 导入自己的 业务逻辑处理模块
const ctrl = require('./controller.js')

// 只要有人请求 后台的 / 根路径地址,就提示他,请求API服务器成功了!
router.get('/', ctrl.testAPI)

// 对外暴露 getAllHero 接口
router.get('/getallhero', ctrl.getAllHero)

// 对外暴露添加英雄的API接口
router.post('/addhero', ctrl.addHero)

// 对外暴露 获取英雄信息的 API 接口
router.get('/gethero/:id', ctrl.getHeroById)

// 对外暴露 根据Id更新英雄数据的API接口
router.post('/updatehero/:id', ctrl.updateHeroById)

// 对外暴露 根据Id软删除英雄数据的API接口
router.get('/deletehero/:id', ctrl.deleteHeroById)

module.exports = router

server.js 入口

const express = require('express')
const app = express()

// 注册 body-parser 中间件
const bodyParser = require('body-parser')
app.use(bodyParser.urlencoded({ extended: false }))

// 在 API 服务器端,启用 CORS 跨域资源共享
const cors = require('cors')
app.use(cors())

// 导入自己的路由模块
const router = require('./router.js')

// 注册路由模块
app.use(router)

// 让 后端项目,运行在 5001 端口
app.listen(5001, () => {
  console.log('api server running at http://127.0.0.1:5001')
})

controller.js 业务处理模块


const conn = require('./db.js')

module.exports = {

  /**
   * 测试 API 服务器能否正常被请求
   */
  testAPI: (req, res) => {
    res.send('请求后台API接口成功!')
  },

  /**
   *  获取所有英雄列表
   */
  getAllHero: (req, res) => {
    const sql = 'select * from heros'
    conn.query(sql, (err, result) => {
      // 如果读取数据失败,则返回一个失败的结果
      if (err) return res.send({ status: 500, msg: err.message, data: null })
      // 如果获取数据成功,则直接返回成功的数据结果
      res.send({ status: 200, msg: 'ok', data: result })
    })
  },

  /**
   *  添加英雄
   *  1. 获取到客户端提交到 服务器的 表单数据: 英雄名称、性别 即可
   *  2. 获取服务器的当前时间,当作 英雄的添加时间
   */
  addHero: (req, res) => {
   
    const hero = req.body

    // 得到当前的时间对象
    const dt = new Date()

    // 字符串,有一个新方法,叫做 padStart(长度, 要填充的字符串)
    const y = dt.getFullYear()
    const m = (dt.getMonth() + 1).toString().padStart(2, '0')
    const d = dt
      .getDate()
      .toString()
      .padStart(2, '0')

    const hh = dt
      .getHours()
      .toString()
      .padStart(2, '0')
    const mm = dt
      .getMinutes()
      .toString()
      .padStart(2, '0')
    const ss = dt
      .getSeconds()
      .toString()
      .padStart(2, '0')
    // 补全英雄的添加时间
    hero.ctime = y + '-' + m + '-' + d + ' ' + hh + ':' + mm + ':' + ss

    /**
     *  调用 conn.query 实现 添加英雄
     */
    const sql = 'insert into heros set ?'
    conn.query(sql, hero, (err, result) => {
      if (err) return res.send({ status: 500, msg: err.message, data: null })
      res.send({ status: 200, msg: 'ok', data: null })
    })

  },

  /**
   *  根据Id获取英雄信息
   *  1. 获取到英雄的Id
   *  2. 根据Id查询数据,并返回给客户端查询的结果
   */
  getHeroById: (req, res) => {
   
    const id = req.params.id
    const sql = 'select * from heros where id=?'
    conn.query(sql, id, (err, result) => {
      if (err) return res.send({ status: 500, msg: err.message, data: null })
      res.send({ status: 200, msg: 'ok', data: result })
    })

  },

  /**
   *  根据 Id 更新英雄信息
   */
  updateHeroById: (req, res) => {
    const id = req.params.id
    const newInfo = req.body
    const sql = 'update heros set ? where id=?'
    conn.query(sql, [newInfo, id], (err, result) => {
      if (err) return res.send({ status: 500, msg: err.message, data: null })
      res.send({ status: 200, msg: 'ok', data: null })
    })
  },

  /**
   *  根据Id删除英雄信息
   */
  deleteHeroById: (req, res) => {
    const id = req.params.id
    const sql = 'update heros set isdel=1 where id=?'
    conn.query(sql, id, (err, result) => {
      if (err) return res.send({ status: 500, msg: err.message, data: null })
      res.send({ status: 200, msg: 'ok', data: null })
    })
  }

}

后台接口设计

获取所有英雄列表

  • 请求类型:GET
  • 请求地址:http://127.0.0.1:5001/getallhero
  • 请求的参数:无

插入新的英雄数据

  • 请求类型:POST
  • 请求地址:http://127.0.0.1:5001/addhero
  • 请求参数:{ name, gender }

根据Id获取英雄信息

请求类型:GET

请求地址:http://127.0.0.1:5001/gethero/:id

请求参数:通过 URL 地址,把要查询的英雄Id,携带过去

根据Id更新英雄数据

请求类型: POST

请求地址:http://127.0.0.1:5001/updatehero/:id

请求参数:{ name, gender }

根据Id软删除英雄数据

软删除 只是将isdel的状态改变了 (isdel为 1,表示删除)

请求类型:GET

请求地址:http://127.0.0.1:5001/deletehero/:id

请求参数:通过 URL 地址栏传参,把 要删除的英雄Id提交给服务器

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

落花流雨

你的鼓励将是我创作的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值