本文通过后台JS——Node.js、后台Web开发框架Express、MongoDB数据库、MongoDB操作库Monggose以及前端开发框架Bootstrap来简单开发一个增删改查demo。该demo以简单、方便理解的方式来记录前后端结合使用的过程。
系统架构 前端:Bootstrap 3.4.1 后端:Node.js 14.17.3 Express 5 MongoDB 5.0.3 模块化规范:CommonJS
启动后访问:http://localhost:3000/players
开发步骤
- 创建工程
终端输入命令:npm init -y创建 package.json文件;安装express,mongoDB数据库等,此处不再过多赘述; - 编写后端代码
入口文件 app.js:
const artTemplate = require('art-template')
const express = require('express')
const router = require('./router')
const bodyParser = require('body-parser')
const app = express()
const port = 3000
app.engine('html', require('express-art-template'))
app.use('/node_modules/', express.static('./node_modules/'))
app.use('/public/', express.static('./public/'))
app.use(bodyParser.urlencoded({ extended: false }))
app.use(bodyParser.json())
app.use(router)
app.listen(port, () => {
console.log(`Example app listening at http://localhost:${port}`)
})
module.exports = app
路由文件 router.js:
const player = require('./player')
const express = require('express')
const router = express.Router()
router.get('/players', function (req, res) {
player.find(function (err, players) {
if (err) {
return res.send('Server error')
}
res.render('index.html', {
players: players
})
})
})
router.get('/players/new', function (req, res) {
res.render('add_players.html')
})
router.post('/players/new', function (req, res) {
new player(req.body).save(function (err) {
if (err) {
return res.send('Server error')
}
res.redirect('/players')
})
})
router.get('/players/edit', function (req, res) {
player.findById(req.query.id.replace(/"/g, ''), function (err, player) {
if (err) {
return res.send('Server error')
}
res.render('update_player.html', {
player: player
})
})
})
router.post('/players/edit', function (req, res) {
const id = req.body.id.replace(/"/g, '')
player.findByIdAndUpdate(id, req.body, function (err) {
if (err) {
return res.send('Server error')
}
res.redirect('/players')
})
})
router.get('/players/delete', function (req, res) {
const id = req.query.id.replace(/"/g, '')
player.findByIdAndRemove(id, function (err) {
if (err) {
return res.send('Server error')
}
res.redirect('/players')
})
})
module.exports = router
player实体:player.js:
const mongoose = require('mongoose')
mongoose.connect('mongodb://localhost/itcast')
const Schema = mongoose.Schema
const playerSchema = new Schema({
name: {
type: String,
required: true
},
age: {
type: Number,
required: true
},
number: {
type: Number,
required: true
},
position: {
type: String
}
})
module.exports = mongoose.model('Player', playerSchema)
- 编写前端代码
主页面 index.html(Bootstrap官网上的模板):展示球员信息:
<!doctype html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="">
<meta name="author" content="">
<link rel="icon" href="https://cdn.jsdelivr.net/npm/@bootcss/v3.bootcss.com@1.0.16/favicon.ico">
<link rel="canonical" href="https://getbootstrap.com/docs/3.4/examples/dashboard/">
<title>Dashboard Template for Bootstrap</title>
<link href="https://cdn.jsdelivr.net/npm/@bootcss/v3.bootcss.com@1.0.16/dist/css/bootstrap.min.css" rel="stylesheet">
<link href="/public/css/main.css" rel="stylesheet">
</head>
<body>
<nav class="navbar navbar-inverse navbar-fixed-top">
<div class="container-fluid">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="#">简易球员管理系统</a>
</div>
<div id="navbar" class="navbar-collapse collapse">
<ul class="nav navbar-nav navbar-right">
<li><a href="#">Dashboard</a></li>
<li><a href="#">Settings</a></li>
<li><a href="#">Profile</a></li>
<li><a href="#">Help</a></li>
</ul>
<form class="navbar-form navbar-right">
<input type="text" class="form-control" placeholder="Search...">
</form>
</div>
</div>
</nav>
<div class="container-fluid">
<div class="row">
<div class="col-sm-3 col-md-2 sidebar">
<ul class="nav nav-sidebar">
<li class="active"><a href="#">球员管理 <span class="sr-only">(current)</span></a></li>
<li><a href="#">Reports</a></li>
<li><a href="#">Analytics</a></li>
<li><a href="#">Export</a></li>
</ul>
<ul class="nav nav-sidebar">
<li><a href="">Nav item</a></li>
<li><a href="">Nav item again</a></li>
<li><a href="">One more nav</a></li>
<li><a href="">Another nav item</a></li>
<li><a href="">More navigation</a></li>
</ul>
<ul class="nav nav-sidebar">
<li><a href="">Nav item again</a></li>
<li><a href="">One more nav</a></li>
<li><a href="">Another nav item</a></li>
</ul>
</div>
<div class="col-sm-9 col-sm-offset-3 col-md-10 col-md-offset-2 main">
<h1 class="page-header">Dashboard</h1>
<div class="row placeholders">
<div class="col-xs-6 col-sm-3 placeholder">
<img src="data:image/gif;base64,R0lGODlhAQABAIAAAHd3dwAAACH5BAAAAAAALAAAAAABAAEAAAICRAEAOw==" width="200" height="200" class="img-responsive" alt="Generic placeholder thumbnail">
<h4>Label</h4>
<span class="text-muted">Something else</span>
</div>
<div class="col-xs-6 col-sm-3 placeholder">
<img src="data:image/gif;base64,R0lGODlhAQABAIAAAHd3dwAAACH5BAAAAAAALAAAAAABAAEAAAICRAEAOw==" width="200" height="200" class="img-responsive" alt="Generic placeholder thumbnail">
<h4>Label</h4>
<span class="text-muted">Something else</span>
</div>
<div class="col-xs-6 col-sm-3 placeholder">
<img src="data:image/gif;base64,R0lGODlhAQABAIAAAHd3dwAAACH5BAAAAAAALAAAAAABAAEAAAICRAEAOw==" width="200" height="200" class="img-responsive" alt="Generic placeholder thumbnail">
<h4>Label</h4>
<span class="text-muted">Something else</span>
</div>
<div class="col-xs-6 col-sm-3 placeholder">
<img src="data:image/gif;base64,R0lGODlhAQABAIAAAHd3dwAAACH5BAAAAAAALAAAAAABAAEAAAICRAEAOw==" width="200" height="200" class="img-responsive" alt="Generic placeholder thumbnail">
<h4>Label</h4>
<span class="text-muted">Something else</span>
</div>
</div>
<h2 class="sub-header">Section title</h2>
<a class="btn btn-success" href="/players/new">添加球员</a>
<div class="table-responsive">
<table class="table table-striped">
<thead>
<tr>
<th>#</th>
<th>姓名</th>
<th>年龄</th>
<th>号码</th>
<th>位置</th>
<th>操作</th>
</tr>
</thead>
<tbody>
{{ each players}}
<tr>
<td>{{ $index + 1 }}</td>
<td>{{ $value.name }}</td>
<td>{{ $value.age }}</td>
<td>{{ $value.number }}</td>
<td>{{ $value.position }}</td>
<td>
<a href="/players/edit/?id={{ $value._id }}">编辑</a>
<a href="/players/delete/?id={{ $value._id }}">删除</a>
</td>
</tr>
{{ /each }}
</tbody>
</table>
</div>
</div>
</div>
</div>
</body>
</html>
添加球员页面 add_players.html(Bootstrap官网上的模板):
<!doctype html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="">
<meta name="author" content="">
<link rel="icon" href="https://cdn.jsdelivr.net/npm/@bootcss/v3.bootcss.com@1.0.16/favicon.ico">
<link rel="canonical" href="https://getbootstrap.com/docs/3.4/examples/dashboard/">
<title>Dashboard Template for Bootstrap</title>
<link href="https://cdn.jsdelivr.net/npm/@bootcss/v3.bootcss.com@1.0.16/dist/css/bootstrap.min.css" rel="stylesheet">
<link href="/public/css/main.css" rel="stylesheet">
</head>
<body>
<nav class="navbar navbar-inverse navbar-fixed-top">
<div class="container-fluid">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="#">Project name</a>
</div>
<div id="navbar" class="navbar-collapse collapse">
<ul class="nav navbar-nav navbar-right">
<li><a href="#">Dashboard</a></li>
<li><a href="#">Settings</a></li>
<li><a href="#">Profile</a></li>
<li><a href="#">Help</a></li>
</ul>
<form class="navbar-form navbar-right">
<input type="text" class="form-control" placeholder="Search...">
</form>
</div>
</div>
</nav>
<div class="container-fluid">
<div class="row">
<div class="col-sm-3 col-md-2 sidebar">
<ul class="nav nav-sidebar">
<li class="active"><a href="#">Overview <span class="sr-only">(current)</span></a></li>
<li><a href="#">Reports</a></li>
<li><a href="#">Analytics</a></li>
<li><a href="#">Export</a></li>
</ul>
<ul class="nav nav-sidebar">
<li><a href="">Nav item</a></li>
<li><a href="">Nav item again</a></li>
<li><a href="">One more nav</a></li>
<li><a href="">Another nav item</a></li>
<li><a href="">More navigation</a></li>
</ul>
<ul class="nav nav-sidebar">
<li><a href="">Nav item again</a></li>
<li><a href="">One more nav</a></li>
<li><a href="">Another nav item</a></li>
</ul>
</div>
<div class="col-sm-9 col-sm-offset-3 col-md-10 col-md-offset-2 main">
<form action="/players/new" method="post">
<div class="form-group">
<label for="">姓名</label>
<input type="text" class="form-control" id="" placeholder="姓名" name="name">
</div>
<div class="form-group">
<label for="">年龄</label>
<input type="number" class="form-control" id="" placeholder="年龄" name="age">
</div>
<div class="form-group">
<label for="">号码</label>
<input type="number" class="form-control" id="" placeholder="号码" name="number">
</div>
<div class="form-group">
<label for="">位置</label>
<input type="text" class="form-control" id="" placeholder="位置" name="position">
</div>
<button type="submit" class="btn btn-default">Submit</button>
</form>
</div>
</div>
</div>
</body>
</html>
修改球员信息页面 update_player.html:
<!doctype html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="">
<meta name="author" content="">
<link rel="icon" href="https://cdn.jsdelivr.net/npm/@bootcss/v3.bootcss.com@1.0.16/favicon.ico">
<link rel="canonical" href="https://getbootstrap.com/docs/3.4/examples/dashboard/">
<title>Dashboard Template for Bootstrap</title>
<link href="https://cdn.jsdelivr.net/npm/@bootcss/v3.bootcss.com@1.0.16/dist/css/bootstrap.min.css" rel="stylesheet">
<link href="/public/css/main.css" rel="stylesheet">
</head>
<body>
<nav class="navbar navbar-inverse navbar-fixed-top">
<div class="container-fluid">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="#">Project name</a>
</div>
<div id="navbar" class="navbar-collapse collapse">
<ul class="nav navbar-nav navbar-right">
<li><a href="#">Dashboard</a></li>
<li><a href="#">Settings</a></li>
<li><a href="#">Profile</a></li>
<li><a href="#">Help</a></li>
</ul>
<form class="navbar-form navbar-right">
<input type="text" class="form-control" placeholder="Search...">
</form>
</div>
</div>
</nav>
<div class="container-fluid">
<div class="row">
<div class="col-sm-3 col-md-2 sidebar">
<ul class="nav nav-sidebar">
<li class="active"><a href="#">Overview <span class="sr-only">(current)</span></a></li>
<li><a href="#">Reports</a></li>
<li><a href="#">Analytics</a></li>
<li><a href="#">Export</a></li>
</ul>
<ul class="nav nav-sidebar">
<li><a href="">Nav item</a></li>
<li><a href="">Nav item again</a></li>
<li><a href="">One more nav</a></li>
<li><a href="">Another nav item</a></li>
<li><a href="">More navigation</a></li>
</ul>
<ul class="nav nav-sidebar">
<li><a href="">Nav item again</a></li>
<li><a href="">One more nav</a></li>
<li><a href="">Another nav item</a></li>
</ul>
</div>
<div class="col-sm-9 col-sm-offset-3 col-md-10 col-md-offset-2 main">
<form action="/players/edit" method="post">
<div class="form-group">
<label for="">姓名</label>
<input type="text" class="form-control" id="" placeholder="姓名" name="name" value="{{ player.name }}">
</div>
<div class="form-group">
<label for="">年龄</label>
<input type="number" class="form-control" id="" placeholder="年龄" name="age" value="{{ player.age }}">
</div>
<div class="form-group">
<label for="">号码</label>
<input type="number" class="form-control" id="" placeholder="号码" name="number" value="{{ player.number }}">
</div>
<div class="form-group">
<label for="">位置</label>
<input type="text" class="form-control" id="" placeholder="位置" name="position" value="{{ player.position }}">
</div>
<button type="submit" class="btn btn-default">Submit</button>
</form>
</div>
</div>
</div>
</body>
</html>
效果展示 系统首页: 添加球员: 更新球员:
删除球员:
|