[目录]
├── node_modules #第三方插件模块包文件
├── control #文件操作模块
│ └──control.js
├── router #路由模块
│ └──router.js
├── static #静态资源文件存放图片字体css文件
|
├── views #存放html模板文件
├── app.js #主入口文件
├── db.json #要操作的json文件
复制代码
#快速创建项目-不加-y则手动配置
npm init -y
复制代码
安装express
框架、body-parser
POST请求解析、art-template
模板渲染插件nodemon
自动重启工具
#安装Express
npm install --save express
#安装art-template
npm install --save art-template
npm install --save express-art-template
#安装body-parser
npm install --save body-parser
#安装node自动重启工具
npm install --global nodemon
复制代码
在项目目录根创建主入口文件app.js
文件:app.js
//引入Express框架
const express = require('express');
//引入body-parser
const bodyParser = require('body-parser');
//创建服务
const app = express();
//配置 post解析 body-parser
app.use(bodyParser.urlencoded({extended:false}));
//端口号
let port = 3000
// 配置静态资源
app.use('/static', express.static('static'))
// 配置模板引擎
app.engine('html', require('express-art-template'));
//启动
app.listen(port,()=>{
console.log('启动成功')
})
复制代码
将路由分一个文件做处理router->router.js
渲染模板必须把渲染模板views
目录下
路由器.js
const express = require('express');
const router = express.Router();
//首页渲染数据
router.get('/', (req, res) => {
//模板渲染
res.render('index.html', {
listData: {
name:'假数据'
}
});
})
//导出路由模块
module.exports = router
复制代码
在主入口引入创建好的宣传文件const router = require('./router/router')
在底下挂载几个可以使用app.use(router)
文件:app.js
const express = require('express');
const bodyParser = require('body-parser');
//---------------------引入路由模块-----------------------
const router = require('./router/router')
//------------------------------------------------------
const app = express();
app.use(bodyParser.urlencoded({extended:false}));
let port = 3000
app.use('/static', express.static('static'))
app.engine('html', require('express-art-template'));
//------------------------挂载路由------------------------
app.use(router)
//------------------------------------------------------
app.listen(port,()=>{
console.log('启动成功')
})
复制代码
配置好后可以输入nodemon ./app.js
启动,再浏览器中输入本机IP地址指定3000
端口号,192.168xx:3000
layui
框架官网www.layui.com/
layui
使用:官网下载文件中的相关约定和static
再html中使用layui.css
layui.all.js
此处html
搜索2个文件的首页页面
首页:index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<link rel="stylesheet" href="../static/css/layui.css">
<style>
.layui-table {
text-align: center;
}
.layui-layout-admin {
padding: 20px;
}
.layui-layout-admin .layui-center {
text-align: center;
}
#form {
padding: 20px;
}
.search {
width: 300px;
}
.flex {
display: flex;
}
.justify-between {
justify-content: space-between;
}
.top-nav {
width: 100%;
}
.margin-bottom{
margin-bottom: 10px;
}
</style>
</head>
<body>
<div class="layui-container layui-layout-admin">
<div class="margin-bottom">
<span class="layui-breadcrumb">
<a href="/">首页</a>
</span>
</div>
<div class=" flex justify-between top-nav">
<button type="button" class="layui-btn" id="add">添加</button>
<form action="/search">
<div class="search flex">
<input type="text" name="text" placeholder="关键字" class="layui-input input-search ">
<button class="layui-btn search-butt" type="submit">搜索</button>
</div>
</form>
</div>
<!-- 使用layui表格 -->
<div class="layui-row">
<table class="layui-table">
<colgroup>
<col width="150">
<col width="200">
<col>
</colgroup>
<thead>
<tr>
<th class="layui-center">ID</th>
<th class="layui-center">名称</th>
<th class="layui-center">性别</th>
<th class="layui-center">年龄</th>
<th class="layui-center">兴趣</th>
<th class="layui-center">入学日期</th>
<th class="layui-center">操作</th>
</tr>
</thead>
<tbody>
<tr>
<td>4</td>
<td>完犊子</td>
<td>男</td>
<td>22</td>
<td>
<span>写作</span>、
<span>阅读</span>、
<span>发呆</span>、
</td>
<td>2021-01-21</td>
<td>
<!--操作按钮-->
<div class="layui-btn-group">
<button type="button" class="layui-btn layui-btn-sm edit" data-id="4">
<i class="layui-icon"></i>
</button>
<button data-id="4" type="button" class="layui-btn layui-btn-sm delete">
<i class="layui-icon"></i>
</button>
</div>
</td>
</tr>
</tbody>
</table>
</div>
<!-- 使用layui表单 -->
<form lay-filter="from" class="layui-form layui-form-pane" action="" id="form" style="display: none;">
<div class="layui-form-item layui-form-text">
<label class="layui-form-label">姓名</label>
<div class="layui-input-block">
<input type="text" name="name" required lay-verify="required" placeholder="请输入标题" autocomplete="off"
class="layui-input">
</div>
</div>
<div class="layui-form-item layui-form-text">
<label class="layui-form-label">性别</label>
<div class="layui-input-block">
<input type="radio" name="gender" value="1" title="男">
<input type="radio" name="gender" value="2" title="女" checked>
</div>
</div>
<div class="layui-form-item layui-form-text">
<label class="layui-form-label">年龄</label>
<div class="layui-input-block">
<input type="number" name="age" required lay-verify="required" placeholder="请输入标题"
autocomplete="off" class="layui-input">
</div>
</div>
<div class="layui-form-item layui-form-text">
<label class="layui-form-label">兴趣</label>
<div class="layui-input-block checkbox-item">
<input type="checkbox" name="like[xiezuo]" title="写作" value="写作">
<input type="checkbox" name="like[yuedu]" title="阅读" value="阅读" checked>
<input type="checkbox" name="like[fadai]" title="发呆" value="发呆">
</div>
</div>
<div class="layui-form-item layui-form-text">
<label class="layui-form-label">入学日期</label>
<div class="layui-input-block">
<input type="text" name="EnterDate" id="test1" required lay-verify="required" placeholder="请输入标题"
autocomplete="off" class="layui-input">
</div>
</div>
<div class="layui-form-item">
<div class="layui-input-block">
<button class="layui-btn" lay-submit lay-filter="formDemo">立即提交</button>
<button type="reset" class="layui-btn layui-btn-primary">重置</button>
</div>
</div>
</form>
</div>
<script src="../static/layui.all.js"></script>
</body>
</html>
复制代码
搜索页面模板
搜索:search.html
<html lang="en"><head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<link rel="stylesheet" href="../static/css/layui.css">
<style>
.layui-table {
text-align: center;
}
.layui-layout-admin {
padding: 20px;
}
.layui-layout-admin .layui-center {
text-align: center;
}
#form {
padding: 20px;
}
.search {
width: 300px;
}
.flex {
display: flex;
}
.justify-between {
justify-content: space-between;
}
.justify-center{
justify-content: center;
}
.top-nav {
width: 100%;
}
</style>
<link id="layuicss-laydate" rel="stylesheet" href="http://192.168.1.103:3000/static/css/modules/laydate/default/laydate.css?v=5.0.9" media="all"><link id="layuicss-layer" rel="stylesheet" href="http://192.168.1.103:3000/static/css/modules/layer/default/layer.css?v=3.1.1" media="all"><link id="layuicss-skincodecss" rel="stylesheet" href="http://192.168.1.103:3000/static/css/modules/code.css" media="all"></head>
<body>
<div class="layui-container layui-layout-admin">
<div>
<span class="layui-breadcrumb" style="visibility: visible;">
<a href="/">首页</a><span lay-separator="">/</span>
<a><cite>搜索</cite></a><span lay-separator="">/</span>
<a><cite>小</cite></a>
</span>
</div>
<div class=" flex justify-center top-nav">
<form action="/search">
<div class="search flex ">
<input type="text" name="text" placeholder="关键字" class="layui-input input-search " value="小">
<button class="layui-btn search-butt" type="submit">搜索</button>
</div>
</form>
</div>
<div class="text">
关键词:小
</div>
<div class="layui-row">
<table class="layui-table">
<colgroup>
<col width="150">
<col width="200">
<col>
</colgroup>
<thead>
<tr>
<th class="layui-center">ID</th>
<th class="layui-center">名称</th>
<th class="layui-center">性别</th>
<th class="layui-center">年龄</th>
<th class="layui-center">兴趣</th>
<th class="layui-center">入学日期</th>
<th class="layui-center">操作</th>
</tr>
</thead>
<tbody>
<tr>
<td>11</td>
<td>小鬼头</td>
<td>男</td>
<td>6</td>
<td>
<span>写作</span>、
<span>阅读</span>、
<span>发呆</span>、
</td>
<td>2021-01-15</td>
<td>
<div class="layui-btn-group">
<button type="button" class="layui-btn layui-btn-sm edit" data-id="11">
<i class="layui-icon"></i>
</button>
<button data-id="11" type="button" class="layui-btn layui-btn-sm delete">
<i class="layui-icon"></i>
</button>
</div>
</td>
</tr>
</tbody>
</table>
</div>
<!-- 填写表单 -->
<form lay-filter="from" class="layui-form layui-form-pane" action="" id="form" style="display: none;">
<div class="layui-form-item layui-form-text">
<label class="layui-form-label">姓名</label>
<div class="layui-input-block">
<input type="text" name="name" required="" lay-verify="required" placeholder="请输入标题" autocomplete="off" class="layui-input">
</div>
</div>
<div class="layui-form-item layui-form-text">
<label class="layui-form-label">性别</label>
<div class="layui-input-block">
<input type="radio" name="gender" value="1" title="男"><div class="layui-unselect layui-form-radio"><i class="layui-anim layui-icon"></i><div>男</div></div>
<input type="radio" name="gender" value="2" title="女" checked=""><div class="layui-unselect layui-form-radio layui-form-radioed"><i class="layui-anim layui-icon"></i><div>女</div></div>
</div>
</div>
<div class="layui-form-item layui-form-text">
<label class="layui-form-label">年龄</label>
<div class="layui-input-block">
<input type="number" name="age" required="" lay-verify="required" placeholder="请输入标题" autocomplete="off" class="layui-input">
</div>
</div>
<div class="layui-form-item layui-form-text">
<label class="layui-form-label">兴趣</label>
<div class="layui-input-block checkbox-item">
<input type="checkbox" name="like[xiezuo]" title="写作" value="写作"><div class="layui-unselect layui-form-checkbox"><span>写作</span><i class="layui-icon layui-icon-ok"></i></div>
<input type="checkbox" name="like[yuedu]" title="阅读" value="阅读" checked=""><div class="layui-unselect layui-form-checkbox layui-form-checked"><span>阅读</span><i class="layui-icon layui-icon-ok"></i></div>
<input type="checkbox" name="like[fadai]" title="发呆" value="发呆"><div class="layui-unselect layui-form-checkbox"><span>发呆</span><i class="layui-icon layui-icon-ok"></i></div>
</div>
</div>
<div class="layui-form-item layui-form-text">
<label class="layui-form-label">入学日期</label>
<div class="layui-input-block">
<input type="text" name="EnterDate" id="test1" required="" lay-verify="required" placeholder="请输入标题" autocomplete="off" class="layui-input" lay-key="1">
</div>
</div>
<div class="layui-form-item">
<div class="layui-input-block">
<button class="layui-btn" lay-submit="" lay-filter="formDemo">立即提交</button>
<button type="reset" class="layui-btn layui-btn-primary">重置</button>
</div>
</div>
</form>
</div>
<script src="../static/layui.all.js"></script>
</body></html>
复制代码
渲染首页数据前先创建一个json
文件db.json
根目录
文件:db.json
{
"list": [
{
"name": "张三",
"gender": 1,
"age": 22,
"interest": {
"like[xiezuo]": "写作",
"like[yuedu]": "阅读",
"like[fadai]": "发呆"
},
"EnterDate": "2021-01-21",
"id": 4
}
]
}
复制代码
db.json
文件创建完成后新建一个模块是操作这个文件的增、删、改、查、文件名control->control.js
封装一个读文件操作将字符串转成对象返回出去
将一个对象转换成字符串写入db.json
文件中
文件:control.js
//引入fs模块
const fs = require('fs');
//设置要读的文件路径
const path = './db.json'
//读文件
exports.Read = ()=>{
let fileData = ''
try{
//这里使用的时node的同步读取文件的api [readFileSync]
fileData = fs.readFileSync(path,'utf-8');
console.log(fileData)
}catch (err) {
// 出错了
console.log(err)
}
//读取到的文件转成对象返回
return JSON.parse(fileData)
}
//写入文件-接收一个参数要追加的数据
exports.Write= (data)=>{
try{
//这里同样使用了node同步写入文件api[writeFileSync]
fs.writeFileSync(path,JSON.stringify(data),'utf8')
}catch(err){
//出错
console.log(err)
}
}
复制代码
router.js
中使用control.js
完成以上2个读写api
后可以进行首页数据渲染,将文件control.js
在router.js
中引用即可使用
文件:router.js
请求地址 | 类型 | 参数 | 说明 |
---|---|---|---|
/ | GET | 无 | 渲染首页模板和数据 |
const express = require('express');
//引入读写文件
const control = require('../control/control.js')
const router = express.Router();
//首页渲染数据
router.get('/', (req, res) => {
//读文件
let data = control.Read();
res.render('index.html', {
listData: data.list //将拿到的数据挂载到模板上
});
})
module.exports = router
复制代码
在模板中用模板语法把数据渲染出来
art-template
官网aui.github.io/art-templat…
文件:index.html
{{each listData}}
<tr>
<td>{{$value.id}}</td>
<td>{{$value.name}}</td>
<td>{{$value.gender==1?'男':'女'}}</td>
<td>{{$value.age}}</td>
<td>
{{each $value.interest}}
<span>{{$value}}</span>、
{{/each}}
</td>
<td>{{$value.EnterDate}}</td>
<td>
<div class="layui-btn-group">
<!--使用data-id自定义属性将ID赋值方便再点击操作时取得每行得ID-->
<button type="button" class="layui-btn layui-btn-sm edit" data-id="{{$value.id}}">
<i class="layui-icon"></i>
</button>
<button type="button" class="layui-btn layui-btn-sm delete" data-id="{{$value.id}}">
<i class="layui-icon"></i>
</button>
</div>
</td>
</tr>
{{/each}}
复制代码
文件:router.js
这里接收表单数据结构{"name":"完犊子","gender":1,"age":22,"interest":{"like[xiezuo]":"写作","like[yuedu]":"阅读","like[fadai]":"发呆"},"EnterDate":"2021-01-21"}
读取db.json
中的数据
将前端发来的数据进行转换成对象
在为这条数据分配一个ID,这里直接拿到表中最后一条数据的id然后再+1
分配完ID后将数据push
进入上面读取的到数据中
数据写入文件中
请求地址 | 类型 | 参数 | 说明 |
---|---|---|---|
/add | POST | 表单数据 | 向列表中新增一条数据 |
//添加
router.post('/add', (req, res) => {
//读文件
let data = control.Read();
//获取前端传来的数据
let getData =JSON.parse(req.body.data);
//分配ID
getData.id = data.list[data.list.length-1].id + 1
//新增一条数据
data.list.push(getData)
//写入文件
control.Write(data);
//返回给前端
res.json(getData);
})
复制代码
这里先创建用户的按钮编辑添加变量,用于记录addEdit
当前点击的是公用编辑的,或者是记录当前删除时删除保存的IDuserID
文件:index.html
ajax传值设置,否则节点那里必须traditional: true
不能得到正常的数据,还有一个问题必须把内层的数据转成json字符串,否则节点也不能得到正常的数据
let addEdit = 1 //用来判断当前点击的时编辑还是新增 [1:表示新增,2表示编辑]
let userID = 0 //点击编辑和删除时用来保存当前ID
layui.use(['layer', 'jquery', 'form', 'laydate'], function () {
const $ = layui.$
const form = layui.form;
const laydate = layui.laydate;
//点击添加按钮弹出新增表单
$('#add').click(function () {
addEdit = 1
layer.open({
type: 1,
content: $('#form') //这个表单再html文件中做隐藏不直接显示
});
//重置表单
document.getElementById('form').reset();
});
//监听提交
form.on('submit(formDemo)', function (data) {
//拿到表单的数据进行赋值给dataItem
var dataItem = {
"name": data.field.name,
"gender": parseInt(data.field.gender),
"age": parseInt(data.field.age),
"interest": {},
"EnterDate": data.field.EnterDate
};
//这里特殊处理多选框成为我们想要的数据结构 {"like[xiezuo]":"写作","like[yuedu]":"阅读","like[fadai]":"发呆"}
$('.checkbox-item input').each((index, item) => {
if (item.checked) {
dataItem.interest[item.name] = item.value
}
});
//addEdit=1则为新增
if (addEdit == 1) {
//ajax传值必须设置traditional: true,否则node那边无法拿到正常的数据,再一个就是必须把内层的数据转成json字符串否则node也无法拿到正常的数据
$.ajax({
url: '/add',
type: 'POST',
data: { data: JSON.stringify(dataItem) },
traditional: true,
success: (msg) => {
layer.msg("添加成功!");
//添加成功后刷新页面
setTimeout(() => {
window.location.reload();
}, 500)
}
})
} else {
//实现修改操作
}
return false;
});
})
复制代码
ES6
方法findIndex
检索ID 如果返回当前ID所在的下标splice
对当前数据删除请求地址 | 类型 | 参数 | 说明 |
---|---|---|---|
/删除 | 得到了 | ID | 要删除某条数据 |
//删除
router.get('/delete', (req, res) => {
//读文件
let data = control.Read();
//检索用户返回index
let userIndex = data.list.findIndex(item => item.id == req.query.id);
// 删除
data.list.splice(userIndex, 1);
//写入文件
control.Write(data);
res.json(data);
})
复制代码
//删除
$('.delete').click(function () {
//获取当前点击得节点上得ID
userID = $(this).attr('data-id');
//使用layui确认弹窗
layer.confirm('确定要删除吗?', {
btn: ['确认', '取消'], btn1: function (index, layero) {
layer.close(index);
//用户点击确认时发送删除请求/delete 传递ID
$.ajax({
url: '/delete',
type: 'GET',
data: { id: userID },
traditional: true,
success: (res) => {
layer.msg("删除成功!");
setTimeout(() => {
window.location.reload();
}, 500)
}
})
}
});
})
复制代码
请求地址 | 类型 | 参数 | 说明 |
---|---|---|---|
/获取信息 | 得到了 | ID | 返回用户要修改的信息 |
/编辑 | 邮政 | ID | 修改用户信息 |
文件:router.js
//读取用户信息
router.get('/getInfo', (req, res) => {
let data = control.Read();
// 用户find 方法查找对应ID 的数据返回给前端
let userInfo = data.list.find(item => item.id == req.query.id);
res.json(userInfo);
})
//修改用户信息
router.post('/edit', (req, res) => {
//拿数据
let getData =JSON.parse(req.body.data);
//读文件
let data = control.Read();
//检索用户返回index
let userIndex = data.list.findIndex(item => item.id == getData.id);
// 更新用户信息
data.list[userIndex] = getData
//写入文件
control.Write(data);
res.json(getData);
})
复制代码
//点击编辑按钮
$(".edit").click(function (e) {
//将全局变量设置为2标识为修改
addEdit = 2
//拿到当前要修改的数据ID
userID = $(this).attr('data-id');
//获取要修改的数据信息,给表单进行赋值操作
$.ajax({
url: '/getInfo',
type: 'get',
data: { id: userID },
traditional: true,
success: (data) => {
let fromData = {
"name": data.name,
"gender": data.gender,
"age": data.age,
"like[xiezuo]": false,
"like[yuedu]": false,
"like[fadai]": false,
"EnterDate": data.EnterDate
}
//给复选框赋值
$('.checkbox-item input').each((index, item) => {
if (data.interest[item.name]) {
fromData[item.name] = true
}
});
//表单赋值
form.val("from", fromData);
},
error: (err) => {
console.log(err, '错误了')
}
})
layer.open({
type: 1,
content: $('#form') //这里content是一个DOM,注意:最好该元素要存放在body最外层,否则可能被其它的相对元素所影响
});
})
复制代码
2.点击提交按钮
//监听提交
form.on('submit(formDemo)', function (data) {
var dataItem = {
"name": data.field.name,
"gender": parseInt(data.field.gender),
"age": parseInt(data.field.age),
"interest": {},
"EnterDate": data.field.EnterDate
};
$('.checkbox-item input').each((index, item) => {
if (item.checked) {
dataItem.interest[item.name] = item.value
}
});
if (addEdit == 1) {
//新增一条数据
} else {
//--------------------------------------确认修改表单---------------------------------//
dataItem.id = parseInt(userID);
$.ajax({
url: '/edit',
type: 'POST',
data: { data: JSON.stringify(dataItem) },
traditional: true,
success: (msg) => {
layer.msg("修改成功!");
setTimeout(() => {
window.location.reload();
}, 500);
}
})
}
return false;
});
复制代码
请求地址 | 类型 | 参数 | 说明 |
---|---|---|---|
/搜索 |
indexOf
方法,对name
领域中的检索关键字如果有就进行push
到临时对象中//搜索
router.get('/search', (req, res) => {
let list = []
//读文件
let data = control.Read();
//检索用户返回index
data.list.forEach((item, index, array)=>{
if(item.name.indexOf(req.query.text)!=-1){
list.push(item)
}
})
//写入文件
// control.Write(data);
res.render('search.html', {
listData: list,
search:req.query.text
});
})
复制代码
文件:search.html
<div class="layui-container layui-layout-admin">
<!----------------------面包屑导航--------------------------->
<div>
<span class="layui-breadcrumb">
<a href="/">首页</a>
<a><cite>搜索</cite></a>
<a><cite>{{search}}</cite></a>
</span>
</div>
<!----------------------搜索表单--------------------------->
<div class=" flex justify-center top-nav">
<form action="/search">
<div class="search flex ">
<input type="text" name="text" placeholder="关键字" class="layui-input input-search " value="{{search}}">
<button class="layui-btn search-butt" type="submit">搜索</button>
</div>
</form>
</div>
<!----------------------搜索关键字--------------------------->
<div class="text">
关键词:{{search}}
</div>
<!----------------------完--------------------------->
<div class="layui-row">
<table class="layui-table">
<colgroup>
<col width="150">
<col width="200">
<col>
</colgroup>
<thead>
<tr>
<th class="layui-center">ID</th>
<th class="layui-center">名称</th>
<th class="layui-center">性别</th>
<th class="layui-center">年龄</th>
<th class="layui-center">兴趣</th>
<th class="layui-center">入学日期</th>
<th class="layui-center">操作</th>
</tr>
</thead>
<tbody>
{{each listData}}
<tr>
<td>{{$value.id}}</td>
<td>{{$value.name}}</td>
<td>{{$value.gender==1?'男':'女'}}</td>
<td>{{$value.age}}</td>
<td>
{{each $value.interest}}
<span>{{$value}}</span>、
{{/each}}
</td>
<td>{{$value.EnterDate}}</td>
<td>
<div class="layui-btn-group">
<button type="button" class="layui-btn layui-btn-sm edit" data-id="{{$value.id}}">
<i class="layui-icon"></i>
</button>
<button data-id="{{$value.id}}" type="button" class="layui-btn layui-btn-sm delete">
<i class="layui-icon"></i>
</button>
</div>
</td>
</tr>
{{/each}}
</tbody>
</table>
</div>
复制代码
这里没有用 Ajax 的判断,这做了一个让用户不能提交的表单
//搜索
$('.search-butt').click(function () {
let text = $('.input-search').val();
if(text==''){
layer.msg("请输入关键字");
return false
}
})
复制代码
联系客服