大前端全栈的热潮下,最近趁工作不太忙,学习了JavaScript,node.js,做一个小小的Demo来记录一下学习的过程。大佬勿喷。小Demo主要功能是记录用户的个人信息,可以对用户的个人信息进行增删改查。前端页面使用HTML +CSS实现,JavaScript控制逻辑,后台使用node.js实现。下面我分三部分总结一下。
一、前端页面
1.1 页面
网上传着一句话:不会点HTML+CSS都不敢说自己是程序员,所以写了几个简单的页面,也没有什么技术含量,都是div、span、ul、li、input之类的标签。
下图就是我写的页面!


1.2 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

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访问。已经不是静态页面了。

因为自己平时学习,所以服务器弄在自己电脑上,所以这里的IP就是我电脑的IP地址。
在终端输入:
1
| ifconfig | grep "inet " | grep -v 127.0.0.1
|
增加操作:

删除操作:

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