NODE.JS

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ù)器的基本步驟

  1. 導(dǎo)入http核心模塊

  2. 使用http.creatServer()方法創(chuàng)建一個(gè)web服務(wù)器篙议,返回一個(gè)Server實(shí)例

  3. 給Server實(shí)例綁定request 事件唾糯,監(jiān)聽客戶端的請求。當(dāng)客戶端發(fā)送請求過來鬼贱,會(huì)觸發(fā)服務(wù)器的request請求事件移怯,然后執(zhí)行回調(diào)函數(shù)

  4. 綁定端口號(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()

【注】

  • 所有的請求路徑 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ī)定:

  1. 模塊作用域

  2. 每個(gè)模塊內(nèi)部局待,module 變量代表當(dāng)前模塊。

  3. 使用require() 方法用于加載模塊

  4. module 變量是一個(gè)對象菱属,它的 exports 屬性(即 module.exports)是對外的接口钳榨。使用exports接口對象導(dǎo)出模塊中的成員

  5. 加載某個(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 里面(這里 iinstall 的簡寫挺益,兩者均可)。

如果直接只寫一個(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 官網(wǎng)

  • Express 中文文檔(非官方)

  • Express GitHub倉庫

安裝express

項(xiàng)目文件夾中窒所,執(zhí)行npm i express即可下載安裝express娜氏。

注意:express不能安裝在express文件夾中。否則安裝失敗墩新。

使用express搭建web服務(wù)器

步驟:

  1. 加載express模塊

  2. 創(chuàng)建express服務(wù)器

  3. 開啟服務(wù)器贸弥,設(shè)置端口

  4. 監(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

// 寫接口
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

// /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ú)的模塊躏升。抽離的步驟如下:

  1. 創(chuàng)建路由對應(yīng)的.js文件:

    創(chuàng)建router.js 存放 登錄辩棒、注冊、驗(yàn)證碼三個(gè)路由

  2. 引入express模塊膨疏,

const express = require('express');

  1. 調(diào)用express.Router()函數(shù)創(chuàng)建路由對象盗温。路由對象router中會(huì)自動(dòng)攜帶req、res成肘。不用額外傳遞

const router = express.Router();

  1. 向路由對象上掛載具體的路由--配置路由卖局。路由對象叫啥,下面就叫啥双霍。不要寫app了砚偶。

// 把a(bǔ)pp換成router,比如
router.get('/xxx/xxx', (req, res) => {});
router.post('/xxx/xxx', (req, res) => {});</pre>

  1. 導(dǎo)出路由對象洒闸,使用nodule.express向外共享路由文件

    module.exports = router;

  2. 在主文件中引入路由文件

    const router = require('./router.js')

  3. 在主文件中使用路由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)行

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市余赢,隨后出現(xiàn)的幾起案子芯义,更是在濱河造成了極大的恐慌,老刑警劉巖妻柒,帶你破解...
    沈念sama閱讀 217,277評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件扛拨,死亡現(xiàn)場離奇詭異,居然都是意外死亡蛤奢,警方通過查閱死者的電腦和手機(jī)鬼癣,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門陶贼,熙熙樓的掌柜王于貴愁眉苦臉地迎上來啤贩,“玉大人待秃,你說我怎么就攤上這事”砸伲” “怎么了章郁?”我有些...
    開封第一講書人閱讀 163,624評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長志衍。 經(jīng)常有香客問我暖庄,道長,這世上最難降的妖魔是什么楼肪? 我笑而不...
    開封第一講書人閱讀 58,356評(píng)論 1 293
  • 正文 為了忘掉前任培廓,我火速辦了婚禮,結(jié)果婚禮上春叫,老公的妹妹穿的比我還像新娘肩钠。我一直安慰自己,他們只是感情好暂殖,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,402評(píng)論 6 392
  • 文/花漫 我一把揭開白布价匠。 她就那樣靜靜地躺著,像睡著了一般呛每。 火紅的嫁衣襯著肌膚如雪踩窖。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,292評(píng)論 1 301
  • 那天晨横,我揣著相機(jī)與錄音洋腮,去河邊找鬼。 笑死手形,一個(gè)胖子當(dāng)著我的面吹牛徐矩,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播叁幢,決...
    沈念sama閱讀 40,135評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼滤灯,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了曼玩?” 一聲冷哼從身側(cè)響起鳞骤,我...
    開封第一講書人閱讀 38,992評(píng)論 0 275
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎黍判,沒想到半個(gè)月后豫尽,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,429評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡顷帖,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,636評(píng)論 3 334
  • 正文 我和宋清朗相戀三年美旧,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了渤滞。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,785評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡榴嗅,死狀恐怖妄呕,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情嗽测,我是刑警寧澤绪励,帶...
    沈念sama閱讀 35,492評(píng)論 5 345
  • 正文 年R本政府宣布,位于F島的核電站唠粥,受9級(jí)特大地震影響疏魏,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜晤愧,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,092評(píng)論 3 328
  • 文/蒙蒙 一大莫、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧官份,春花似錦只厘、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,723評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至悄谐,卻和暖如春介评,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背爬舰。 一陣腳步聲響...
    開封第一講書人閱讀 32,858評(píng)論 1 269
  • 我被黑心中介騙來泰國打工们陆, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人情屹。 一個(gè)月前我還...
    沈念sama閱讀 47,891評(píng)論 2 370
  • 正文 我出身青樓坪仇,卻偏偏與公主長得像,于是被迫代替她去往敵國和親垃你。 傳聞我的和親對象是個(gè)殘疾皇子椅文,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,713評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容

  • Node介紹 為什么要學(xué)習(xí)Node.js 企業(yè)需求具有服務(wù)端開發(fā)經(jīng)驗(yàn)更改front-endback-end全棧開發(fā)...
    廢棄的種子閱讀 438評(píng)論 0 0
  • node.js 介紹 node.js是什么 node.js 是一個(gè)開發(fā)平臺(tái),就像java開發(fā)平臺(tái)...何為開發(fā)平臺(tái)...
    小淺_閱讀 1,162評(píng)論 0 6
  • 一. 簡介 1.Node.js是js運(yùn)行在服務(wù)器的一個(gè)平臺(tái)2.Node中,每一個(gè)js文件中的代碼都是獨(dú)立運(yùn)行在一個(gè)...
    codingZero閱讀 413評(píng)論 0 0
  • 4. 增加郵箱驗(yàn)證功能 剛剛我們只是實(shí)現(xiàn)了登錄的流程惜颇,不過里面用的驗(yàn)證碼是假的皆刺,我們考慮下實(shí)現(xiàn)真正的郵箱驗(yàn)證碼發(fā)送...
    小五同學(xué)H閱讀 359評(píng)論 0 0
  • 個(gè)人入門學(xué)習(xí)用筆記、不過多作為參考依據(jù)凌摄。如有錯(cuò)誤歡迎斧正 目錄 簡書好像不支持錨點(diǎn)羡蛾、復(fù)制搜索(反正也是寫給我自己看...
    kirito_song閱讀 2,469評(píng)論 1 37