NODE.JS
什么是node.js媳拴?
-
Node.js? is a JavaScript runtime(運(yùn)行時(shí)、運(yùn)行環(huán)境) built on Chrome's V8 JavaScript engine.
Node.js 是一個(gè)構(gòu)建于 Chrome V8 引擎的 JavaScript 運(yùn)行環(huán)境墨榄。
Node.js 為 JavaScript 代碼的正常運(yùn)行昙啄,提供的必要的環(huán)境律歼。
不是庫踊挠、框架只怎、不是語言绿淋。
是一個(gè)JS運(yùn)行時(shí)環(huán)境。簡單說就是可以解析和執(zhí)行JS代碼尝盼。
像瀏覽器一樣提供可以解析和執(zhí)行的環(huán)境,但不是瀏覽器佑菩。以前只有瀏覽器可以解析和執(zhí)行js代碼盾沫,有了node.js,現(xiàn)在可以脫離瀏覽器去解析和執(zhí)行殿漠。
(技術(shù)性的網(wǎng)站一般都是io或者org)
-
瀏覽器中的javaScript:
-
ECMAScript(語法)
基本的語法
if語句
var
function
objeck
array
DOM
BOM
-
-
node.js中的javaScrip:
沒有DOM和BOM赴精。(服務(wù)端不負(fù)責(zé)處理處理DOM和BOM)
有ECMAScript
-
在node這個(gè)JavaScript執(zhí)行環(huán)境中為JavaScript提供了一些操作服務(wù)器級(jí)別的API。如:
文件的讀寫
網(wǎng)絡(luò)服務(wù)的構(gòu)建
數(shù)據(jù)網(wǎng)絡(luò)通信
http服務(wù)器绞幌。蕾哟。。
-
node.js 的特點(diǎn)
單線程莲蜘,非阻塞I/O谭确,事件驅(qū)動(dòng)。
相比多線程語言更節(jié)省內(nèi)存票渠,非阻塞I/O使得程序不停在運(yùn)行逐哈,事件驅(qū)動(dòng)可以處理I/O后的回調(diào)。
單線程則系統(tǒng)不會(huì)再用于建立銷毀線程增加開銷问顷,不過線程出問題昂秃,全部業(yè)務(wù)都出問題。
在非阻塞模式下杜窄,一個(gè)線程永遠(yuǎn)在計(jì)算肠骆,線程CPU核心利用率永遠(yuǎn)100%。
npm是最大的開源庫生態(tài)系統(tǒng)塞耕。(node.js開發(fā)的)絕大多數(shù)的JavaScript相關(guān)的包都存放在npm上面蚀腿,這樣做的目的是為了使開發(fā)人員更方便的使用和下載。
Node.js能做什么
web服務(wù)器后臺(tái)扫外,網(wǎng)站后臺(tái)
-
命令行工具
npm
git(c語言開發(fā)的)
hexo(node開發(fā)的)
對于前端開發(fā)工程師來說唯咬,接觸node最多的是命令行工具,自己寫的很少畏浆,主要是使用第三方工具
可以學(xué)到什么
-
B/S編程模型
Browser-server
back-end
任何服務(wù)端奇數(shù)這種BS編程模型都是一樣的胆胰,和語言無關(guān)
Node只是作為我們學(xué)習(xí)BS編程模型的一個(gè)工具
-
模塊化編程
RequireJS
SeaJS
在Node中可以像
@import('w文件路徑')
一樣來引用加在JavaScript腳本文件
Node常用API
-
異步編程
回調(diào)函數(shù)
Promise
async
agenerator
ES6新語法
global模塊
global模塊,是node的全局模塊刻获,在使用時(shí)不需要引入蜀涨,可以直接使用瞎嬉。
* window 頂層對象 全局變量
* global 全局模塊 里面的變量 , 都是全局變量
* 注意 : node里面使用 global里面的變量,不需要引入 , 說明其他的是需要引入的
*/
//1\. console.log() 打印
?
//2\. setTimeout 和setInterval ,延時(shí)器和定時(shí)器
setTimeout(() => {
console.log('123');
}, 1000);
?
//3\. __dirname 當(dāng)前文件夾的絕對路徑
//從當(dāng)前所在磁盤盤符一直到當(dāng)前文件夾的路徑
console.log(__dirname);
//4\. require 引入模塊
// 在node里是通過require 來引入模塊的
// 除了global其他模塊都是需要引入的
const fs = require('fs')
?</pre>
Node中的JavaScript
-
EcmaScript
- 沒有DOM厚柳、BOM
核心模塊
核心模塊
Node為JavaScript提供了很多服務(wù)器級(jí)別的API氧枣,這些API絕大多數(shù)都被包裝到了一個(gè)具體的核心模塊中了。例如操作文件的fs核心模塊别垮,http服務(wù)構(gòu)建的http模塊便监。。如果需要使用核心模塊碳想,就必須先引入const fs = require('fs')
fs 文件系統(tǒng)核心模塊
fs是file-s 的簡寫烧董,他是node.js提供的用來操作文件的模塊。在fs這個(gè)核心模塊中胧奔,就提供了所有文件操作相關(guān)的API逊移。使用文件系統(tǒng)模塊之前,先i引入fs模塊:conts fs = require('fs')
(瀏覽器中的JavaScript沒有文件操作的能力龙填,node.js中有操作文件的能力)瀏覽器不認(rèn)識(shí)node代碼
-
向指定文件讀取內(nèi)容:fs.readFile()
-
fs.readFile(path[, options], callback)
參數(shù)1:必選胳泉,指定文件的路徑
參數(shù)2:可選,表示以什么編碼格式讀取
-
參數(shù)3:必選岩遗,回調(diào)函數(shù)扇商。
第一個(gè)參數(shù)err(錯(cuò)誤內(nèi)容),讀取成功會(huì)返回null宿礁。
第二個(gè)data(讀到的數(shù)據(jù))
-
-
向指定文件書寫內(nèi)容:fs.writeFile()
-
fs.writeFile(file, data[, options], callback)
參數(shù)1:必選钳吟,指定文件的路徑
參數(shù)2:必選,要書寫的文件內(nèi)容
參數(shù)3:可選窘拯,以什么格式寫入红且,默認(rèn)為'utf8'
參數(shù)4:必選,回調(diào)函數(shù)涤姊。參數(shù)err(錯(cuò)誤內(nèi)容)暇番,讀取成功會(huì)返回null
【注】1、以覆蓋的形式寫入文件
2思喊、寫入的文件不存在壁酬,會(huì)新創(chuàng)建一個(gè)文件
-
-
讀取指定目錄下所有文件的名稱:fs.readdir()
-
fs.readdir(path[, options], callback)
參數(shù)1:必選,指定要讀取哪個(gè)目錄下所有的文件名稱
參數(shù)2:可選恨课,以什么格式讀取目錄
參數(shù)3:回調(diào)函數(shù)
-
path 路徑核心模塊
path 模塊是 Node.js 官方提供的舆乔、用來處理路徑的模塊。使用之前需要先引入const path = require('path')
-
路徑拼接path.join()
path.join([...paths])
paths <string> 多個(gè)路徑片段的序列剂公,返回值string
默認(rèn)按照拼接順序拼接
-
獲取路徑中的文件名path.basename()
可以從一個(gè)文件路徑中希俩,獲取到文件的名稱部分
path.basename(path[,ext])
path <string> 必選參數(shù),表示一個(gè)路徑的字符串
ext <string> 可選參數(shù)纲辽,表示可選的文件擴(kuò)展名
返回: <string> 表示路徑中的最后一部分颜武,如果不存在路徑璃搜,全部都是文件名。路徑存在鳞上,取最后一個(gè)斜杠后面的內(nèi)容
http核心模塊
http 模塊是 Node.js 官方提供的这吻、用來創(chuàng)建web 服務(wù)器和客戶端的模塊。使用之前需要先引入const http= require('http')
創(chuàng)建 web 服務(wù)器的基本步驟
導(dǎo)入http核心模塊
使用
http.creatServer()
方法創(chuàng)建一個(gè)web服務(wù)器篙议,返回一個(gè)Server實(shí)例給Server實(shí)例綁定request 事件唾糯,監(jiān)聽客戶端的請求。當(dāng)客戶端發(fā)送請求過來鬼贱,會(huì)觸發(fā)服務(wù)器的request請求事件移怯,然后執(zhí)行回調(diào)函數(shù)
綁定端口號(hào),啟動(dòng)服務(wù)器(不要設(shè)置6666)
示例代碼
// 1\. 加載 http 模塊
const http = require('http');
// 2\. 創(chuàng)建server 對象
const server = http.createServer();
// 3\. 監(jiān)聽端口吩愧,開啟服務(wù)器
server.listen(3000, () => console.log('my server running'));
// 4\. 注冊server的request事件,準(zhǔn)備處理瀏覽器的請求
server.on('request', (req, res) => {
// req request 請求增显,通過req對象可以獲取到所有和請求相關(guān)的信息
// res response 響應(yīng)雁佳,通過res對象可以做出響應(yīng)以及設(shè)置一些和響應(yīng)相關(guān)的內(nèi)容
?
// // 設(shè)置響應(yīng)頭
// res.setHeader('Content-Type', 'text/html; charset=utf-8');
// res.setHeader('Author', 'zhangsan'); // 自己設(shè)置響應(yīng)頭,不要用中文
// // 設(shè)置響應(yīng)狀態(tài)碼
// res.statusCode = 200;
?
// 綜合性的設(shè)置響應(yīng)狀態(tài)碼和響應(yīng)頭的方法
res.writeHead(200, {
'Content-Type': 'text/html; charset=utf-8',
'Author': 'zhangsan'
});
// write方法同云,也可以設(shè)置響應(yīng)體糖权,但是沒有做出響應(yīng)的意思,只是單純的設(shè)置響應(yīng)體
res.write('1234');
res.write('5678');
// res.end(響應(yīng)體); // 做出響應(yīng)
res.end('hello炸站,你的請求我收到了');
// 做出響應(yīng)之后星澳,不能再有其他代碼。
});</pre>
【注意】如果代碼修改旱易,要重啟服務(wù)器才能
Request請求事件處理函數(shù)禁偎,需要接收兩個(gè)參數(shù),分別是Request請求對象和Response響應(yīng)對象
Request 請求對象
可以用來獲取客戶端的一些請求信息阀坏,例如請求路徑如暖、方式、頭忌堂、體盒至,所有和請求相關(guān)的信息,都可以獲取到士修。
獲取請求地址
req.url
獲取請求方式
req.method
Response 響應(yīng)對象
可以用來給客戶端響應(yīng)消息枷遂。有一個(gè)方法res.write()
可以用來給客戶端發(fā)送響應(yīng)的數(shù)據(jù)。write()
方法可以使用多次棋嘲,但最后一定要用end()
結(jié)束響應(yīng)酒唉,否則客戶端會(huì)一直等待》幸疲可以在響應(yīng)結(jié)束的時(shí)候黔州,
-
設(shè)置響應(yīng)頭耍鬓,解決中文亂碼
res.setHeader('Content-Type', 'text/html; charset=utf-8');
-
設(shè)置狀態(tài)碼
res.statusCode = 200;
-
綜合設(shè)置響應(yīng)頭和狀態(tài)碼的方法
res.writeHead(200,{'Content-Type', 'text/html; charset=utf-8','Author':'ls'})
-
響應(yīng)體
res.write()
- 結(jié)束響應(yīng)
res.end()
- 結(jié)束響應(yīng)
【注】
所有的請求路徑 url 都是以 / 開頭的
響應(yīng)內(nèi)容只能是字符串或者二進(jìn)制數(shù)據(jù)
當(dāng)請求不同的路徑的時(shí)候,響應(yīng)不同的結(jié)果流妻。
例如請求:
/ index 牲蜀,響應(yīng)index
/login蚂子,響應(yīng)login
/haha酝枢,響應(yīng)哈哈
server.on('request', (req, res) => {
// 獲取請求路徑。再根據(jù)路徑響應(yīng)
// 所有的請求路徑 url 都是以 / 開頭的
var url = req.url
if (url === '/index' || url === '/') {
res.end('index page')
} else if (url === '/login') {
res.end('login page')
} else if (url === '/haha') {
res.end('haha page')
} else {
res.end('404 Not Found')
}
})</pre>
端口號(hào)
計(jì)算機(jī)中的端口號(hào)册踩,就好像是現(xiàn)實(shí)生活中的門牌號(hào)一樣证薇。通過門牌號(hào)度苔,外賣小哥可以在整棟大樓眾多的房間中,準(zhǔn)確把外賣 送到你的手中浑度。
同樣的道理寇窑,在一臺(tái)服務(wù)器中,可以運(yùn)行成百上千個(gè)web 服務(wù)箩张。此時(shí)甩骏,通過端口號(hào),客戶端發(fā)送過來的網(wǎng)絡(luò)請求先慷,可以被準(zhǔn) 確地交給端口號(hào)對應(yīng)的web 服務(wù)進(jìn)行處理饮笛。
npm初步使用
npm(node package manager)node包管理器。
包是什么论熙?包就是模塊福青。
npm這個(gè)工具,在安裝node的時(shí)候脓诡,就已經(jīng)安裝到你的計(jì)算機(jī)中了无午。
命令行中執(zhí)行:
npm -v
,如果看到版本號(hào)祝谚,說明安裝成功了指厌。
作用
npm的作用是:管理node模塊的工具。
下載并安裝第三方的模塊
卸載第三方模塊
發(fā)布模塊
刪除已發(fā)布的模塊
....
npm 就是一個(gè)管理(下載安裝踊跟、卸載...)第三方模塊的工具
第三方模塊:
非內(nèi)置模塊踩验,安裝完node,還不能使用的模塊商玫,需要從網(wǎng)上下載安裝箕憾,才能使用的模塊
第三方模塊是個(gè)人、公司拳昌、組織編寫的模塊袭异,發(fā)布到網(wǎng)上,供我們使用
初始化
使用npm工具之前炬藤,必須先初始化御铃。
npm init -y
或
npm init
然后一路回車
初始化之后碴里,會(huì)在項(xiàng)目目錄中生成 package.json 的文件。
什么第三方模塊
非node自帶的模塊上真。
是別人寫的模塊咬腋,然后發(fā)布到npm網(wǎng)站,我們可以使用npm工具來下載安裝別人寫的模塊睡互。
第三方模塊根竿,都是在node核心模塊的基礎(chǔ)之上,封裝了一下就珠,實(shí)現(xiàn)了很多非常方便快速簡潔的方法寇壳。
目前,npm網(wǎng)站收錄了超過 150萬個(gè)第三方模塊妻怎。
安裝卸載項(xiàng)目模塊
下載安裝第三方模塊
npm install 模塊名
npm i 模塊名
卸載模塊
npm uninstall 模塊名
npm un 模塊名</pre>
安裝指定版本:
npm i 模塊名@版本號(hào)
npm i jquery@3.5.0</pre>
演示代碼
這里演示一個(gè)處理時(shí)間日期的模塊 -- moment
下載安裝moment模塊
npm init -y
npm i moment</pre>
演示使用moment模塊處理時(shí)間
// 加載模塊
const moment = require('moment');
console.log(moment().format('YYYY-MM-DD hh:mm:ss'));
// 官網(wǎng):http://momentjs.cn</pre>
全局模塊
全局安裝的模塊壳炎,不能通過
require()
加載使用。全局安裝的模塊逼侦,一般都是命令或者工具匿辩。
安裝方法,在安裝模塊的命令后面偿洁,加
-g
npm i 模塊名 -g
# 或
npm i -g 模塊名</pre>
- 卸載方法(也是多一個(gè)
-g
)
npm un 模塊名 -g</pre>
-
全局安裝的模塊撒汉,在系統(tǒng)盤(C盤)
- 通過命令
npm root -g
可以查看全局安裝路徑
- 通過命令
查看安裝的全局模塊----沒有-g查看本地安裝沟优,加上-g查看全局模塊
npm list -g --depth 0
全局安裝nodemon模塊
- 安裝命令
npm i nodemon -g
nodemon的作用:
代替node命令涕滋,啟動(dòng)服務(wù)的,當(dāng)更改代碼之后挠阁,nodemon會(huì)自動(dòng)幫我們重啟服務(wù)宾肺。
運(yùn)行nodemon,如果報(bào)錯(cuò)如下:
[圖片上傳失敗...(image-2a0f9e-1609946235846)]
-
解決辦法是:
管理員
方式侵俗,打開命令行窗口執(zhí)行
set-ExecutionPolicy RemoteSigned;
在出現(xiàn)的選項(xiàng)中锨用,輸入
A
,回車隘谣。即可
執(zhí)行 : nodemon 文件路徑
更改鏡像源
鏡像源增拥,就是下載安裝第三方模塊的網(wǎng)站。
我們下載的第三方模塊都是從國外的npm主站下載的寻歧,速度比較慢掌栅。
淘寶在國內(nèi)對npm上的第三方模塊做了一個(gè)備份,也就是說码泛,我們可以從國內(nèi)下載第三方模塊猾封。
除了淘寶之外,還有很多其他鏡像源噪珊。
簡單的更改鏡像源方法:
-
全局安裝 nrm 的模塊
- nrm 用于管理鏡像源
-
使用nrm
nrm ls
通過這個(gè)命令晌缘,可以查看可用的鏡像源nrm use taobao
齐莲,切換下載模塊的網(wǎng)站為淘寶
模塊化
模塊化是指解決一個(gè)復(fù)雜問題時(shí),自頂向下逐層把系統(tǒng)劃分成若干模塊的過程磷箕。 對于整個(gè)系統(tǒng)來說选酗,模塊是可組合、分解和更換的單元搀捷。
編程中的模塊化
編程領(lǐng)域中的模塊化星掰,就是遵守固定的規(guī)則,把一個(gè)大文件拆成獨(dú)立并互相依賴的多個(gè)小模塊嫩舟。
把代碼進(jìn)行模塊化拆分的好處:
提高了代碼的復(fù)用性
提高了代碼的可維護(hù)性
可以實(shí)現(xiàn)按需加載
文件作用域
-
通信規(guī)則
加載require
導(dǎo)出
Node中的模塊分類:
Node.js 中根據(jù)模塊來源的不同氢烘,將模塊分為了 3 大類,分別是:
內(nèi)置模塊(內(nèi)置模塊是由 Node.js 官方提供的家厌,例如 fs播玖、path、http 等)
自定義模塊(用戶創(chuàng)建的每個(gè)
.js
文件饭于,都是自定義模塊)第三方模塊(由第三方開發(fā)出來的模塊蜀踏,并非官方提供的內(nèi)置模塊,也不是用戶創(chuàng)建的自定義模塊掰吕,使用前需要先下載)
CommonJS規(guī)范
在node中的JavaScript有一個(gè)很重要的概念果覆,系統(tǒng)模塊
Node.js 遵循了 CommonJS 模塊化規(guī)范,CommonJS 規(guī)定了模塊的特性和各模塊之間如何相互依賴殖熟。
CommonJS 規(guī)定:
模塊作用域
每個(gè)模塊內(nèi)部局待,module 變量代表當(dāng)前模塊。
使用require() 方法用于加載模塊
module 變量是一個(gè)對象菱属,它的 exports 屬性(即 module.exports)是對外的接口钳榨。使用exports接口對象導(dǎo)出模塊中的成員
加載某個(gè)模塊,其實(shí)是加載該模塊的 module.exports 屬性纽门。
require加載自定義模塊
語法演示:
// 加載自定義模塊
const 自定義變量名 = require('./custom');</pre>
作用:
執(zhí)行被加載的模塊中的代碼
得到被加載模塊中的
exports
導(dǎo)出接口對象
注意事項(xiàng):
- 加載自定義的模塊薛耻,需要加
./路徑
,而且可以省略后綴.js
exports導(dǎo)出自定義模塊
node中是模塊作用域赏陵,默認(rèn)文件中所有的成員只能在當(dāng)前模塊中有效,另一個(gè)JS文件就無法使用當(dāng)前模塊定義的內(nèi)容所以需要導(dǎo)出導(dǎo)入文件
每個(gè)模塊內(nèi)部都有一個(gè)module對象饼齿。在module對象中有一個(gè)成員叫exports,也是對象蝙搔。誰require缕溉,誰就得到
module.exports
屬性,默認(rèn)是一個(gè)空對象杂瘸。對于希望可以被其他模塊訪問的成員倒淫,只需要把成員掛載到module。使用
module.exports
導(dǎo)出需要共享的內(nèi)容。導(dǎo)出等于是給其賦值敌土,重復(fù)賦值會(huì)被覆蓋镜硕。
使用模塊的JS文件需要使用
require()
導(dǎo)入模塊。導(dǎo)入的內(nèi)容就是返干,模塊導(dǎo)出的內(nèi)容
導(dǎo)出多個(gè)成員(必須在對象中)
exports.a = 123;
exports.b = 'hello';
exports.c = function(){
console.log('ccc')
}
exports.d = {
foo:'bar'
}</pre>
導(dǎo)出單個(gè)成員(拿到的就是函數(shù)兴枯、字符串)
module.exports = 'hello'
//以這個(gè)為準(zhǔn),后者會(huì)覆蓋前者
module.exports = funciton(){
return x+y
}
//這樣可以導(dǎo)出多個(gè)成員
module.exports{
add:function(){
return console.log(x+y)
},
str:'hello'
}</pre>
原理解析
- 在node底層中矩欠,每個(gè)模塊都有一個(gè)自己的module對象财剖,該module對象中,有一個(gè)成員叫exports癌淮,也是一個(gè)對象
//演示:
var module= {
exports:{
}
}
//如果需要對外導(dǎo)出某些成員躺坟,只需要把這些成員掛載到module對象上的exports對象中。
module.exports.foo = 'bar'//等于是在exports對象中添加了 foo: 'bar'
//默認(rèn)在代碼的最后有一句,誰來require乳蓄,誰就得到module.exports
return module.exports
</pre>
- exports是
module.exports
的一個(gè)引用var exports = module.exports
//我們發(fā)現(xiàn)咪橙,每次導(dǎo)出接口的成員的時(shí)候,都需要通過module.exports.xxx=xxx的方式很麻煩
//于是虚倒,node為了簡化操作美侦,專門提供一個(gè)變量 var exports = module.exports
console.log( exports === module.exports) //true 可以使用任何一方來導(dǎo)出接口成員
//二者等價(jià).最后return的是 module.exports 所以注意不要給exports重新賦值
module.exports.foo = 'bar'//等于是在exports對象中添加了 foo: 'bar'
exports.foo = 'bar'</pre>
模塊加載順序和區(qū)別
通過引入的內(nèi)容 核心模塊和第三方模塊直接引入模塊名,自定義模塊必須要帶有路徑魂奥。
// 加載核心模塊
const fs = require('fs');
// 加載第三方模塊
const express = require('express');
// 加載自定義模塊
const custom = require('./custom');</pre>
加載順序:
無論是什么模塊菠剩,我們都要使用
require()
去加載,然后才能使用耻煤。優(yōu)先加載內(nèi)置模塊具壮,即使有同名文件,也會(huì)優(yōu)先使用內(nèi)置模塊
不是內(nèi)置模塊违霞,先去緩存中找嘴办,緩存沒有去找對應(yīng)路徑的文件
不存在對應(yīng)的文件瞬场,就將這個(gè)路徑作為文件夾加載买鸽。
對應(yīng)的文件和文件夾還找不到就去
node_modules
下面找
注意事項(xiàng):
加載自定義的模塊,需要加
require(./路徑)
贯被,可以省略文件擴(kuò)展名加載第三方模塊和核心模塊眼五。只需要寫
require(模塊名)
如果是非路徑形式的模塊標(biāo)識(shí),會(huì)判斷是不是核心模塊彤灶,如果是看幼,優(yōu)先加載核心模塊
-
如果是路徑形式的』仙拢肯定是第三方模塊诵姜,會(huì)去當(dāng)前的
node_modules
文件中查找優(yōu)先加載相同名字的文件,加載一個(gè)叫做 abc 的文件
自動(dòng)補(bǔ)
.js
后綴搏熄,然后加載abc.js
文件自動(dòng)補(bǔ)
.json
后綴棚唆,然后加載abc.json
文件自動(dòng)補(bǔ)
.node
后綴暇赤,然后加載abc.node
文件以上文件都沒有,則報(bào)錯(cuò)
Cannot find module './abc'
其他
main說明
package.json文件中的main選項(xiàng)宵凌,作用時(shí)配置路口文件鞋囊,在路口文件中坑定有導(dǎo)出(module.express)
如果沒有main選項(xiàng),那么項(xiàng)目根目錄必然會(huì)有index.js瞎惫,默認(rèn)是入口文件溜腐。
依賴管理dependencies:
nodejs 中總共有 5 種依賴:
dependencies (常用)
devDependencies (常用)
peerDependencies (不太常用)
bundledDependencies (我之前沒用過)
optionalDependencies (我之前沒用過)
dependencies:
保存本地安裝的所有依賴
這是 npm 最基本的依賴,通過命令 npm i xxx -S
或者 npm i xxx --save
來安裝一個(gè)包瓜喇,并且添加到 package.json 的 dependencies 里面(這里 i
是 install
的簡寫挺益,兩者均可)。
如果直接只寫一個(gè)包的名字乘寒,則安裝當(dāng)前 npm registry 中這個(gè)包的最新版本矩肩;如果要指定版本的,可以把版本號(hào)寫在包名后面肃续,例如 npm i webpack@3.0.0 --save
黍檩。
npm install
也支持 tag,tar 包地址等等始锚,不過那些不太常用刽酱,可以查看官方文檔。
dependencies 比較簡單瞧捌,我就不再多做解釋了棵里。注意一點(diǎn):npm 5.x 開始可以省略 --save
,即如果執(zhí)行 npm install xxx
姐呐,npm 一樣會(huì)把包的依賴添加到 package.json 中去殿怜。要關(guān)閉這個(gè)功能,可以使用 npm config set save false
曙砂。
npm install
把邏輯代碼pull到本地之后头谜,通過npm install拉取到node_modules文件夾。依賴管理鸠澈。一定要初始化柱告,要有package.json文件
Express
介紹
Express 是一個(gè)第三方模塊,用于快速搭建服務(wù)器
Express 是一個(gè)基于 Node.js 平臺(tái)笑陈,快速际度、開放、極簡的 web 開發(fā)框架涵妥。
express保留了http模塊的基本API乖菱,使用express的時(shí)候,也能使用http的API
express還額外封裝了一些新方法,能讓我們更方便的搭建服務(wù)器
安裝express
項(xiàng)目文件夾中窒所,執(zhí)行npm i express
即可下載安裝express娜氏。
注意:express不能安裝在express文件夾中。否則安裝失敗墩新。
使用express搭建web服務(wù)器
步驟:
加載express模塊
創(chuàng)建express服務(wù)器
開啟服務(wù)器贸弥,設(shè)置端口
監(jiān)聽瀏覽器的請求并進(jìn)行處理
代碼演示:
// 1、加載express模塊
const express = require('espress')
// 2海渊、創(chuàng)建express服務(wù)器
const app = express()
// 3绵疲、設(shè)置端口、開啟服務(wù)器
app.listen(8001, () => console.log('開啟服務(wù)器'))
// 4臣疑、監(jiān)聽瀏覽請請求并處理
app.get('GET請求的地址', 處理函數(shù))
app.post('POST請求的地址', 處理函數(shù));</pre>
express封裝的新方法
express之所以能夠?qū)崿F(xiàn)web服務(wù)器的搭建盔憨,是因?yàn)槠鋬?nèi)部對核心模塊http進(jìn)行了封裝。提供一些非常好用的新方法讯沈。http方法也能使用郁岩。
-
req
獲取POST請求體
req.body
獲取GET請求參數(shù)(查詢字符串格式)
req.query
獲取GET請求動(dòng)態(tài)參數(shù)(動(dòng)態(tài)路由)
req.params
其他...
-
res
res.sendFile(文件的絕對路徑)
-- 讀取文件,并將結(jié)果響應(yīng)缺狠。后面不要有res.send()
res.set({name, value})
-- 設(shè)置響應(yīng)頭res.status(200)
-- 設(shè)置響應(yīng)狀態(tài)碼res.send(字符串或?qū)ο?
-- 響應(yīng)結(jié)果问慎。end()
和字符集效果res.json(對象)
-- 以JSON格式響應(yīng)結(jié)果res.jsonp() -- 以JSONP格式響應(yīng)結(jié)果
其他...
-
app
app.get()
-- 處理客戶 端的GET請求app.post()
-- 處理客戶端的POST請求app.use()
-- 設(shè)置應(yīng)用級(jí)別的配置其他...
-
express
express.static() -- 開放靜態(tài)資源
express.urlencoded() -- 獲取POST請求體
其他...
GET接口
app.get('請求的URL', callback);
查詢字符串 常規(guī)參數(shù)
?id=10&name=lw
獲取參數(shù)方式:
res.query
代碼演示
// 寫接口
app.get('/index', (req, res) => {
console.log(req.query); // { id: '3', bookname: 'zxx', age: '20' }
});</pre>
動(dòng)態(tài)參數(shù)(動(dòng)態(tài)路由)
url/:id/:name
獲取參數(shù)方式
res.params
代碼演示
// /index/:id/:name 接口 動(dòng)態(tài)參數(shù)
// 瀏覽器的請求:http://locallhost:3001/index1/20/ww
app.get('/index1/:id/:name', (req, res) => {
console.log(req.params) //{ id: '20', name: 'ww' } 可以獲取所有動(dòng)態(tài)參數(shù)
res.send()
})</pre>
-
匹配到所有的GET請求-配置404
-
app.get('*', (req, res) => {})
他能夠匹配到所有的GET請求,所以把它放到所有接口的最后挤茄。
-
POST接口
app.post('請求的URL', callback)
獲取POST請求體
GET沒有請求體如叼。POST方式才是才有請求體
請求體,即客戶端提交的數(shù)據(jù)
可以使用http模塊中的方法穷劈,獲取請求體
-
POST請求體笼恰,有哪些格式
查詢字符串 -- 對應(yīng)的
Content-Type: application/x-www-form-urlencoded
FormData對象 -- 對應(yīng)的
Content-Type: multipart/form-data; --XXADFsdfssf
請求體是查詢字符串
const path = require('path')
const express = require('express')
const app = express()
app.listen(8001, () => console.log('開啟服務(wù)器'))
// 全局應(yīng)用級(jí)配置
//可以幫我們接收 content-type: application/x-www-form-urlencoded類型的請求體
app.use(express.urlencoded({ extended: false }))
app.post('/index', (req, res) => {
// 獲取post的請求體 請求體是查詢字符串
// 配置之后,任何一個(gè)POST接口歇终,都可以通過req.body獲取到請求體的內(nèi)容
console.log(req.body) //[Object: null prototype] { name: 'zs', age: '20', id: '10' }
res.send()
})</pre>
postman發(fā)送一個(gè)POST方式的請求社证,來配合測試:
點(diǎn)擊POST,選中body评凝,選中x-www-formurlencoded追葡。模擬發(fā)送post請求
請求體是FormData對象
需要使用第三方模塊(multer)才能夠獲取到。
案例:圖書接口
使用cors模塊肥哎,實(shí)現(xiàn)跨資源共享 允許跨域 1辽俗、npm i cors 2疾渣、加載 const cors = require('cors) 3篡诽、app.use(cors())
使用cors模塊,實(shí)現(xiàn)跨資源共享 允許跨域
1榴捡、npm i cors
2杈女、加載 const cors = require('cors)
3、app.use(cors())
const cors = require('cors')
const fs = require('fs')
const path = require('path')
const express = require('express')
const app = express()
app.listen(3006, () => console.log('開啟服務(wù)器'))
// 接收post請求的 查詢字符串參數(shù) req.body
app.use(express.urlencoded({ extended: false }))
// 通過應(yīng)用級(jí)的配置,設(shè)置接口可以跨域
// app.use((req, res, next) => {
// res.set({
// 'Access-Control-Allow-Origin': '*',
// })
// next()
// })
// cors 的第三方模塊 實(shí)現(xiàn)跨域
app.use(cors())
// 獲取圖書列表路由配置
app.get('/api/getbooks', (req, res) => {
// 獲取圖書列表文件
let data = require(path.join(__dirname, './books.json'))
res.json({
status: 200,
msg: '列表接口讀取成功',
data: data,
})
})
// 添加圖書
app.post('/api/addbook', (req, res) => {
// 獲取參數(shù)
req.body.id = Date.now() //使用時(shí)間戳做id
// 獲取圖書列表文件
let data = require(path.join(__dirname, './books.json'))
// 把獲取到的參數(shù)添加到圖書列表文件中
data.push(req.body)
// 寫入數(shù)據(jù)
fs.writeFile(
path.join(__dirname, './books.json'),
JSON.stringify(data, null, 2),
(err) => {
if (err) {
res.json({
status: 500,
msg: '添加圖書失敗',
})
} else {
res.json({
status: 201,
msg: '添加圖書成功',
})
}
}
)
})
// 刪除圖書
app.get('/api/delbook', (req, res) => {
// 2达椰、讀取數(shù)據(jù)文件內(nèi)容
// 3翰蠢、刪除id對應(yīng)數(shù)據(jù)項(xiàng)
// 4、向數(shù)據(jù)文件寫入新數(shù)據(jù)
// 1啰劲、拿到id
let id = req.query.id //拿到get請求 靜態(tài)數(shù)據(jù)id
// 2梁沧、驗(yàn)證id 找不到或者不規(guī)范的時(shí)候
if (!id) {
res.json({
status: 500,
msg: '未指定要?jiǎng)h除的圖書Id',
})
return
}
// 拿到文件數(shù)據(jù)
let data = require(path.join(__dirname, './books.json'))
// 篩選數(shù)據(jù),將選中的id刪除
data = data.filter((item) => item.id != id)
// 寫入數(shù)據(jù)
fs.writeFile(
path.join(__dirname, './books.json'),
JSON.stringify(data, null, 2),
(err) => {
if (err) {
res.json({
status: 500,
msg: '刪除圖書失斢恪廷支!',
})
} else {
res.json({
status: 200,
msg: '刪除圖書成功!',
})
}
}
)
})
</pre>
使用第三方模塊栓辜,實(shí)現(xiàn)跨域資源共享
實(shí)現(xiàn)跨域資源共享恋拍,可以使用一個(gè)叫做 cors 的第三方模塊。推薦使用它來實(shí)現(xiàn)跨域資源共享藕甩。
使用方法:
下載安裝cors
npm i cors
const cors = require('cors');
--- 加載模塊app.use(cors());
-- 使用use方法即可
開放靜態(tài)資源
什么是靜態(tài)資源:CSS文件施敢、圖片文件、JS文件等等
開放靜態(tài)資源:開放出來狭莱,使客戶端能夠訪問
-
具體做法:
比如僵娃,允許客戶端訪問某文件夾中的文件
app.use(express.static('絕對路徑'))
d通過應(yīng)用級(jí)配置
【注】如果配置多個(gè)靜態(tài)資源目錄有同名,會(huì)按照順序顯示腋妙。
配置一個(gè)別名悯许,可以用來標(biāo)識(shí)目錄app.use('/別名',express.static('絕對路徑'))
通過別名訪問,互不干擾
接收POST請求體
-
POST請求體的類型(Content-Type)
application/x-www-form-urlencoded 比如:id=1&name=zs&age=20
form-data 比如辉阶,提交的是FormData對象
application/json 比如先壕,提交的是 {"id": 1, "name": "zs", "age": 20}
其他...
-
服務(wù)器端接收不同類型的請求體,使用的方式是不同的
urlencoded --->
app.use(express.urlencoded({extended: false}));
application/json --->
app.use(express.json());
-- 沒有演示form-data ---> 服務(wù)器端使用第三方模塊處理(
multer
)
當(dāng)初學(xué)習(xí)ajax的時(shí)候谆甜,如果是POST請求垃僚,為什么要加Content-Type
路由
express中的路由
指的是客戶端的請求與服務(wù)器處理函數(shù)之間的映射關(guān)系。
Express 中的路由分 3 部分組成规辱,分別是請求的類型谆棺、請求的 URL 地址、處理函數(shù)罕袋,格式如下
// 路徑 改淑,就是我們之前說的接口的處理程序
app.get('/api/getbooks', (req, res) => {
});
app.post('/api/getbooks', (req, res) => {
});
app.post('/api/addbook', (req, res) => {
});</pre>
每當(dāng)一個(gè)請求到達(dá)以后,都需要先經(jīng)過路由的配置浴讯,只有匹配成功之后朵夏,才會(huì)調(diào)用對應(yīng)的處理函數(shù)。
在匹配的時(shí)候榆纽,會(huì)按照路由的順序進(jìn)行匹配仰猖,如果請求的URL和請求的方式同時(shí)匹配成功捏肢,則Express會(huì)將這次的請求,轉(zhuǎn)交給對應(yīng)function函數(shù)進(jìn)行處理饥侵。
模塊化路由
為了方便對路由進(jìn)行模塊化管理鸵赫。Express不建議直接將路由掛載到app上面運(yùn)行,而是推薦將路由抽離出來成為單獨(dú)的模塊躏升。抽離的步驟如下:
-
創(chuàng)建路由對應(yīng)的.js文件:
創(chuàng)建router.js 存放 登錄辩棒、注冊、驗(yàn)證碼三個(gè)路由
引入express模塊膨疏,
const express = require('express');
- 調(diào)用express.Router()函數(shù)創(chuàng)建路由對象盗温。路由對象router中會(huì)自動(dòng)攜帶req、res成肘。不用額外傳遞
const router = express.Router();
- 向路由對象上掛載具體的路由--配置路由卖局。路由對象叫啥,下面就叫啥双霍。不要寫app了砚偶。
// 把a(bǔ)pp換成router,比如
router.get('/xxx/xxx', (req, res) => {});
router.post('/xxx/xxx', (req, res) => {});</pre>
-
導(dǎo)出路由對象洒闸,使用
nodule.express
向外共享路由文件module.exports = router;
-
在主文件中引入路由文件
const router = require('./router.js')
在主文件中使用路由
app.use(router)
// app.js 中染坯,將路由導(dǎo)入,注冊路由
const login = require('./router/logon.js');
app.use(login)
// app.use(require('./router/heroes.js'));
app.use( require(path.join(__dirname, 'router', 'heores.js')) );</pre>
為路由模塊添加前綴
路由模塊化之后丘逸,可以按照須有拆分成多個(gè)路由文件单鹿。每個(gè)被拆分的文件都要有引入創(chuàng)建導(dǎo)出
我們可以省略路由模塊中的 /api
前綴,而是在注冊路由的時(shí)候深纲,統(tǒng)一設(shè)置仲锄。路由文件中,把前綴 /api 和 /my 去掉
// 導(dǎo)入路由模塊湃鹊,并注冊路由
app.use('/api', require(path.join(__dirname, 'router', 'login.js')) );
app.use('/my', require(path.join(__dirname, 'router', 'heroes.js')) );</pre>
使用路由模塊的好處
分模塊管理路徑儒喊,提高了代碼的可讀性
可維護(hù)性更強(qiáng)
減少路由的匹配次數(shù)
權(quán)限管理更方便
etc...
其他:
throw err是js中的語法。拋出語句異常
作用:
1币呵、把錯(cuò)誤的信息打到控制臺(tái)
2怀愧、阻止程序的運(yùn)行