标准js风格:
https://standardjs.com/readme-zhcn.html一.如何运行
- 安装vscode对应插件
![v2-2ebcd784a8d3f69457159f5a672d55a4_b.jpg](https://i-blog.csdnimg.cn/blog_migrate/b4ca8b8cabd0858e5d5693ed0ff2cab1.png)
2. 在文件中右键运行
![v2-93d35412e17d41ec28326454ee87bbaf_b.jpg](https://i-blog.csdnimg.cn/blog_migrate/3a7c4a74d65c0991396d23aea368375b.png)
3. 输入 node app或者node app.js运行
![v2-d01bed0dfb7531f1069d96711aece511_b.jpg](https://i-blog.csdnimg.cn/blog_migrate/6233eccb948397ae78c6298de2c7ec4a.png)
附:vscode如何实现代码提示:
CSDN-专业IT技术社区-登录 cnpm install --save @types/node
4.如何在控制台中调试node 的API
任意目录下输入node,进入node环境就可以进行API测试了
![v2-b6578c70a928040c7683ec2b542dbc20_b.jpg](https://i-blog.csdnimg.cn/blog_migrate/9bf91b2b3c1a4d625c02ab5fbd5c7475.png)
二. node中的JS
1.没有DOM和BOM
2.控制台输出 console.log()
输出项目文件夹地址 console.log(__dirname);
输出项目文件地址 console.log(__filename);
3.定时执行
setTimeout(() => {
console.log("time's up")
}, 3000);
4.定时循环执行
var time=0;
timer1 = setInterval(() => {
time += 2
console.log(time + " s passed!")
if (time > 5)
clearInterval(timer1);
}, 2000);
5. 核心模块
node专门为JS提供了很多服务器级别的API.这些API绝大多数都被包装到了一个具名的核心模块中.如 文件操作的fs核心模块,http服务构建的http模块,path路径操作模块,os操作系统信息模块.
引用方法
var 模块别名 =require('模块名')
6. 自定义模块
直接require(./模块名) // 其中./表示相对路径同路径
7.作用域
在node中没有全局作用域,只有模块作用域.模块之间互不影响.
8.导出 //模块之间通讯
每个文件中都提供了一个对象叫:exports
当文件被require时,不仅会执行模块,还会接受文件的导出
三. 最简单的读写文件
1.读文件
读写文件我们要引用fs核心模块
fs.readFile(path: string | number | Buffer | URL, callback: (err: NodeJS.ErrnoException, data: Buffer) =>void): void (+3overloads)
namespacereadFile
var fs=require('fs')
var rev=fs.readFile("./xiaojiejie.txt",function(err,data){
console.log(data.toString());
});
![v2-2471800d5455445c5d60ca0b20bf2300_b.jpg](https://i-blog.csdnimg.cn/blog_migrate/cea8fda4d9088ab6881bef901f3f3295.jpeg)
2.写文件
fs.writeFile(path: string | number | Buffer | URL, data: any, callback: NoParamCallback): void (+1overload)
namespacewriteFile
var fs = require('fs')
fs.writeFile("./xiaojiejie.txt", '5.芙蓉姐姐', (err) => {
if (!err) console.log("写入成功!");
});
fs.readFile("./xiaojiejie.txt", function (err, data) {
console.log(data.toString());
});
![v2-06892220a4a7fcde9f29947f55cdca3f_b.jpg](https://i-blog.csdnimg.cn/blog_migrate/d9dcd56a810e289e5d57c1513c8edda9.png)
3.读取目录
fs.readdir('地址',(err,strs)=>{}) //strs是一个字符串列表
fs.readdir(wwwDir, (err, strs) => {
if (err) return console.log(err);
for (let index = 0; index < strs.length; index++) {
console.log(strs[index]);
};
});
四. 最简单的的http服务
http服务我们要引用http核心模块
function createServer(requestListener?: RequestListener): Server (+1overload)
http.createServer()
server.on("request",function(request,responce){}//responce响应内容只能是二进制文件或字符串
server.listen(3000,function(){}) //80端口号是浏览器默认访问的
//引用http核心模块
var http = require('http');
//实例化一个server实例
var server = http.createServer();
server.on("request", function (request,responce) {
console.log("收到客户端的请求了,请求路径是:"+request.url);//服务器收到的请求
//responce.write("hello");//服务器返回给客户端的回应
//responce.end(); //回应必须告知客户端结束
responce.end("hello"); //上面两句的简写
})
//监听端口号,启动服务
server.listen(3000, () => {
console.log("服务器启动成功");
});
附:JSON列表字符串化
var products = [
{
product: "iphone",
price: "8888"
},
{
product: "ipad",
price: "3000"
},
{
product: "macbook",
price: "11000"
}
]
str=JSON.stringify(products);
3.通过responce让客户端重定向
(1). responce将状态码设置为302(临时重定向)
(2). 客户端收到302后会去响应头中的Location处寻找重定向页面,并发起新的请求.
(3). 记得结束响应
rsp.statusCode=302
rsp.setHeader('Location','/')
rsp.end()
五. 最简单的模块调用
对于调用文件:使用require调用模块,同时还会接收模块中暴露的内容
对于被调用文件:使用exports来暴露想传递的参数或方法
例如:a.js
var b=require('./b')
console.log(b);
console.log(b.add(10,30));
b.js
var foo="bbb";
function add(x,y){return x+y;}
exports.add=add;
exports.foo=foo;
![v2-5ab3f8e16199be5646ef7172c86a5d92_b.jpg](https://i-blog.csdnimg.cn/blog_migrate/9c55fa8dd68493e1642bc2140cbdebf4.png)
六.获取IP地址和端口号
1.每个通讯的软件都需要一个端口号,取值范围0~65535,
2.端口号有些被默认使用了,应该注意不要用80等已占用的
3.可以开启多个服务,但一定要确保不同服务占用的端口号不一致才可以
4.服务器默认发送数据是utf8编码的内容,但浏览器在不指定编码格式情况下会按照操作系统去解析,中文系统中是'gbk' ,应手动设置为utf-8
rsp.setHeader('Content-Type','text/plain;charset=utf-8')
text/plain 是普通文本,如果返回的是html元素则 text/html 详见下一节
//引用http核心模块
var http = require('http');
//实例化一个server实例
var server = http.createServer();
server.on("request", function (request, responce) {
console.log("收到客户端的请求了,请求路径是:" + request.url);//服务器收到的请求
console.log("客户端的端口号是:"+request.socket.remotePort);
console.log("客户端的IP是:"+request.socket.remoteAddress);
})
//监听端口号,启动服务
server.listen(3000, () => {
console.log("服务器启动成功");
});
![v2-17246c66f628867e291e9224feb1374c_b.jpg](https://i-blog.csdnimg.cn/blog_migrate/69ea8789f7f3fc6bce78dd6654224612.jpeg)
七. 服务器发送文件及Content-Type
1.发送文件中的数据
发送文件中的数据要结合fs模块使用,
2.Content-Type文件格式
不同的资源对应的Content-Type是不一样的
rsp.setHeader('Content-Type','text/plain;charset=utf-8')
text/plain部分其实是在声明返回的字符串其实是什么资源,具体怎么用参照下面的网页:
HTTP Content-type 对照表 var http = require('http');
var fs = require('fs');
var sever = http.createServer();
sever.on("request", (req, rsp) => {
console.log(req.url);
if (req.url =="/") {
fs.readFile("./res/index.html",(err,data)=>{
if (err) {
console.log(err);
rsp.setHeader('Content-Type', 'text/plain;charset=utf-8');
rsp.end("访问出错,原因:"+err);
}else{
rsp.setHeader('Content-Type', 'text/html;charset=utf-8');
rsp.end(data);
}
})
};
if (req.url =="/image") {
fs.readFile("./res/8.jpg",(err,data)=>{
if (err) {
console.log(err);
rsp.setHeader('Content-Type', 'text/plain;charset=utf-8');
rsp.end("访问出错,原因:"+err);
}else{
rsp.setHeader('Content-Type', 'image/jpeg');//图片就不需要指定编码了!
rsp.end(data);
}
})
};
if (req.url =="/txt") {
fs.readFile("./res/xiaojiejie.txt",(err,data)=>{
if (err) {
console.log(err);
rsp.setHeader('Content-Type', 'text/plain;charset=utf-8');
rsp.end("访问出错,原因:"+err);
}else{
rsp.setHeader('Content-Type', 'text/plain;charset=utf-8');
rsp.end(data);
}
})
};
}
);
sever.listen(3000, () => {
console.log("the server is good to request!");
})
八. 将文件与url对应起来
apache服务器软件中默认有一个www文件夹,里面的资源均可通过url来访问
var http = require('http')
var fs = require('fs')
var wwwDir = "./www"
var server = http.createServer();
server.on('request', (req, rsp) => {
console.log(req.url);
var filePath='/index.html'
if(req.url !=='/') filePath=req.url
fs.readFile(wwwDir + filePath, (err, data) => {
if (err) return rsp.end("failed to read the file");
rsp.end(data);
})
})
server.listen(3000, () => {
console.log("on");
})
九. node中使用art-template模板引擎进行服务端渲染
art-template1.安装
安装:在项目文件夹执行:
npm install art-template --save
![v2-2d25c666f8a77f8742956e5344e4e8fa_b.jpg](https://i-blog.csdnimg.cn/blog_migrate/e3b6ef185c80d147c9152c39265462d1.jpeg)
2.引包
var template=require('art-template')
3.模板标记语法
模板引擎不关心内容,只关系它能认识的模板标记语法,例如{{}}
(1).template.render(str,{键值对}) //返回新的str
例子:index2.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>
</head>
<body>
<h1>欢迎新同学!</h1>
<h2>姓名:{{name}}</h2>
<h2>年龄:{{age}}</h2>
<h2>性别:{{sex}}</h2>
<h3>爱好:{{hobbies}}</h3>
</body>
</html>
app.js
var http = require('http')
var fs = require('fs')
var template = require('art-template')
var wwwDir = "./www"
var server = http.createServer();
function addHtml(str, stuName, stuAge, stuSex, stuHobbies) {
nstr = template.render(
str,
{
name: stuName,
age: stuAge,
sex: stuSex,
hobbies: stuHobbies
}
);
return nstr;
}
server.on('request', (req, rsp) => {
console.log(req.url);
var filePath = '/index2.html'
if (req.url !== '/') filePath = req.url
if (filePath = '/index2.html') {
stuhtml = addHtml("lili", "18", "girl");
fs.readFile(wwwDir + '/index2.html', (err, data) => {
if (err) return err;
str = data.toString()//
str = addHtml(str, 'lili', '18', 'girl', ['吃饭', '睡觉', '拯救世界']);
console.log(str);
fs.writeFile(wwwDir + '/index2.html', str, () => {
fs.readFile(wwwDir + filePath, (err, data) => {
if (err) return rsp.end("failed to read the file");
rsp.end(data);
})
});
})
}
})
server.listen(3000, () => {
console.log("on");
})
![v2-ae657dd10e43994cdd2051997a3ae621_b.jpg](https://i-blog.csdnimg.cn/blog_migrate/076da71ba31295221f7b760989c4f879.png)
综合练习中有更多用法.
十.url核心模块
1.引用模块
var http = require('http')
2.url解析URL
url.parse('http://127.0.0.1:3000/comment?name=%E5%95%8A&msg=%E5%95%8A%E5%95%8A')
![v2-3770e1d0d412c919bc71855c61935a32_b.jpg](https://i-blog.csdnimg.cn/blog_migrate/8faefabab6d7d729c9f894225117654a.jpeg)
其中:
search:查询字符串, query:不含?的查询字符串
pathname:不包含查询字符串的路径
进一步解析:
url.parse('http://127.0.0.1:3000/comment?name=%E5%95%8A&msg=%E5%95%8A%E5%95%8A',true)
![v2-4d3bf9fe09257a1b5d74f2fef995d7ff_b.jpg](https://i-blog.csdnimg.cn/blog_migrate/cab26ad3379ebe8731c7c811cb0831c7.png)
query解析成对象了
十一. 获取时间
1.npm安装模块
npm install silly-datetime
![v2-c1a0a5583f763197087bd663a8f9e9cc_b.jpg](https://i-blog.csdnimg.cn/blog_migrate/094e0778bb15dcb61cbf8132ec256fab.jpeg)
2.在JS中的应用
var sd = require('silly-datetime');
var time=sd.format(new Date(), 'YYYY-MM-DD HH:mm:ss');
console.log(time);
3.具体用法
var myDate = new Date();
myDate.getYear(); //获取当前年份(2位)
myDate.getFullYear(); //获取完整的年份(4位,1970-????)
myDate.getMonth(); //获取当前月份(0-11,0代表1月)
myDate.getDate(); //获取当前日(1-31)
myDate.getDay(); //获取当前星期X(0-6,0代表星期天)
myDate.getTime(); //获取当前时间(从1970.1.1开始的毫秒数)
myDate.getHours(); //获取当前小时数(0-23)
myDate.getMinutes(); //获取当前分钟数(0-59)
myDate.getSeconds(); //获取当前秒数(0-59)
myDate.getMilliseconds(); //获取当前毫秒数(0-999)
myDate.toLocaleDateString(); //获取当前日期
var mytime=myDate.toLocaleTimeString(); //获取当前时间
myDate.toLocaleString( ); //获取日期与时间
十二.综合案例:留言板
![v2-1bd4b1813f7143a66b3c621a2df2d463_b.jpg](https://i-blog.csdnimg.cn/blog_migrate/7a22a942949d7dd2a3245ee9099f0019.png)
![v2-485f6fc1e683dd5a43804a689520918a_b.jpg](https://i-blog.csdnimg.cn/blog_migrate/0e1aebf5d645e104382967169eb2cb1f.png)
1.目录结构
![v2-0fbcd52416d939311c669257b2024878_b.png](https://i-blog.csdnimg.cn/blog_migrate/dcb63d76d8ae672aa03ea5ef7272554f.png)
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>留言板</title>
<!-- 最新版本的 Bootstrap 核心 CSS 文件 -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css"
integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<!-- 最新的 Bootstrap 核心 JavaScript 文件 -->
<script src="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/js/bootstrap.min.js"
integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa"
crossorigin="anonymous"></script>
<style type="text/css">
* {
margin: 0;
padding: 0;
font-family: arial, "微软雅黑";
}
header {
margin-top: 30px;
}
body {
margin-left: 80px;
margin-right: 80px;
}
a {
margin-top: 10px;
margin-bottom: 10px;
background-color: #4CAF50;
/* Green */
border: none;
color: white;
padding: 6px 10px;
text-align: center;
text-decoration: none;
display: inline-block;
font-size: 10px;
border-radius: 5px;
}
ul {
padding-top: 10px;
border-top: 1px solid #eee;
}
li {
border: solid;
border-bottom: none;
border-width: 1px;
border-color: #eee;
list-style: none;
padding: 10px;
}
li:last-of-type {
border-bottom: 1px solid #eee;
}
#title {
font-size: 30px;
}
#subtitle {
font-size: 16px;
color: #999;
margin-left: 10px;
}
</style>
</head>
<body>
<header>
<b id="title">留言板</b>
<b id="subtitle">留言板</b>
</header>
<a href="/post">发表留言</a>
<body>
<div>
<ul>
{{each comments}}
<li>
{{$value.name}}说: {{$value.msg}}
<span class="pull-right">{{$value.dateTime}}</span>
</li>
{{/each}}
</ul>
</div>
</body>
<footer>
</footer>
</body>
</html>
3.post.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>提交留言</title>
<!-- 最新版本的 Bootstrap 核心 CSS 文件 -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css"
integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<!-- 最新的 Bootstrap 核心 JavaScript 文件 -->
<script src="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/js/bootstrap.min.js"
integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa"
crossorigin="anonymous"></script>
<style>
* {
margin: 0;
padding: 0;
font-family: arial, "微软雅黑";
}
header {
margin-top: 30px;
}
body {
margin-left: 100px;
margin-right: 100px;
}
.clearfix:after {
content: "";
display: block;
clear: both;
}
#title {
font-size: 30px;
color: rgb(38, 151, 196);
}
#subtitle {
font-size: 16px;
color: #999;
margin-left: 10px;
}
</style>
</head>
<body>
<header>
<b id="title">留言板</b>
<b id="subtitle">留言板</b>
<hr>
</header>
<body>
<form action="/comment">
<div class="form-group">
<label for="name">你的大名</label><br>
<input name="name" type="text" id="name" class="from-control" placeholder="请输入您的名字">
</div>
<div class="form-group">
<label for="name">你的留言</label><br>
<textarea name="msg" id="" cols="30" rows="10" ></textarea>
</div>
<button type="submit" class="btn btn-default">留言</button>
</form>
</body>
<footer>
</footer>
</body>
</html>
4.最关键的app.js服务脚本
var http = require('http') //http核心组件 实例化服务
var fs = require('fs') //fs核心组件 文件操作
var template = require('art-template') //art-template模板引擎组件,需npm安装
var url = require('url') //url核心组件 url解析
var sd = require('silly-datetime');//silly-datetime时间组件,需npm安装
var wwwDir = "./views" //html放在此文件夹中
var comments = [] //由于没有数据库,建立一个数组来保持评论信息
var server = http.createServer();//实例化一个服务
server.on('request', (req, rsp) => { //接受请求处理函数
var obj = url.parse(req.url, true) //将请求的url转为一个对象
if (obj.pathname === '/') { //默认返回index页面
fs.readFile( //读取对应的html模板文件
wwwDir + '/index.html',
(err, data) => {
if (err) return rsp.end(err);//如果读取失败就报错
var revStr = template.render(data.toString(), { comments: comments })
// template.render渲染模板文件套入数据,data.toString()是fs读取的html数据
rsp.end(revStr);//将处理好的数据(字符串)响应给客户端
}
);
} else if (obj.pathname === '/post') {//处理post页面
fs.readFile(
wwwDir + '/post.html',
(err, data) => {
if (err) return err;
rsp.end(data);
}
)
} else if (obj.pathname === '/comment') { //如果是comment,则证明此为客户端提交数据
comments.unshift({ //将客户端提交的数据写在comments中
name: obj.query.name,
msg: obj.query.msg,
dateTime: sd.format(new Date(), 'YYYY-MM-DD HH:mm:ss')//处理时间
})
rsp.statusCode=302 //给客户端一个302状态码,让它重定向
rsp.setHeader('Location','/') //设定重定向地址
rsp.end() //别忘了结束响应
} else {
rsp.end('404 not found') //这个else是访问不存在页面的处理,
}
})
//开启监听3000窗口
server.listen(3000, () => {
console.log("listening.....");
})