最近学习 JavaScript、node.js 的总结

大前端全栈的热潮下,最近趁工作不太忙,学习了JavaScript,node.js,做一个小小的Demo来记录一下学习的过程。大佬勿喷。小Demo主要功能是记录用户的个人信息,可以对用户的个人信息进行增删改查。前端页面使用HTML +CSS实现,JavaScript控制逻辑,后台使用node.js实现。下面我分三部分总结一下。

一、前端页面

1.1 页面

网上传着一句话:不会点HTML+CSS都不敢说自己是程序员,所以写了几个简单的页面,也没有什么技术含量,都是div、span、ul、li、input之类的标签。

下图就是我写的页面!

首页无CSS
增加页无CSS

1.2 CSS

哈哈是不是太丑了,那肯定不是有三个星期CSS功力的我写的页面,简单的加入点CSS样式之后,这才是我写的。

首页CSS
增加页CSS
css也就是 margin、padding、width、height等值的配置,当然变成一个高手这些远远不够。

二、前端服务器交互(AJAX)

只是做前端的相比都知道AJAX,这里说说我只怎么处理各个浏览器兼容,并且很高效
问题引出: 犹豫IE低版本不兼容XMLHttpRequest,所以每次调用AJAX就需要判断是否兼容,然后在调用合适的方法,假如浏览器用AJAX调用100个请求,那就要判断100次兼容。所以非常消耗性能和时间。
解决思想: 第一次执行creatXHR函数的时候,需要兼容判断,在判断完成后,直接把创建AJAX函数赋值(这里举例AJAX函数赋值就是A)给creatXHR函数,那么以后调用creatXHR函数的时候执行的就是AJAX函数赋值(A),可以省去其中的兼容性判断。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
function creatXHR() {
var xhr = null,
flag = false,
ary = [
function () {
return new XMLHttpRequest;
},
function () {
return new ActiveXObject("Microsoft.XMLHTTP");
},
function () {
return new ActiveXObject("Msxml2.XMLHTTP");
},
function () {
return new ActiveXObject("Msxml3.XMLHTTP");
}
];
for (var i = 0, len = ary.length; i < len; i++) {
var curFn = ary[i];
try {
xhr = curFn();
creatXHR = curFn;
flag = true;
break;
} catch (e) {
}
}
if (!flag) {
throw new Error("your browser is not support ajax,please change you broser,try again");
}
return xhr;
}

AJAX向服务器端发送请求的四个步骤;

1
2
3
4
5
var xhr = creatXHR();//1、创建对象
xhr.open(_default.type, _default.url, _default.async);//2、请求类型,网址,是否异步
xhr.onreadystatechange = function () {
};//3、状态变化监听函数
xhr.send(_default.data);//4、发送请求

Demo中处理网络请求核心代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
function ajax(option) {
var _default = {
url: "",
type: "get",
dataType: "json",
async: true,
data: null,
getHead: null,
success: null
};
for (var key in option) {
if (option.hasOwnProperty(key)) {
_default[key] = option[key];
}
}
//解决缓存问题
if (_default.type === "get") {
_default.url.indexOf("?") >= 0 ? _default.url += "&" : _default.url += "?";
_default.url += "_=" + Math.random();
}
var xhr = creatXHR();
xhr.open(_default.type, _default.url, _default.async);
xhr.onreadystatechange = function () {
if (/^2\d{2}$/.test(xhr.status)) {
if (xhr.readyState === 2) {
if (typeof _default.getHead === "function") {
_default.getHead.call(xhr);
}
}
if (xhr.readyState === 4) {
var val = xhr.responseText;
if (_default.dataType === "json") {
val = "JSON" in window ? JSON.parse(val) : eval("(" + val + ")");
}
_default.success && _default.success.call(xhr, val);
}
}
};
xhr.send(_default.data);
}

三、后端(node.js)

3.1 环境配置

因为我事先安装好了,所以前两步操作无图(尴尬)
第一步:打开终端,输入以下命令安装Homebrew
ruby -e “$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install);
第二步:安装node,在终端输入以下命令
brew install node
第三步 查看node安装成功与否
node -v
查看是否验证安装node

3.2 node.js的最基本操作

1.node中提供的三个常用的模块

1
2
3
var http = require("http"),
fs = require("fs"),
url = require("url");

2.静态资源文件请求的处理

1
2
3
4
var server = http.createServer(function (req, res) {
// 静态资源文件请求的处理
// 数据接口的处理
});

3.服务创建成功执行回调函数

1
2
3
4
server.listen(8080, function () {
//->当服务创建成功,并且端口号也监听成功之后执行这个回调函数
console.log("server is create success,listening on 8080 port!");
});

3.3 静态资源文件请求的处理

静态资源文件请求的处理其中重要的点是为了兼容,要对请求文件的MIME Type进行匹配。MIME Type是什么?
在浏览器中显示的内容HTML、XML、CSS、PNG、GIF…… 那么,浏览器是如何区分它们,决定什么内容用什么形式来显示?,答案是 MIME Type,也就是该资源的媒体类型。

参考链接:http://tool.oschina.net/commons

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
var server = http.createServer(function (req, res) {
var urlObj = url.parse(req.url, true),
pathname = urlObj.pathname,
query = urlObj.query;
var reg = /\.(HTML|CSS|JS|ICO)/i;
if (reg.test(pathname)) {
var suffix = reg.exec(pathname)[1].toUpperCase();
var suffixMIME = "text/html";
switch (suffix) {
case "CSS":
suffixMIME = "text/css";
break;
case "JS":
suffixMIME = "text/javascript";
break;
}
try {
var 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;
}
});

3.4 API数据接口的处理

这个是Demo实现了数据的增、删、改、查,所以这里简单的对增,删谈谈。

1
2
3
4
5
6
7
// 获取服务器端存储的数据
var customId = null,
customPath = "./json/custom.json",
result = {code: 1, msg: "", data: null},
con = fs.readFileSync(customPath, "utf-8");
con.length === 0 ? con = '[]' : null;
con = JSON.parse(con);

增加一条客户信息的时候要介绍一下node中requestListener的两个监听方法,

1
2
3
4
5
6
7
8
// 在接收到数据的时候调用
req.on("data", function (chunk) {
<!--数据传到服务器不是一次接受到,而是一段一段的数据所以要对数据进行整合 其中参数chunk就是一段一段的数据-->
});
// 在接收数据完成后调用
req.on("end", function () {
<!--数据传递完之后调用,调用之前要先判断数据是否为空-->
});

增加一条客户信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
// 增加一条客户信息相关代码
if (pathname === "/addInfo") {
//->获取客户端通过请求主体传递进来的内容
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: "增加失败,没有传递任何需要增加的信息"
}));
return;
}
var data = JSON.parse(str);
//->在现有的DATA中追加一个ID:获取CON中最后一项的ID,新的ID是在原有基础上加一即可,如果之前一项都没有,我们这一项的ID就是1
data["id"] = con.length === 0 ? 1 : parseFloat(con[con.length - 1]["id"]) + 1;
con.push(data);
fs.writeFileSync(customPath, JSON.stringify(con), "utf-8");
res.end(JSON.stringify({
code: 0,
msg: "增加成功!"
}));
});
return;
}

根据传入的用户ID删除这个用户信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
//3)根据传递进来的客户ID删除这个客户
if (pathname === "/removeInfo") {
customId = query["id"];
var flag = false;
for (i = 0; i < con.length; i++) {
if (con[i]["id"] == customId) {
con.splice(i, 1);
flag = true;
break;
}
}
result.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;
}

四、Demo演示

演示由于服务器中配置的端口号是8080,所以网址的时候需要加上端口号,
现在打开页面(不是本地的页面),通过IP访问。已经不是静态页面了。

Demo演示

因为自己平时学习,所以服务器弄在自己电脑上,所以这里的IP就是我电脑的IP地址。
在终端输入:

1
ifconfig | grep "inet " | grep -v 127.0.0.1

增加操作:
Demo演示

删除操作:
Demo演示

项目地址 麻烦各位大佬给个Starhttps://github.com/leerme/NodeDemo