首先展示一下预览效果以及文件结构:
一、预览效果:
信息列表:
编辑:
新增:
删除:
二、代码结构:
文件说明:1.css文件:存放项目页面样式
2.json:用于项目数据存储
3.index.html:用户列表展示页面
4.add.html:新增|编辑用户信息页面
5.server.js: 启动node服务
github代码下载地址:https://github.com/wyj2443573...
启动方法
:
1.进入crmNode文件,在命令控制台中输入node server.js 来启动服务,出现以下提示代表成功。
2.在终端中输入ipconfig 查看本机联网ip:
3.将ipv4的地址输入到浏览器地址栏中,添加上端口8082,如图所示:
到一步启动完成。
三、代码解析
(1)server.js 文件
主要用于1.启动本地服务 2.写接口文档
用的node模块有:http 、url、fs
接口逻辑:
- 创建服务
根据正则判断(1.静态资源文件请求,2.API数据接口的请求)不同的请求类型做不同的处理
- 如果是静态资源文件请求:用fs去读取文件,然后node服务获取文件内容并返回客户端。
- 如果是API数据接口请求:判断当前操作的接口逻辑是什么(增|删|改|查),然后根据不同的逻辑去写处理方法。总体来说无外乎fs模块操作json文件的读写,http模块将处理后的json文件中的内容返回给客户端。
代码(给出了相关注释如下):
var http=require('http'),
url=require('url'),
fs=require('fs');
var server=http.createServer(function(req,res){
let urlObj=url.parse(req.url,true),
pathname=urlObj.pathname
query=urlObj.query; //query 存储的是客户端请求的url地址中问号传参后面的信息
//静态资源文件请求的处理
let reg=/\.(html|css|js|ico)/i;
if(reg.test(pathname)){
let suffix=reg.exec(pathname)[1].toUpperCase();
let suffixMIME='text/html';
switch(suffix){
case "CSS":
suffixMIME='text/css';
break;
case "JS":
suffixMIME='text/javascript';
break;
}
try{
let conFile=fs.readFileSync('.'+pathname,'utf-8');
res.writeHead(200,{'content-type':suffixMIME+';charset=utf-8;'})
res.end(conFile)
}catch(e){
res.writeHead(404,{'content-type':'text/plain;charset=utf-8;'})
res.end('file is not found');
return;
}
}
//API数据接口的请求
var con=null,
result=null,
customId=null,
customPath='./json/customer.json';
//首先把customer.json中的内容都获取到
con=fs.readFileSync(customPath,'utf-8');
con.length===0?con='[]':null;//为了防止我们custom.json中什么也没有,con也是一个空字符串,我们会使用JSON.parse转换的时候会报错
con=JSON.parse(con);
//1.获取所有的客户信息
if(pathname==='/getList'){
//开始按照API文章的规范给客户端返回的数据
result={
code:1,
msg:'没有任何的客户信息',
data:null
};
if(con.length>0){
result={
code:0,
msg:'成功',
data:con
}
}
res.writeHead(200,{'content-type':'application/json;charset:utf-8'});
res.end(JSON.stringify(result));
return;
}
//2.获取具体某一个客户的信息根据客户id
if(pathname==='/getInfo'){
//把客户端传递进来的ID获取到
customId=query['id'];
result={
code:1,
msg:'客户不存在',
data:null
};
for (var i = 0; i < con.length; i++){
if(con[i]['id']==customId){
con=con[i];
result={
code:0,
msg:'成功',
data:con
}
break;
}
}
res.writeHead(200,{'content-type':'application/json;charset:utf-8'});
res.end(JSON.stringify(result));
return;
}
//3.根据id删除用户
if(pathname==='/removeInfo'){
customId=query["id"];
var flag=false;
for (var i = 0; i < con.length; i++) {
if(con[i]['id']==customId){
con.splice(i,1);
flag=true;
break;
}
}
result={
code:1,
msg:'删除失败'
}
if(flag){
fs.writeFileSync(customPath,JSON.stringify(con),'utf-8');
result={
code:0,
msg:'删除成功'
}
}
res.writeHead(200,{'content-type':'application/json;charset:utf-8'});
res.end(JSON.stringify(result));
return;
}
//4.增加客户信息
if(pathname==='/addInfo'){
//获取客户端通过请求主体传递进来的内容
var str='';
req.on("data",function(chunk){ //chunk实时传输的数据
str+=chunk;
})
req.on("end",function(){ //接收数据完毕
if(str.length===0){
res.writeHead(200,{'content-type':'application/json;charset:utf-8'});
res.end(JSON.stringify({
code:1,
msg:'增加失败,没有传递任何需要增加的信息'
}));
return;
}
var data=JSON.parse(str);
//在现有的id中追加一个ID:获取con中最后一项的ID,ID+1=>新ID
data['id']=con.length===0?1:parseInt(con[con.length-1]['id'])+1;
con.push(data);
fs.writeFileSync(customPath,JSON.stringify(con),'utf-8');
res.writeHead(200,{'content-type':'application/json;charset:utf-8'});
res.end(JSON.stringify({
code:0,
msg:'增加成功'
}));
});
return;
}
//5.修改客户信息
if(pathname==='/updateInfo'){
var str='';
req.on("data",function(chunk){
str+=chunk;
});
req.on("end",function(){
if(str.length===0){
res.writeHead(200,{'content-type':'application/json;charset:utf-8'});
res.end(JSON.stringify({
code:1,
msg:'修改失败,修改信息为空'
}));
}
var data=JSON.parse(str);
var flag=false;
for (var i = 0; i < con.length; i++) {
if(con[i]['id']==data['id']){
con[i]=data;
flag=true;
break;
}
}
if(flag){
fs.writeFileSync(customPath,JSON.stringify(con),'utf-8');
res.writeHead(200,{'content-type':'application/json;charset:utf-8'});
res.end(JSON.stringify({
code:0,
msg:'修改成功'
}));
}
});
return;
}
res.writeHead(404,{'content-type':'text/plain;charset=utf-8'});
res.end(JSON.stringify({
code:1,
msg:'请求接口不存在'
}))
})
server.listen(8082,function(){
console.log('server is success, listening on 8082 port')
})
(2)index. html
主要是按照单例模式写相关事件绑定的方法。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>node撸接口</title>
<link rel="stylesheet" href="css/index.css">
</head>
<body>
<div class="box" >
<a class="addBtn" href="add.html">增加新用户</a>
<h2 class="head">
<span>编号</span>
<span>姓名</span>
<span>年龄</span>
<span>地址</span>
<span>操作</span>
</h2>
<ul class="list" id="list">
</ul>
</div>
<script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script>
<script>
//获取客户信息,完成页面的数据绑定
var customeModule=(function(){
//Bind html
var documentList=document.getElementById('list');
function bindHtml(data){
var str='';
for (var i = 0; i < data.length; i++) {
var curData=data[i];
str+=`<li>
<span>${curData.id}</span>
<span>${curData.name}</span>
<span>${curData.age}</span>
<span>${curData.address}</span>
<span>
<a href="add.html?id=${curData.id}">修改</a>
<a href="javascript:;" cusId="${curData.id}">删除</a>
</span>
</li>`
}
documentList.innerHTML=str;
}
function removeCustomer(){
documentList.onclick=function(e){
var e=e||window.event,
tar= e.target|| e.srcElement,
tarTag=tar.tagName.toUpperCase();
//删除操作
if(tarTag==='A'&&tar.innerHTML==='删除'){
//确认提示框
var customId=tar.getAttribute('cusId'),
flag=window.confirm('确定要删除编号为['+customId+']的客户吗?');
if(flag){
$.ajax({
url:'/removeInfo?id='+customId,
success:function(data){
if(data&&data.code==0){
documentList.removeChild(tar.parentNode.parentNode);
return;
}
alert(data.msg);
}
})
}
}
}
}
//send ajax get data
function init(){
$.ajax({
url:'/getList',
success:function(data){
console.log(data);
if(data&&data.code==0){
var data=data['data'];
//绑定数据
bindHtml(data);
//取消
removeCustomer();
}
}
})
}
return{
init:init
}
})();
customeModule.init();
</script>
</body>
</html>
(3)add.html
通过URL参数判断操作是增加客户信息还是编辑客户信息。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>增加用户</title>
<link rel="stylesheet" href="css/index.css">
<style>
.box2{
width:800px;
margin:50px auto;
font-family:Arial,"PingFang SC","Hiragino Sans GB",STHeiti,"Microsoft YaHei","WenQuanYi Micro Hei",sans-serif ;
font-weight: 700;
border:10px solid #dadada;
text-align: center;
padding:10px;
}
.box2 ul{
width:100%;
overflow: hidden;
}
.box2 ul li{
width:100%;
height:36px;
float:left;
padding:5px;
text-align: center;
}
.box2 .type{
display: inline-block;
width:60px;
height:36px;
line-height: 36px;
}
.inputInfo{
width:600px;
padding:0 10px;
height:36px;
border:1px solid #ddd;
}
.submit{
display: inline-block;
margin:15px auto 0;
width:100px;
height:36px;
background-color: #179a6e;
cursor: pointer;
}
</style>
</head>
<body>
<div class="box2">
<ul>
<li>
<span class="type">姓名:</span>
<input type="text" id="userName" class="inputInfo">
</li>
<li>
<span class="type" >年龄:</span>
<input type="text" id="userAge" class="inputInfo">
</li>
<li>
<span class="type" >地址:</span>
<input type="text" class="inputInfo" id="userAddress">
</li>
</ul>
<button class="submit" id="submit">提交</button>
</div>
</body>
<script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script>
<script>
// 获取URL地址栏的参数值
String.prototype.queryUrlParameter=function(){
var obj={};
var reg=/([^?=&#]+)=([^?=&#]+)/g;
this.replace(reg,function(){
var key=arguments[1];
var value=arguments[2];
obj[key]=value;
})
return obj;
}
var userName=document.getElementById('userName');
var userAge=document.getElementById('userAge');
var userAddress=document.getElementById('userAddress');
var submit=document.getElementById('submit');
//判断修改还是增加:如果url后面传递了ID值就是修改,否则就是增加
var urlBoj= window.location.href.queryUrlParameter(),
customId=urlBoj['id'],
isFlag=typeof customId==='undefined'?false:true; //true->修改 false->增加
//如果是修改,首先需要把对应客户的信息获取到,并且增加到对应的文本框中。
if(isFlag){
$.ajax({
url:'/getInfo?id='+customId,
success:function(data){
if(data&&data.code==0){
var result=data['data'];
userName.value=result['name'];
userAge.value=result['age'];
userAddress.value=result['address'];
}
}
})
}
//点击提交按钮1.增加2.修改
submit.onclick=function(){
var obj={
name:userName.value,
age:userAge.value,
address:userAddress.value
};
//update send ajax
if(isFlag){
console.log('进入修改');
obj.id=customId;
$.ajax({
url:'/updateInfo',
type:'POST',
data:JSON.stringify(obj),
success:function(data){
if(data&&data.code==0){
window.location.href='index.html'
return;
}
alert(data.msg);
}
})
return;
}
//add send ajax
$.ajax({
url:'/addInfo',
type:'POST',
data:JSON.stringify(obj), //请求主体的内容是json格式的字符串
success:function(data){
if(data&&data.code==0){
//成功后跳转回首页
window.location.href='index.html'
}
alert(data.msg);
}
});
}
</script>
</html>
(4)customer.json
[{"name":"Tom","age":"20","address":"北京天通苑","id":"1"},{"name":"Tony","age":"23","address":"北京沙河","id":"2"}]
(5)index.css
*{
margin:0;
padding:0;
}
li{
list-style: none;
}
.box{
width:800px;
margin:50px auto;
font-family:Arial,"PingFang SC","Hiragino Sans GB",STHeiti,"Microsoft YaHei","WenQuanYi Micro Hei",sans-serif ;
font-weight: 700;
border:10px solid #dadada;
}
.addBtn{
color:#179a6e;
font-size:18px;
}
.head{
width:100%;
height:30px;
font-size:16px;
line-height:30px;
background-color: #179a6e;
overflow: hidden;
}
.head span{
display: inline-block;
float:left;
width:20%;
text-align: center;
color:#fff;
position: relative;
}
.head span:after{
content:'';
position:absolute;
width:1px;
height:30px;
background-color: #fff;
right:0;
top:0;
}
.list{
width:100%;
}
.list li{
width:100%;
height:36px;
line-height: 36px;
overflow: hidden;
border-bottom:1px solid #ddd;
cursor: pointer;
}
.list li:hover{
background-color: #fafafa;
}
.list li span{
display: inline-block;
width:20%;
float:left;
text-align: center;
overflow: hidden;
text-overflow: ellipsis;
white-space:nowrap;
}