NodeJS基础入门

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 协议握手
' +
        '升级:WebSocket
' +
        '连接:升级
' +
        '
'
    );
    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"));
```
原文地址:https://www.cnblogs.com/nanhuaqiushui/p/9498012.html