首先展示一下预览效果以及文件结构:
一、预览效果:
信息列表:
编辑:
新增:
删除:
二、代码结构:
文件说明: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:
三、代码解析
(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
主要是按照单例模式写相关事件绑定的方法。
node撸接口
(3)add.html
通过URL参数判断操作是增加客户信息还是编辑客户信息。
增加用户
-
姓名:
-
年龄:
-
地址:
(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;
}