NodeJs學習一NodeJs初識

1、前言javascript

  按照慣例,先扯淡,就由於這貨,如今纔有了各大公司招聘的全棧工程師,正是由於它,讓之前只會寫前端的人也能寫起後端服務器代碼來了。因此呢,你招一個會NodeJs的前端,它都能把後端幹了,一我的幹了兩我的的事,你說哪一個公司不想要。可是我仍是要同情一下前端的兄弟們,真是苦了大家了,之前大家只是寫頁面就完了,如今還得寫後臺,再加上各類前端框架,什麼Vue,Angular,React啊,恭喜大家,如今微信又帶了一波小程序的節奏,唉,可憐的娃啊。html

  

  NodeJs看着也帶Js後綴,可是它和VueJs,Angular,ReactJs可不同,後三個都是框架,而NodeJs是平臺,運行時環境。怎麼說呢,就是NodeJs之於JavaScript,就比如jvm之於Java,就比如CLR之於c#,而Vue,Angular,React之於JavaScript就比如於 SpringMVC 之於Java,Asp.Net MVC,這個栗子舉得應該是十分清楚了吧。也就是說通常的js都是在瀏覽器上執行,能力也有限,只能操做瀏覽器上邊的東西,不能夠讀寫你操做系統的文件什麼的,而配上node環境的js是在你電腦上執行,能夠讀寫你操做系統的文件啥的,一不當心還能把你的操做系統中的東西都給你刪除了,多可怕。前端

  但凡一個東西火了,咱們要用它,因此它必有過人之處,也必有好的地方。因此呢,NodeJs好的地方就是 :java

  1.用JavaScript做爲服務器端語言,這東西火啊,誰都會,簡直沒有學習成本,只用背幾個api就好了啊。node

  2.統一先後端啊,全棧開發只須要學習一門語言,老闆高興了,招幾個前端啥都有了,你給我寫寫寫寫寫(爲前端同窗默哀3分鐘)。web

  3.擅長處理高併發,作網站和文件讀寫相關的應用很不錯。mongodb

  4.參看前三點。(暫時還想不起來,僞裝有第四點)數據庫

   I am very 皮。express

2、關於NodeJs的介紹npm

 咱們先來看NodeJs官方給的介紹

  2.1 第一句話

  Node.js® is a JavaScript runtime built on Chrome's V8 JavaScript engine. 說NodeJs是一個基於谷歌V8JavaScript解析引擎的一個JavaScript 運行時。(聽說V8是目前最快的js 解析引擎,畢竟大廠出品,值得信賴)。

  2.2 第二句話

  Node.js uses an event-driven, non-blocking I/O model that makes it lightweight and efficient. 說NodeJs採用了事件驅動,非阻塞的IO模型,因此很輕,效率也很高。(因此處理併發很給力)

   2.3 第三句話

   Node.js' package ecosystem, npm, is the largest ecosystem of open source libraries in the world.  說NodeJs的包生態系統,npm,是世界上最大的開源庫生態系統。(厲害了,個人哥)

3、Node中的JavaScript

   3.1 沒有BOM和DOM

  衆所周知,as we know,瀏覽器中的JavaScript是有dom和bom的,由於這樣才能夠操做html和瀏覽器相關的東西,好比document對象,window對象的,可是在Node中的js是沒有這些對象的,由於很顯然,不須要操做html和瀏覽器,由於壓根在服務器端就沒有這些東西。

 

    

 

    如圖所示,在node中沒有window和document對象,輸出時就會報錯。

 

  3.2 提供了一些服務器級別的API

  除了沒有dom和bom一說,在語法上是同樣的,都是基於ECMAScript的,另外的是Node提供了一些服務器級別的api,好比操做文件、網絡請求,http什麼的,這些在瀏覽器端的js是沒有這些功能的。

  3.3 Node中的模塊系統

  Node中沒有全局做用於的概念,在 Node 中,只能經過 require 方法來加載執行多個 JavaScript 腳本文件,默認每一個文件就是一個模塊,兩個模塊中的變量不會有污染問題,也就是說兩個文件中能夠有相同的變量,可是在瀏覽器中的js是不容許這樣作的。若是你同時在a.js 和b.js中聲明 var foo  = 'bar' ;這在Node中是容許的。可是在瀏覽器中就會報錯。

  

    能夠看出,在a.js中輸出foo,是a的值,在b.js中調用add方法,結果是b中的add函數在起做用,由此能夠看出,模塊之間不存在變量污染問題,每一個模塊都是獨立的做用域。

    Node中經過require加載並執行其中的代碼,文件與文件之間因爲是模塊做用域,因此不會有全局污染的問題,模塊是徹底封閉的,外部沒法訪問內部,內部也沒法訪問外部。

    可是模塊之間是須要通信的,Node爲每一個文件(也就是模塊)提供了一個exports對象,默認狀況下,該對象是一個空對象,你要作的就是把須要外部訪問使用的成員手動掛載到exports接口對象中,而後誰來require這個模塊,返回值就是模塊內部的exports對象。

//a.js
var b = require('./b.js');
console.log(b);

//b.js
var foo = 'b foo';
function add(x, y) {
    return x - y;
}

//運行後輸出
{}

  能夠看出require的返回值是一個空對象,也就是b.js中的exports對象,接下來咱們對exports對象進行操做,看看會有什麼結果。

//a.js
var b = require('./b.js');
console.log(b);

//b.js
var foo = 'b foo';
function add(x, y) {
    return x - y;
}
exports.foo = foo;
exports.add = add;

//運行後輸出 
{
    foo:'b foo',
    add:[Function:add]
}

  能夠看出返回的對象裏邊已經有了咱們賦值的屬性。這樣,咱們就可使用這些屬性和功能,就能夠進行模塊之間的通信。

  3.4 Node中的核心模塊

     核心模塊是由Node提供的一個個具備名字的模塊,它們都有本身特殊的名稱標識,例如: fs 文件操做模塊、http 網絡服務構建模塊、os 操做系統信息模塊、path 路徑處理模塊等等。全部核心模塊在使用的過程當中必須手動的用require方法來加載,例如使用文件系統模塊,var fs = require('fs');    

var http = require('http');
var fs = require('fs');
var os = require('os');
var path = require('path');
console.log(http,fs,os,path);

4、傳說中的四行代碼開發Web服務器

var http = require('http'); //加載http模塊

var server = http.createServer(); //建立服務器

server.on('request', function (request, response) { //註冊request請求事件
    response.end('hello,nodejs')
});

server.listen('4396', function () { //監聽4396端口
    console.log('服務器已經啓動成功了');
});

  瀏覽器訪問:http://localhost:4396/ 響應以下

  

  剛看到,感受是真的厲害,就想問問Node 你究竟幹了什麼。

5、加載和導出的使用規則

  1.require 加載方式

//加載方式有如下幾種
// 1. 直接寫模塊名字

//系統核心模塊,直接寫名字就行,不須要路徑。
var module = require('fs'); 

//第三方模塊,也是直接寫名字,可是名字絕對不可能與系統核心模塊同樣。你懂的。
var module = require('art-template'); 

// ./ 相對路徑形式,用於本身寫的模塊,路徑前必須加.,否則路徑找的是當前文件的根目錄路徑
// 做過web開發的同窗應該都知道,通常項目中歷來都是禁止寫絕對路徑的
var module = require('../a.js');
var module = require('./b.js');

     2.導出的規則

//每一個頁面(模塊)默認有一個exports對象,想要導出什麼就按照如下方式
exports.add = function (x, y) {
    return x + y;
}
exports.foo = 'foo';

//可是這種方式是錯誤的,並不能導出
exports = {
    add: function (x, y) {
        return x + y;
    },
    foo: 'foo'
};
//內部原理module.exports,由於node內部默認是
exports = module.exports;
// 最終導出的仍是module.exports;因此若是想導出一個總體,應該以下:
//體會如下引用的含義就明白爲何了。
module.exports = {
    add: function (x, y) {
        return x + y;
    },
    foo: 'foo'
}

6、包加載的方式

  1.有路徑的包

    有路徑的話是按照相對當前文件的路徑找到對應的文件 直接執行就好了。

   2.第三方的包(不帶路徑符號的)

    2.1 找到當前文件中的node_modules,找到相應的模塊名字,找到下面的package.json,裏邊有main,找到main的值,通常是index.js(這裏就能夠指定),而後node就去加載index.js文件 得到返回的exports對象,接着就想咱們上邊用模塊同樣了。

      以art-template爲例,第一步,找到package.json

       

      第二步,找到裏邊的main.js的值,爲index.js

      

      第三步,node去加載index.js,下邊是index.js裏邊的代碼,能夠看出是標準的node中的模塊導出寫法。

const template = require('./lib/index');
const extension = require('./lib/extension');

template.extension = extension;
require.extensions[template.defaults.extname] = extension;

module.exports = template;

  3.關於package-lock.json

   npm 版本 5.0以上會自動添加一個package-lock.json的文件,在該文件中保存了全部的包的依賴和下載地址,這樣的話還原包的時候就不用一個個解析依賴,直接下載就好了,大大提升了效率。並且,有了這個文件,當你用npm還原包的時候還能鎖定文件的版本,不至於還原的時候自動升級到最新版本。

7、npm經常使用命令

  基本上就用到一下幾個很是簡單的命令

npm init  //初始化一個基於node的app,這會讓你一步一步輸入你的app的配置

npm init -y //初始化一個基於node的app,使用默認生成配置

npm install 包名 // 安裝一個包

npm install --save 包名 //安裝一個包,並添加依賴信息到配置文件裏邊

npm install //根據依賴還原你全部依賴的包,萬一不當心把node_modules文件夾刪除了,那就用這個很是方便

npm remove 包名 //卸載一個包

npm remove --save 包名 //卸載一個包,並刪除配置文件裏相關的依賴配置信息

 8、Express框架

var express = require('express'); //加載express模塊

var app = express(); //啓動服務器,至關於http.createServer()

app.use('/public/', express.static('./public/')); //設置靜態文件目錄

app.get('/', function (req, res) { //處理/的請求
    res.end('hello,express');
})

app.listen(3000, function () {  //開啓監聽3000端口
    console.log('starting...');
})

9、框架搭建

  9.1 app.js 

var express = require('express');
var router = require('./router');
var bodyParser = require('body-parser');
var app = express();

app.engine('html', require('express-art-template')); //設置art-template的解析方式,爲解析帶html後綴的文件

app.use('/node_modules/', express.static('./node_modules/'));
app.use('/public/', express.static('./public/'));

app.use(bodyParser.urlencoded({ extended: false })); //使用body解析post數據庫
app.use(bodyParser.json()); 

app.use(router); //使用路由


app.listen(3000, function () {
    console.log('running...');
})

   9.2 router.js

var express = require('express');
var student = require('./student');
var router = express.Router();

router.get('/add', function (req, res) {
    res.render('add.html'); //默認去找views文件下的同名文件
});

router.post('/add', function (req, res) {
    student.add(req.body, function (error, data) {
        if (error) {
            res.end('error');
        } else {
            res.redirect('/');
        }
    })
})

router.get('/', function (req, res) {
    student.list(function (error, data) {
        if (error) {
            res.end('error');
        } else {
            res.render('index.html', {
                students: data
            });
        }
    })
})

router.get('/student', function (req, res) {
    res.render('index.html')
})

router.post('/post', function (req, res) {

});
module.exports = router;

  9.3 student.js

var fs = require('fs');
var student = {};

student.list = function (fn) {
    fs.readFile('./student.json', function (error, data) {
        if (error) {
            fn(error);
        } else {
            fn(null, JSON.parse(data.toString()));
        }
    })
}

student.add = function (student, fn) {
    fs.readFile('./student.json', function (error, data) {

        if (error) {
            fn(error);
        } else {
            var students = JSON.parse(data.toString());
            students.push(student);
            fs.writeFile('./student.json', JSON.stringify(students), function (error, data) {
                if (error) {
                    fn(error);
                } else {
                    fn(null, data);
                }
            });
        }
    })
}
module.exports = student;

10、數據訪問(mongodb)

const mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/test');

var catSchema = mongoose.Schema({
    name: String
});

const cat = mongoose.model('Cat', catSchema);
const kitty = new Cat({ name: 'cat' });

kitty.save().then(() => console.log('meow'));

cat.find({ name: 'cat' }, function (error, cat) {

})

 

10、總結

  總之,NodeJs開啓了JavaScript的新的神祕之旅,目前正在探索中,不過前幾天看到Node之父說NodeJs設計的出現了很大的失敗,又出了個叫deno的東西,唉,前端兄弟們真是堪憂。。。。

  

相關文章
相關標籤/搜索