1.前端最主流的JavaScript运行环境
1>Node.js是一个基于Chrome V8引擎的JavaScript运行环境。
2>Node.js使用了一个事件驱动、非阻塞式I/O的模型,使其轻量又高效。
3>Node.js的包管理器npm,是全球最大的开源库生态系统。
2.工作原理
V8引擎
模块
事件队列
文件系统
...
3.V8引擎
引擎:电脑根本不识别也不理解JavaScript,JS引擎的作用是使电脑能够识别JS代码
NodeJS是使用C++写的
V8引擎是Node.js的核心
V8引擎的作用就是让JS代码能够被电脑识别
4.Module & Require
```
stuff.js
var adder = function(a,b){
var result = `结果是:${ a + b }`;
return result;
}
var PI = 3.14;
module.exports = {
adder: adder,
PI: PI
}
main.js
var stuff = require("./stuff");
stuff.adder(10,stuff.PI);
```
5.事件模块 Events
1>大多数Node.js核心API都是采用惯用的异步事件驱动架构(fs/http)
2>所有能触发事件的对象都是EventEmitter类的实例
3>事件流程:引入模块——创建EventEmitter对象——注册事件——触发事件
```
eg:
const EventEmitter = require("events"); //引入事件模块
class MyEmitter extends EventEmitter{}; //创建EventEmitter对象
const myEmitter = new MyEmitter();
//var myEmitter = events.EventEmitter();
myEmitter.on("someEvent",(msg)=>{ //注册事件
setImmediate(function(){ //IE,把一个需要长时间运行的操作放在一个回调函数里,在浏览器完成后面的其他语句后,就立即执行这个回调函数
console.log(msg);
});
});
myEmitter.emit("someEvent","实现事件并传递此参数到注册事件的回调函数中"); //触发事件
```
6.文件系统
读取文件 fs.readFile
写入文件 fs.writeFile
流程:引入fs模块——调用方法——异常捕获
```
eg: var fs = require("fs");
var readMe = fs.readFileSync("readMe.txt","utf8"); //同步读取文件
fs.writeFileSync("writeMe.txt",readMe); //同步写入
fs.readFile("readMe.txt","utf8",function(err,data){ //异步读取文件
if(err){
throw err;
}
console.log(data);
fs.writeFile("writeMe2.txt",data); //异步写入
})
const fs = require("fs");
//删除文件
fs.unlink("writeMe2.txt",function(err){
if(err){
throw err;
}
console.log("文件删除成功");
});
//创建文件夹同步
fs.mkdirSync("stuff");
//删除文件夹 同步
fs.rmdirSync("stuff");
//异步创建文件夹
fs.mkdir("stuff",function(){
fs.readFile("readMe.txt","utf8",function(err,data){
if(err){
throw err;
}
fs.writeFile("./stuff/writeMe.txt",data);
})
})
//异步删除文件夹——先删除文件,再删除外部文件夹
fs.unlink("./stuff/writeMe.txt",function(){
fs.rmdir("stuff",function(err){
if(err){
throw err;
}
console.log("文件夹删除成功");
});
});
```
7.Http创建服务器
通过Http模块搭建本地服务器
```
const http = require("http");
//创建本地服务器
var srv = http.createServer((req,res)=>{
res.writeHead(200,{"Content-Type":"text/plain"});
res.end("Server is working!");
});
//监听本地端口
srv.listen(8888,"127.0.0.1",()=>{
});
srv.on("upgrade",(req,socket,head)=>{
socket.write('HTTP/1.1 101 Web Socket 协议握手\r\n' +
'升级:WebSocket\r\n' +
'连接:升级\r\n' +
'\r\n'
);
socket.pipe(socket);
});
```
8.缓存区 & 流
缓存区:Buffer,可以在TCP流和文件系统操作等场景中处理二进制数据流。
Buffer,全局对象,无需单独引入。
流:Stream, NodeJS中处理流数据的抽象接口
1>读写数据流
```
const fs = require("fs");
//读取文件流
var myReadStream = fs.createReadStream(__dirname + "/readMe.txt","utf8");
//后台服务器自动触发
myReadStream.on("data",function(chunk){
console.log("=======正在接收一部分数据======");
console.log(chunk);
});
//写入文件流
var myWriteStream = fs.createWriteStream(__dirname + "/writeMe.txt");
var time = 0;
myReadStream.on("data",function(chunk){
time++;
console.log("=======正在接收" + time + "一部分数据======");
myWriteStream.write(chunk);
});
//输出到浏览器
var http = require("http");
var fs = require("fs");
var server = http.createServer(function(req,res){
if(req.url != "/favicon.ico"){ //防止发送favicon的请求
res.writeHead(200,{"Content-type":"text/html"});
var myReadStream = fs.createReadStream(__dirname + "/index.html","utf8");
}
});
server.listen(3000,"127.0.0.1");
console.log("Server is running ...");
```
2>读取HTML & JSON
```
res.writeHead(200,{"Content-type":"text/plain"});
res.writeHead(200,{"Content-type":"text/html"});
res.writeHead(200,{"Content-type":"application/json"});
```
9.路由Route
```
var http = require("http");
var fs = require("fs");
var server = http.createServer(function(req,res){
if(req.url !== "/favicon.ico"){
//判断用户所访问的页面地址
if(req.url == "/home" || req.url == "/"){
res.writeHead(200,{"Content-type":"text/html"});
fs.createReadStream(__dirname + "/index.html").pipe(res);
}else if(req.url == "/contact"){
res.writeHead(200,{"Content-type":"text/html"});
fs.createReadStream(__dirname + "/contact.html").pipe(res);
}else if(req.url == "/api/docs"){
var data = [{name:"Henny",age:"30"},{name:"Jack",age:"28"}];
res.writeHead(200,{"Content-type":"application/json"});
res.end(JSON.stringify(data));
}
}
});
```
10.NPM
Node Package Manager
Package.json
用于定义项目中所需要的各种模块,以及项目的配置信息(比如版本名称、版本、许可证等元数据)
npm install ** -g
npm install ** --save
npm install ** --save -dev
npm uninstall **
11.Express框架和nodemon
Express框架
已经封装好服务器
已经封装好路由
已经封装好中间件
已经封装好网络请求...
NPM安装Express框架——引入Express模块——实例化Express的对象——通过对象调用各种方法
```
//引入express模块
var express = require("express");
//实例化express对象
var app = express();
//通过对象调用对应的方法
app.get("/",function(req,res){
console.log(req.url);
res.send("This is home page!");
res.sendFile(__dirname + "/index.html");
});
app.get("/contact",function(){
console.log(req.url);
res.send("This is contact page!");
});
//路由参数
app.get("/profile/:id",function(req,res){
res.send("您所访问的路径参数为:" + req.params.id);
});
//监听服务器端口号
app.listen(8888);
```
12.EJS模板引擎
特点:
快速编译和渲染
简单的模板标签
支持浏览器端和服务器端
支持express视图系统
```
npm install ejs --save -dev
//引入express模块
var express = require("express");
//实例化express对象
var app = express();
//配置视图引擎为EJS
app.set("view engine","ejs");
//通过对象调用对应的方法(响应html文件)
app.get("/",function(req,res){
console.log(req.url);
res.sendFile(__dirname + "/index.html");
});
//返回ejs文件用render而非sendFile
app.get("/contact",function(){
console.log(req.url);
res.render(__dirname + "/contact.html");
});
//路由参数
app.get("/profile/:id",function(req,res){
res.render("profile",{ websiteName:"hello world!" }); //自动找到views下的profile.ejs
});
app.get("/profile/:id",function(req,res){
var data = {age:29,name:"Henry"};
//var data = [{age:29,name:"Henry"},{age:30,name:"Jack"}]
res.render("profile",{ websiteName:req.params.id },data:data); //自动找到views下的profile.ejs
});
//监听服务器端口号
app.listen(8888);
views/profile.ejs
<h1>EJS模板:Welcome To <%= websiteName %> page! </h1>
<p><strong>Name:</strong> <%= data.name %></p>
<p><strong>Age:</strong> <%= data.age %></p>
<ul>
<% data.forEach(function(item){ %>
<li><%= item %></li>
<% })%>
</ul>
```
13.公共模板
使用EJS替代HTML(根据模板引擎确定)
创建导航(公共模板)
解决外部样式不可用的问题(外部样式表无法在服务中运行)
```
public/nav.ejs (模板文件只能有一个根标签)
<nav>
<ul>
<li><a href="/">主页</a></li>
<li><a href="/contact">联系</a></li>
</ul>
<nav>
views/contact.ejs
<body>
<% include ../public/nav.ejs %>
<h1>Welcome to 联系我们页面!</h1>
<p>电话:40080000</p>
</body>
//让服务器识别外部样式表(使用use中间件)
app.use("/assets",express.static("assets"));
```