node.js快速了解與應(yīng)用
一.Node.js簡介與安裝:
1.Node.js發(fā)布于2009年5月,由Ryan Dahl開發(fā),是一個基于Chrome V8引擎的JavaScript運(yùn)行環(huán)境,使用了一個事件驅(qū)動、非阻塞式I/O模型,讓JavaScript 運(yùn)行在服務(wù)端的開發(fā)平臺,它讓JavaScript成為與PHP、Python、Perl、Ruby等服務(wù)端語言平起平坐的腳本語言。
2.Node.js對一些特殊用例進(jìn)行優(yōu)化,提供替代的API,使得V8在非瀏覽器環(huán)境下運(yùn)行得更好,V8引擎執(zhí)行Javascript的速度非常快,性能非常好,基于Chrome JavaScript運(yùn)行時建立的平臺, 用于方便地搭建響應(yīng)速度快、易于擴(kuò)展的網(wǎng)絡(luò)應(yīng)用。
1.2.1 到官網(wǎng)去按照自己系統(tǒng)下載安裝包然后安裝就好。
Node.js中文網(wǎng)
1.2.2 安裝完成后,打開命令控制臺,輸入 node -v 出現(xiàn)版本號便是安裝完成。
二.計算機(jī)的環(huán)境變量:
cmd 的英文意思就是 command ,就是在 cmd 窗口輸入的指令都是對計算機(jī)的命令。比如 node -v就是查看 node 的版本指令。
在任何操作系統(tǒng)都有環(huán)境變量。在環(huán)境變量里面配置的文件夾內(nèi)部 exe 程序,都能被系統(tǒng) cmd 窗口調(diào)用。
比如,你在cmd窗口直接輸入qq,是沒辦法執(zhí)行的,因為你沒配置環(huán)境變量。所以你首先看看 qq.exe 的所在文件夾的路徑位置,把它粘貼配置在環(huán)境變量里就能被cmd窗口調(diào)用了。
三.Node.js的使用:
js文件的運(yùn)行必須要在宿主環(huán)境里,否則不能執(zhí)行。而我們以前學(xué)習(xí)到的宿主環(huán)境只有一個,就是 HTML 。現(xiàn)在學(xué)習(xí)另一個宿主環(huán)境,就是 Node.js 平臺。
我們可以打開 cmd 命令窗口運(yùn)行 js 文件。
如我在路徑 D:\node_Study 下有一個名為 01.js 文件,內(nèi)容為:
for(let i=0;i<10;i++){ console.log(i); }
那我們就在該目錄下 node 這個文件執(zhí)行它:
可以看到有運(yùn)行結(jié)果了,如果執(zhí)行 02.js 就輸入 node 02.js,執(zhí)行什么js文件就node什么文件。
四.Node.js搭建服務(wù)器:
01.js文件里寫入以下代碼:
//得到內(nèi)置的模塊,引入Node.js的內(nèi)置http的模塊 var http = require('http'); //創(chuàng)建服務(wù)器,使用createServer方法 //回調(diào)函數(shù)里的參數(shù)req表示請求,參數(shù)res表示響應(yīng) var server = http.createServer(function(req,res){ // 設(shè)置字符集 res.setHeader("Content-Type","text/html;charset=UTF8") // 輸出一句話 res.end('北極光之夜。') }) //監(jiān)聽,默認(rèn)端口是80,咱們用3000端口 server.listen(3000)
cmd窗口或者PowerShell窗口運(yùn)行 node 01.js,再到瀏覽器運(yùn)行網(wǎng)址 127.0.0.1:3000/ 得到效果:
注意事項:
1.如果要改變這個文件的內(nèi)容,那么就要重新執(zhí)行 node。
ctrl + c 是打斷連接
2.與PHP一樣,Node搭建的服務(wù)器也是將所有的計算結(jié)果扁平化后返回給計算機(jī)的。
3.即使一個沒有安裝Node.js的計算機(jī)也是可以請求我們本地有Node.js的計算機(jī)的功能的。因為Node.js本身即是搭建服務(wù)器的,所有我們只要把id給對應(yīng)的通信網(wǎng)絡(luò)下的計算機(jī)就都可以進(jìn)行訪問,因為本質(zhì)上訪問的并不是Node,而是搭建好服務(wù)器。
//得到內(nèi)置的模塊,引入Node.js的內(nèi)置http的模塊 var http = require('http'); //創(chuàng)建服務(wù)器,使用createServer方法 //回調(diào)函數(shù)里的參數(shù)req表示請求,參數(shù)res表示響應(yīng) var server = http.createServer(function(req,res){ // 設(shè)置字符集 res.setHeader("Content-Type","text/html;charset=UTF8") // 輸出一句話 res.end('北極光之夜。1') res.end('北極光之夜。2') res.end('北極光之夜。4') res.end('北極光之夜。4') res.end('北極光之夜。5') res.end('北極光之夜。6') }) //監(jiān)聽,默認(rèn)端口是80,咱們用3000端口 server.listen(3000)
輸出:
如這樣是錯誤的:
res.end(123455)
如:
res.end("
北極光之夜。
")輸出:
若使用res.write()最后必須要有res.end,否則瀏覽器會一直處于請求狀態(tài)。
res.write好處是可以多條輸出和識別html標(biāo)簽,但也不能輸入非字符串。
//得到內(nèi)置的模塊,引入Node.js的內(nèi)置http的模塊 var http = require('http'); //創(chuàng)建服務(wù)器,使用createServer方法 //回調(diào)函數(shù)里的參數(shù)req表示請求,參數(shù)res表示響應(yīng) var server = http.createServer(function(req,res){ // 設(shè)置字符集 res.setHeader("Content-Type","text/html;charset=UTF8") // 輸出一句話 res.write("
one
"); res.write("two
"); res.write("three
"); res.end("結(jié)束請求") }) //監(jiān)聽,默認(rèn)端口是80,咱們用3000端口 server.listen(3000)結(jié)果:
五.Node.js的內(nèi)置功能:
這是Node.js中文文檔的全部內(nèi)置模塊。
fs模塊最重要的就是異步讀取文件(readFile),第一個參數(shù)文件,第二個參數(shù)是回調(diào)函數(shù)。
fs.readFile("文件路徑與名字",function(err,data){ if(err) throw err; res.end(data); })
例子:
有個index.html文件:
Hello World.
js讀取它:
//得到內(nèi)置的模塊,引入Node.js的內(nèi)置http的模塊 var http = require('http'); //引入Node.js的內(nèi)置fs的模塊 var fs = require('fs'); var server = http.createServer(function(req,res){ fs.readFile("./index.html",function(err,data){ res.end(data); }) }) //監(jiān)聽,默認(rèn)端口是80,咱們用3000端口 server.listen(3000)
結(jié)果:
5.1的例子有個問題就是我們不論地址輸入什么地址url,都是顯示同樣的內(nèi)容,如:
…等
那么我們可以引入設(shè)計路由的概念,當(dāng)用戶輸入不同的url地址,我們獲取不同內(nèi)容返回。
例子:
var http = require('http'); var fs = require('fs'); var server = http.createServer(function(req,res){ res.setHeader("Content-Type","text/html;charset=UTF8"); //當(dāng)?shù)刂窞?/index則讀取index.html這個文件,當(dāng)然這個自定義 if(req.url === "/index"){ fs.readFile("./index.html",function(err,data){ res.end(data); }) //否則顯示Nothing }else{ res.end('Nothing'); } }) server.listen(3000)
效果:
注意:設(shè)計的路由地址并不是說要真正的物理上要存在這個路徑文件,這個是自定義的。
頂層路由設(shè)計概念:
?物理文件層次和 URL是沒有任何關(guān)系的。
?NodeJS 是可以做頂層路由設(shè)計的! 一個頁面URL是可以自定義的。
?用戶的輸 入的URL是可以映射任何HTML頁面的。
設(shè)置有一個地址 http://127.0.0.1:3000/user/..../… 為有效路由。
//得到內(nèi)置的模塊,引入Node.js的內(nèi)置http的模塊 var http = require('http'); var fs = require('fs'); //創(chuàng)建服務(wù)器,使用createServer方法 //回調(diào)函數(shù)里的參數(shù)req表示請求,參數(shù)res表示響應(yīng) var server = http.createServer(function(req,res){ res.setHeader("Content-Type","text/html;charset=UTF8"); //獲取用戶輸入的地址 var url = req.url; //利用正則表達(dá)式獲取地址/user 后的第一個 /.. 和第二個 /.. var arr = url.match(/\/user\/(.+)\/(.+)$/); //如果無對應(yīng)地址,報錯 if(!arr){ res.end("
無對應(yīng)頁面
") return; } // 正則的第一個獲取的 var $1 = arr[1]; //正則的第二個獲取的 var $2 = arr[2]; //模擬一些數(shù)據(jù) var user = { "liuyifei":"劉亦菲", "dilireba":"迪麗熱巴", "yangyin":"楊穎" } // 模擬一些數(shù)據(jù) var list = { "page":"文章", "ask":"提問" } //根據(jù)用戶輸入返回內(nèi)容 res.write("我是"+user[$1]+"~
") res.end("歡迎來到"+list[$2]+"模塊
") }) //監(jiān)聽,默認(rèn)端口是80,咱們用3000端口 server.listen(3000)效果:
比如我們有一個 02.js的文件如下:
當(dāng)?shù)刂窞?/satr/dilireba 則讀取 dilireba.html 這個文件。
var http = require('http'); var fs = require('fs'); var server = http.createServer(function(req,res){ res.setHeader("Content-Type","text/html;charset=UTF8"); //當(dāng)?shù)刂窞?//satr/dilireba則讀取dilireba.html這個文件,當(dāng)然這個自定義 if(req.url === "/satr/dilireba"){ fs.readFile("./dilireba.html",function(err,data){ res.end(data); }) //否則顯示Nothing }else{ res.end('Nothing'); } }) server.listen(3000)
dilireba.html 這個文件內(nèi)容如下:
有句話和一張圖:
我是迪麗熱巴~

運(yùn)行結(jié)果如下:
問題:頁面中只有文字的展示,沒有圖片的展示,但是HTML結(jié)構(gòu)中是有img標(biāo)簽的,為什么不能加載?
答:該圖片的ur1路徑是沒有物理文件夾的。現(xiàn)在這張圖片的真實物理地址是我們自定義的http://127.0.0.1:3000/satr/http://m.bai1xia.com/news/zb_users/upload/2022/05/20220530182241_86469.jpg,但是圖片物理存放地址是在我們本地D:\node_Study, 不一樣,所以一定不能按需加載。
解決:文字和圖片都進(jìn)行請求:
var http = require('http'); var fs = require('fs'); var server = http.createServer(function(req,res){ res.setHeader("Content-Type","text/html;charset=UTF8"); //當(dāng)?shù)刂窞?/index則讀取index.html這個文件,當(dāng)然這個自定義 if(req.url === "/satr/dilireba"){ fs.readFile("./dilireba.html",function(err,data){ res.end(data); }) //否則顯示Nothing }else if(req.url === "/satr/http://m.bai1xia.com/news/zb_users/upload/2022/05/20220530182241_86469.jpg"){ res.setHeader("Content-Type","image/jpg"); //得到圖片 fs.readFile("./http://m.bai1xia.com/news/zb_users/upload/2022/05/20220530182241_86469.jpg",function(err,data){ res.end(data); }) } else{ res.end('Nothing'); } }) server.listen(3000)
結(jié)果:
問題來了,如果圖片的數(shù)量很多怎么辦?
那么每一張都勢必要進(jìn)行對路由的請求和渲染,也就是要給每一張圖片都要開辟路由地址,不僅僅是圖片,其他文件也是一樣的。
解決辦法就是我們后面要學(xué)習(xí)的express的中間件來靜態(tài)化一個文件夾。目的就是當(dāng)前的這個文件夾內(nèi)部的文件自動就有了URL路由,不用每一個都單獨(dú)設(shè)置。
需要注意的是使用NodeJS進(jìn)行請求文件的時候需要設(shè)置對應(yīng)的ContentType,就是文件的請求類型。
如:
html文件:
res.setHeader("Content-Type","text/html;charset=UTF8");
css文件:
res.setHeader("Content-Type","text/css");
jpg格式圖片:
res.setHeader("Content-Type","image/jpg");
等等…
六.模塊(重點(diǎn)):
什么是模塊?
當(dāng)一個js文件可以獨(dú)立完成一個功能的時候,這個js文件就是一個模塊。
當(dāng)一個多個.js文件共同完成一個功能的時候,這個些js文件就是一個模塊。
模塊就是module (模塊的意思)。
在HTML的宿主環(huán)境中,多個js文件公用一個html宿主,此時它們的作用域是公用的。
示例:
index.html內(nèi)容:
01.js內(nèi)容:
var a = 666;
02.js內(nèi)容:
alert(a);
運(yùn)行index.html結(jié)果:
此時頁面中是可以彈出666的,因為此時01. js文件中的a是全局變量也就是window的屬性,所以02.js是可以使用window.a的也就是666.
require()引用文件在引用的同時也在執(zhí)行。
如:
01.js內(nèi)容:
console.log("I am 01.js");
02.js內(nèi)容:
./ 表示當(dāng)前目錄下
require("./01.js"); console.log("I am 02.js");
運(yùn)行02.js結(jié)果:
如:
01.js文件內(nèi)容:
var a = 666;
02.js文件內(nèi)容:
require("./01.js"); console.log(a);
運(yùn)行結(jié)果:
錯誤信息內(nèi)容是a沒有被定義。因為 js 文件在NodeJS中作用域隔離,因為NodeJS沒有window對象。
此時我們想讓文件之間能夠相互通信,所以需要讓文件自己暴露。如 6.4
如:
01.js內(nèi)容:
var num = 666; // 向外暴露num參數(shù) exports.num = num;
02.js內(nèi)容:
var a = require("./01.js"); //輸出獲取到 a文件的 num 參數(shù) console.log(a.num);
運(yùn)行結(jié)果:
當(dāng)然建議命名時要統(tǒng)一規(guī)范。如6.5
如:
這三個文件都是平級的。
round.js內(nèi)容:
function area(r){ return 3.14 * r * r } exports.area = area;
rectangle.js內(nèi)容:
function area(a,b){ return a * b } exports.area = area;
app.js內(nèi)容:
var round = require("./round.js"); var rectangle = require("./rectangle.js"); console.log(round.area(6)); console.log(rectangle.area(2,3));
運(yùn)行結(jié)果:
round.js和rectangle.js都定義了area函數(shù),但是由于我們都各自的命名空間,所以互相不干擾。
exports是可以暴露多個參數(shù)的:
如:
round.js變成如下,rectangle.js不變:
function area(r){ return 3.14 * r * r } function perimeter(r){ return 3.14 * 2 * r } exports.area = area; exports.perimeter = perimeter;
app.js內(nèi)容:
var round = require("./round.js"); var rectangle = require("./rectangle.js"); console.log(round.area(6)); console.log(rectangle.area(2,3)); console.log(round.perimeter(6));
結(jié)果:
當(dāng)一個js文件僅僅希望暴露一個參數(shù),通常是構(gòu)造函數(shù),此時我們可以使用module.exports命令進(jìn)行暴露。
如:
有一個people.js內(nèi)容如下:
function people(name,age,sex){ this.name = name; this.age = age; this.sex = sex; } //prototype 屬性使您有能力向?qū)ο筇砑訉傩院头椒ā?people.prototype.sayHello = function(){ console.log("我加"+this.name+",我"+this.age+"了呢,我性別是"+this.sex+"的。"); } module.exports = people;
app.js內(nèi)容如下:
var people = require("./people.js"); var xiaohong = new people("小紅",18,"女"); xiaohong.sayHello();
兩個文件時平級的。
結(jié)果:
此時我們發(fā)現(xiàn)小紅在new的時候并沒有使用和exports類似的命名空間對象,是因為module. exports默認(rèn)返回的不是對象而是結(jié)果。
假如有個文件目錄層級如下:
我們此時將round. js和rectangle. js放到了一個result文件夾內(nèi)部,被index.js進(jìn)行整合。
round.js內(nèi)容:
function area(r){ return 3.14 * r * r } function perimeter(r){ return 3.14 * 2 * r } exports.area = area; exports.perimeter = perimeter;
rectangle.js內(nèi)容:
function area(a,b){ return a * b } exports.area = area;
index.js內(nèi)容:
var round = require("./round.js"); var rectangle = require("./rectangle.js"); exports.round = round; exports.rectangle = rectangle;
app.js內(nèi)容:
var result = require("./result"); console.log(result.round.area(3)); console.log(result.rectangle.area(1,2));
如果我們require()沒有.js后綴,此時NodeJS會認(rèn)為我們在引入一個文件夾,并且執(zhí)行這個文件夾內(nèi)部的index.js。
var result = require("./result"); 等價于 var result = require("./result/index.js");
運(yùn)行結(jié)果:
我們發(fā)現(xiàn),在我們上面全部的代碼示例中引入件時,前面都不能省略 ./ ,省略就會報錯,但是,在NodeJS中,如果文件夾內(nèi)部存放了node_modules文件夾,此時內(nèi)部的文件引入的時候就不用寫 ./ 了。就這么神奇。
假如我們在6.7的基礎(chǔ)上,在work文件夾下創(chuàng)建 node_modules文件夾,然后把 result文件夾放在 node_modules 下,這樣app.js在引入就不用寫 ./ 了。
當(dāng)前目錄如下:
app.js內(nèi)容:
var result = require("result"); console.log(result.round.area(3)); console.log(result.rectangle.area(1,2));
運(yùn)行不會報錯:
總結(jié),如果我們使用require去引入文件,不加 ./ 就是引入node_ modules文件夾內(nèi)部的文件,否則就是本地其他文件夾。
七.npm的基本使用:
npm是一個全世界范圍內(nèi)的模塊分享社區(qū),我們可以免費(fèi)使用這個社區(qū)內(nèi)別人開發(fā)的模塊。社區(qū)鏈接。
npm受到全球超過1100萬開發(fā)人員的依賴,致力于使JavaScript開發(fā)優(yōu)雅,高效和安全。
安裝去官網(wǎng)查找自己想要的模塊,然后根據(jù)給出步驟文檔安裝和使用即可。
我們從npm上下載的node_ modules 文件夾內(nèi)容稱之為“依賴”。
我們可以使用package.json去管理這些依賴,此時我們就需要創(chuàng)建自己的身份證。
我們在開發(fā)項目的時候第一件事就是要創(chuàng)建身份證。
在終端輸入如下命令:
npm init
然后填寫一些表單信息,比如名字,描述啥的,可以按需回答,也可以回車跳過。
然后就得到如下package.json:
有了這個身份證后,以后安裝依賴的時候要加- -save
比如我們裝一個叫nzh的模塊:
npm install --save nzh
此時再看身份證,得到nzh依賴項:
為什么要這樣做?
我們知道node_ modules 都是相互依賴的,所以如果引入的模塊特別多,此時如果進(jìn)行物理文件傳輸?shù)臅r候會造成特別大,特別碎的文件內(nèi)容。所以在我們物理傳輸時可以不傳這個node_ modules 文件夾,只傳身份證就好。所以一定要用身份證保存,物理傳輸完成后,得到者可以根據(jù)身份證在下一次進(jìn)行使用之前,重新安裝需要的依賴。
以后只要在對應(yīng)的package.json目錄下輸入:
npm isntall
此時npm就會檢索對應(yīng)目錄下面的package . json文件內(nèi)部的dependencies的依賴項然后進(jìn)行安裝。
總結(jié):
持續(xù)更新中~
JavaScript Node.js
版權(quán)聲明:本文內(nèi)容由網(wǎng)絡(luò)用戶投稿,版權(quán)歸原作者所有,本站不擁有其著作權(quán),亦不承擔(dān)相應(yīng)法律責(zé)任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實的內(nèi)容,請聯(lián)系我們jiasou666@gmail.com 處理,核實后本網(wǎng)站將在24小時內(nèi)刪除侵權(quán)內(nèi)容。
版權(quán)聲明:本文內(nèi)容由網(wǎng)絡(luò)用戶投稿,版權(quán)歸原作者所有,本站不擁有其著作權(quán),亦不承擔(dān)相應(yīng)法律責(zé)任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實的內(nèi)容,請聯(lián)系我們jiasou666@gmail.com 處理,核實后本網(wǎng)站將在24小時內(nèi)刪除侵權(quán)內(nèi)容。