總結Node.js模組開發及常用技巧分享

2022-08-08 18:01:19

一、模組化

模組化做為一種現代化的設計方法,這個概念最早起源於生產製造行業。如今這個概念已經被各行各業來衍生應用,在軟體開發中也大量的採用了模組化思想。

所謂的模組化思想,將一個大程式按照功能劃分為若干個小的模組,每個小程式模組完成一個特定的功能,所有的模組按某種方法組裝起來,成為一個整體,完成整個系統所要求功能的程式設計方法。【推薦:】

(一)、為什麼需要模組化

模組化可以使你的程式碼低耦合,功能模組直接不相互影響。

為什麼需要模組化:

  • 程式複雜度上升程式碼越寫越多,在一個檔案里程式碼就會越來越長,不易維護。(把完成特定功能的程式碼分組,分別放到不同的檔案裡,這樣,每個檔案包含的程式碼就相對較少)

  • JavaScript 有複雜的依賴關係的時候就很容易出現一些變數的屬性或方法被覆蓋或改寫,導致變數汙染。這是因為js沒有名稱空間,不像其他語言通過名稱空間可以有效的避免重名問題。

  • 想要存在JavaScript 私有的變數

模組化思想解決問題:

  • 可維護性:每個模組都是單獨定義的,之間相互獨立。模組儘可能的需要和外部撇清關係,方便我們獨立的對其進行維護與改造。維護一個模組比在全域性中修改邏輯判斷要好的多。

  • 命名衝突:為了避免在JavaScript中的全域性汙染,我們通過模組化的方式利用函數作用域來構建名稱空間,避免命名衝突。

  • 檔案依賴:一個功能可能依賴一個或多個其他檔案,使用是除了引入它本身還需要考慮依賴檔案,通過模組化 我們只需要引入檔案,無需考慮檔案依賴(模組化可以幫助我們解決檔案依賴問題)。

  • 可複用性:雖然貼上覆制很簡單,但是要考慮到我們之後的維護以及迭代。

(二)、什麼是Nodejs模組

為了讓Nodejs的檔案可以相互呼叫,Nodejs基於CommonJS規範提供了一個簡單的模組系統。(nodejs實現並遵守CommonJS規範的)。

把具有公共功能的,抽離成一個單獨的js檔案作位一個模組。預設情況下,模組裡的方法或屬性,外面是存取不到的。如果想要在外面存取這些屬性,方法,就必須在模組裡通過exportsmodule.exports暴露,在需要使用的地方通過require()進行引入。

//exports語法範例

// sum.js
exports.sum = function(a,b){
    return a+b;
}

// main.js
var m = require("./sum");
var num = m.sum(10,20);
console.log(num);

//modules.exports語法範例

//sum.js
function sum(a,b){
    return a+b;
}
module.exports= sum;
//main.js
var sum = require('./sum');
sum(10,20);// 30

CommonJS 規定:

  • 每個模組內部,module 變數代表當前模組

  • module 變數是一個物件,它的 exports 屬性(即 module.exports)是對外的介面

  • 載入某個模組,其實是載入該模組的 module.exports 屬性。require() 方法用於載入模組。

(三)、nodejs中的模組分類與載入方式

Node.js 中根據模組來源的不同,將模組分為了 3 大類,分別是:

  • 內建模組(內建模組是由 Node.js 官方提供的,例如 fs、path、http 等)

  • 自定義模組(使用者建立的每個 .js 檔案,都是自定義模組)

  • 第三方模組(包)(由第三方開發出來的模組,並非官方提供的內建模組,也不是使用者建立的自定義模組,使用前需要先下載)

//1.載入內建模組不需要指定路徑
var http = require('http');

//2.載入使用者的自定義模組
var sum = require('./sum.js');

//3.載入第三方模組
const md5=require("md5");

(四)、模組作用域

  • 和函數作用域類似,在自定義模組中定義的變數、方法等成員,只能在當前模組內被存取,這種模組級別的存取限制,叫做模組作用域。
  • 模組作用域的好處:防止了全域性變數汙染的問題

二、npm與包

(一)、包的介紹

  • Node.js 中的第三方模組又叫做包。包是由第三方個人或團隊開發出來的,免費供所有人使用。
  • Node.js 的內建模組僅提供了一些底層的 API,導致在基於內建模組進行專案開發的時,效率很低。
    包是基於內建模組封裝出來的,提供了更高階、更方便的 API,極大的提高了開發效率。
  • 國外有一家 IT 公司,叫做 npm, Inc. 這家公司旗下有一個非常著名的網站: https://www.npmjs.com/ ,它是全球最大的包共用平臺。
  • 我們可以使用這個包管理工具, npm ,來對包進行管理,這個包管理工具隨著 Node.js 的安裝包一起被安裝到了使用者的電腦上。檢測其版本。npm -v

(二)、npm的使用

  • npm init 進行初始化,生成package.json 檔案,記錄專案的資訊,記錄包的資訊
  • npm install 包名 npm i 包名 下載包,放到node_modules資料夾裡
  • npm i 包名 --save npm i 包名 -S (開發環境中)
  • npm i 包名 --save-dev npm i 包名 -D (生產環境中)
  • npm list 列舉當前目錄下安裝的包
  • npm i 包名@1 安裝指定的版本
  • npm i 包名 -g 安裝全域性包
  • npm uninstall 包名 解除安裝包

(三)、全域性安裝nrm nodemon

nrm 是一個管理 npm 源的工具。有時候國外資源太慢,使用這個就可以快速的在npm源間切換。

手動切換方法:

npm config set registry=https://registry.npm.taobao.org

安裝 nrm:

$ npm i nrm -g

檢視nrm 內建的幾個 npm 源的地址:

$ nrm ls

結果如下:

  npm ---- https://registry.npmjs.org/
  cnpm --- http://r.cnpmjs.org/
* taobao - https://registry.npm.taobao.org/
  nj ----- https://registry.nodejitsu.com/
  rednpm - http://registry.mirror.cqupt.edu.cn/
  npmMirror  https://skimdb.npmjs.com/registry/
  edunpm - http://registry.enpmjs.org/

切換nrm:

$ nrm use npm

檢視當前的映象源:

npm config get register

(四)、淘寶cnpm工具

淘寶 NPM 映象是一個完整 npmjs.org 映象,你可以用此代替官方版本(唯讀),同步頻率目前為 10分鐘 一次以保證儘量與官方服務同步。

你可以使用淘寶客製化的 cnpm (gzip 壓縮支援) 命令列工具代替預設的 npm:

npm install -g cnpm -registry=https://registry.npm.taobao.org

安裝包

cnpm install [模組名]

三、路由

路由:根據不同的路徑返回不同的頁面。

案例:server.js;static;route.js;route物件;render();api.js;封裝server.js到index.js;合併物件

獲取請求引數:login頁面發get,post請求,到/api/login

靜態資源託管:

express

Express是一個基於 Node.js 平臺,快速、開放、極簡的 Web 開發框架。

一、下載與安裝

$ npm install express --save

案例:第一個express案例。

二、路由

所謂的路由就是使用者端用來與後端伺服器進行互動的一種方式,使用者端採用特定的URL與請求方法來存取伺服器端,伺服器端通過響應返回特定資源。

路由的定義由如下結構組成:

app.METHOD(PATH, HANDLER)
名稱描述
appapp 是一個 express 範例
METHODMETHOD用於指定要匹配的HTTP請求方式
PATHPATH是伺服器端的路徑
HANDLER是當路由匹配時需要執行的處理程式(回撥函數)

路由路徑和請求方法一起定義了請求的端點,它可以是字串,字串模式以及正規表示式。

app.get('/', function (req, res) {
  res.send('root')})app.get('/about', function (req, res) {
  res.send('about')})app.get('/random.text', function (req, res) {
  res.send('random.text')})

使用字串模式的路由路徑範例:

app.get('/ab?cd', function (req, res) {
  res.send('ab?cd')  //abcd ,acd})app.get('/ab/:id', function (req, res) {
  res.send('ab/:id')  })app.get('/ab+cd', function (req, res) {
  res.send('ab+cd')    //b可以一次或者多次的重複})app.get('/ab*cd', function (req, res) {
  res.send('ab*cd')  //在ab,cd之間隨意寫入任意字元})app.get('/ab(cd)?e', function (req, res) {
  res.send('ab(cd)?e')})

可以為請求處理提供多個回撥函數,其行為類似中介軟體。

案例:中介軟體f1,f2

app.get('/example/b', function (req, res, next) {
  console.log('the response will be sent by the next function ...')
  next()}, function (req, res) {
  res.send('Hello from B!')})
var cb0 = function (req, res, next) {
  console.log('CB0')
  next()}var cb1 = function (req, res, next) {
  console.log('CB1')
  next()}var cb2 = function (req, res) {
  res.send('Hello from C!')}app.get('/example/c', [cb0, cb1, cb2])
var cb0 = function (req, res, next) {
  console.log('CB0')
  next()}var cb1 = function (req, res, next) {
  console.log('CB1')
  next()}app.get('/example/d', [cb0, cb1], function (req, res, next) {
  console.log('the response will be sent by the next function ...')
  next()}, function (req, res) {
  res.send('Hello from D!')})

三、中介軟體

1.應用級中介軟體

在Express程式中,使用 app.use()app.METHOD() 方法將中介軟體系結到應用程式物件(app)。

凡是掛載在app身上的都是應用級中介軟體。

app.use() : 應用中的每個請求都可以執行其程式碼

//萬能中介軟體var express = require('express')var app = express()app.use(function (req, res, next) {
    console.log('Time:', Date.now())
    next()})
//特定路由的應用中介軟體app.use("/login",function (req, res, next) {
    console.log('Time:', Date.now())})

2.路由級中介軟體

路由器級中介軟體的工作方式與應用級中介軟體相同,只是它繫結到express.Router().

var router = express.Router()
var express = require('express')var app = express()var router = express.Router()router.use(function (req, res, next) {
    console.log('Time:', Date.now())
    next()})router.get('/user/:id', function (req, res, next) {
    console.log('Request URL:', req.originalUrl)
    next()}, function (req, res, next) {
    console.log('Request Type:', req.method)
    next()})

案例: / ; /home , /list

3.錯誤處理中介軟體

與其他中介軟體函數相同的方式定義錯誤處理中介軟體函數,但是使用四個引數(err, req, res, next),放到最後。

app.use(function (err, req, res, next) {
  console.error(err.stack)
  res.status(404).send('Something broke!')})

4.內建中介軟體

  • express.static提供靜態資源,例如 HTML 檔案、影象等。

  • express.json使用 JSON 有效負載解析傳入請求。注意:可用於 Express 4.16.0+

    application/json

    由於JSON規範的流行,現在越來越多的開發者將application/json這個Content-Type作為響應頭。用來告訴伺服器端訊息主體是序列化後的JSON字串。除了低版本IE之外各大瀏覽器都原生支援 JSON.stringify,伺服器端語言也都有處理JSON的函數,JSON能格式支援比鍵值對複雜得多的結構化資料,普通鍵值對中的值只能是字串,而使用json,鍵值對可以重複巢狀。

    // 應用級別中介軟體,獲取post--json引數app.use(express.json());
  • express.urlencoded解析帶有 URL 編碼負載的傳入請求。 注意:可用於 Express 4.16.0+

    application/x-www-form-urlencoded
    瀏覽器的原生form表單,如果不設定enctype屬性,那麼最終就會以 application/x-www-form-urlencoded方式提交資料。Content-Type被指定為application/x-www-form-urlencoded提交的資料按照key=val&key=val的方式進行編碼,並且key和val都進行了URL轉碼。

    // 應用級別中介軟體,獲取post--form引數app.use(express.urlencoded({extended:false}));

5.第三方中介軟體

四、獲取請求引數

  • req.query 是一個可獲取使用者端get請求 查詢字串 轉成的物件,預設為{}。
  • req.body 包含在請求體中提交的資料鍵值對。預設情況下undefined,當使用解析中介軟體express.json()express.urlencoded()

五、靜態資源託管

為了提供諸如影象、CSS 檔案和 JavaScript 檔案之類的靜態檔案,請使用 Express 中的 express.static 內建中介軟體函數。

語法:

express.static內建中介軟體函數語法:

express.static(root, [options])
  • root引數指定提供靜態資源的根目錄。

靜態資源範例:

例如,通過如下程式碼就可以將 public 目錄下的圖片、CSS 檔案、JavaScript 檔案對外開放存取了:

app.use(express.static('public'))

現在,你就可以存取 public 目錄中的所有檔案了:

http://localhost:3000/images/kitten.jpg
http://localhost:3000/css/style.css
http://localhost:3000/js/app.js
http://localhost:3000/images/bg.png
http://localhost:3000/hello.html

Express 在靜態目錄查詢檔案,因此,存放靜態檔案的目錄名不會出現在 URL 中。

多個靜態資源目錄:

如果要使用多個靜態資源目錄,請多次呼叫 express.static 中介軟體函數:

app.use(express.static('public'))
app.use(express.static('uploads'))

存取靜態資原始檔時,express.static 中介軟體函數會根據目錄的新增順序查詢所需的檔案。

虛擬路徑:(非得新增static,沒有意義)

express.static中介軟體函數可以為某些靜態資源服務建立虛擬路徑字首(該路徑實際上並不存在於檔案系統中),請指定靜態目錄的掛載路徑,如下所示:

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

現在,你就可以通過帶有 /static 字首地址來存取 public 目錄中的檔案了。

http://localhost:3000/static/images/kitten.jpg
http://localhost:3000/static/css/style.css
http://localhost:3000/static/js/app.js
http://localhost:3000/static/images/bg.png
http://localhost:3000/static/hello.html

六、模板引擎

一、.伺服器端渲染 SSR

後端巢狀模板,後端渲染模板 (後端把頁面組裝起來)

  1. 做好靜態頁面,動態效果
  2. 把前端程式碼提供給後端,後端要把靜態html以及裡面的假資料給刪掉,通過模板進行動態生成html的內容

[外連圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片儲存下來直接上傳(img-jL70ca3p-1658387147221)(C:\Users\11933\Desktop\前端全棧\課件\前後臺互動\imgs\伺服器端渲染.png)]

二、前後端分離,BSR

(前後端分離,通過通用的json資料形式,不挑後端的語言)

  1. 做好靜態頁面,動態效果
  2. json模擬,ajax動態建立頁面
  3. 真實介面資料,前後聯調

[外連圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片儲存下來直接上傳(img-pXRCidw2-1658387147223)(C:\Users\11933\Desktop\前端全棧\課件\前後臺互動\imgs\前後端分離.png)]

三、模板引擎

模板引擎能夠在應用程式中使用靜態模板檔案。在執行時,模板引擎將模板檔案中的變數替換為實際值,並將模板轉換為傳送給使用者端的 HTML 檔案。這種方法使設計 HTML 頁面變得更加容易。

Express模板引擎

與 Express 一起使用的一些流行模板引擎是Pug、 Mustache和EJS。Express 應用程式生成器預設使用Pug,但它也支援其他幾個。

需要在應用中進行如下設定才能讓Express渲染模板引擎:

  • views,放模板檔案的目錄。例如:app.set('views', './views')
  • view engine,要使用的模板引擎。例如,要使用 Pug 模板引擎:app.set('view engine', 'pug').
在路由中渲染模板

在路由渲染模板並將渲染後的 HTML 字串傳送到使用者端。

res.render(view [, locals] [, callback])
  • view:一個字串,view是要渲染的模板檔案的檔案路徑。
  • locals:一個物件,其屬性定義檢視的區域性變數。
app.get('/', function (req, res) {
  res.render('index', { title: 'Hey', message: 'Hello there!' })
})
四、ejs模板引擎的使用
安裝ejs
npm install ejs
在express設定ejs模板引擎
使用ejs模板引擎

在app.js中新增如下程式碼,設定Express使用ejs模板引擎。

app.set('views',path.join(__dirname,'views')); //設定模板儲存位置app.set('view engine','ejs');

注意:此時指定的模板目錄為views,且模板檔案的字尾名為.ejs

設定模板字尾為html

在app.js中新增如下程式碼,設定Express使用ejs模板引擎。並指定模板字尾名為html。

app.set('views',path.join(__dirname,'views')); //設定模板儲存位置app.set('view engine','html');app.engine('html',require('ejs').renderFile); //使用ejs模板引擎解析html

注意:此時指定的模板目錄為views,且模板檔案的字尾名為.html

ejs模板語法
<%= %>   輸出標籤
<%- %>   輸出html標籤(html會被瀏覽器解析)
<%# %>   註釋標籤
<% %>    流程控制標籤(寫的是if,else,for)
<%- include("user/show",{user:user})%>  匯入公共的模板內容

MVC框架:

是一種設計模式,是軟體架構得模式,是在web開發過程中總結的一些套路或者是模組化的內容。M是指業務模型(module),V是指使用者介面(view),C則是控制器(controller)。使用mvc最大的優勢就是分層,目的是將M和V的實現程式碼分離,存在的目的則是確保M和V的同步,一旦M改變,V應該同步更新。MVC是相互獨立的,M,C(後端); V(前端)。路由規劃為Controller。

JSON:

一、概念:

JSON(JavaScript Object Notation, JS物件表示法)簡單來講,JSON 就是 Javascript 物件和陣列的字串表示法,因此,JSON 的本質是字串。

作用:JSON 是一種輕量級的文字資料交換格式,在作用上類似於 XML,專門用於儲存和傳輸資料,但是 JSON 比 XML 更小、更快、更易解析。

現狀:JSON 是在 2001 年開始被推廣和使用的資料格式,到現今為止,JSON 已經成為了主流的資料交換格式。

二、JSON的兩種結構

JSON 就是用字串來表示 Javascript 的物件和陣列。所以,JSON 中包含物件和陣列兩種結構,通過這兩種結構的相互巢狀,可以表示各種複雜的資料結構。

  • 物件結構:物件結構在 JSON 中表示為 { } 括起來的內容。資料結構為 { key: value, key: value, … } 的鍵值對結構。其中,key 必須是使用英文的雙引號包裹的字串,value 的資料型別可以是數位、字串、布林值、null、陣列、物件6種型別。

    {
        "name": "zs",
        "age": 20,
        "gender": "男",
        "hobby": ["吃飯", "睡覺"]}
  • 陣列結構:陣列結構在 JSON 中表示為 [ ] 括起來的內容。資料結構為 [ 「java」, 「javascript」, 30, true … ] 。陣列中資料的型別可以是數位、字串、布林值、null、陣列、物件6種型別。

    [ 100, 200, 300 ][ true, false, null ][ { "name": "zs", "age": 20}, { "name": "ls", "age": 30} ][ [ "aaa", "bbb", "ccc" ], [ 1, 2, 3 ] ]

三、JSON語法的注意事項

  • 屬性名必須使用雙引號包裹
  • 字串型別的值必須使用雙引號包裹
  • JSON 中不允許使用單引號表示字串
  • JSON 中不能寫註釋
  • JSON 的最外層必須是物件或陣列格式
  • 不能使用 undefined 或函數作為 JSON 的值
  • JSON 的作用:在計算機與網路之間儲存和傳輸資料
  • JSON 的本質:用字串來表示 Javascript 物件資料或陣列資料

四、JSON和JS物件的關係

JSON 是 JS 物件的字串表示法,它使用文字表示一個 JS 物件的資訊,本質是一個字串。

//這是一個物件var obj = {a: 'Hello', b: 'World'}//這是一個 JSON 字串,本質是一個字串var json = '{"a": "Hello", "b": "World"}'

五、JSON和JS物件的互轉

  • 要實現從 JSON 字串轉換為 JS 物件,使用 JSON.parse() 方法
  • 要實現從 JS 物件轉換為 JSON 字串,使用 JSON.stringify() 方法

HTTP

一、概念

HTTP 協定即超文字傳送協定 (HyperText Transfer Protocol) ,它規定了使用者端與伺服器之間進行網頁內容傳輸時,所必須遵守的傳輸格式。(是一種約定與規則)

二、請求(請求報文)

使用者端發起的請求叫做 HTTP 請求,使用者端傳送到伺服器的訊息,叫做 HTTP 請求訊息,又叫做 HTTP 請求報文。

請求訊息的組成

HTTP 請求訊息由請求行(request line)、請求頭部( header ) 、空行 和 請求體 4 個部分組成。

[外連圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片儲存下來直接上傳(img-G502I2rT-1658387147224)(C:\Users\11933\Desktop\前端全棧\課件\前後臺互動\imgs\請求訊息組成部分.png)]

  • 請求行:由請求方式(get,post)、URL (/login?)和 HTTP 協定版本 3 個部分組成,他們之間使用空格隔開。
  • 請求頭部:用來描述使用者端的基本資訊,從而把使用者端相關的資訊告知伺服器。請求頭部由多行 鍵/值對 組成,每行的鍵和值之間用英文的冒號分隔。

[外連圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片儲存下來直接上傳(img-ImfA8U4y-1658387147225)(C:\Users\11933\Desktop\前端全棧\課件\前後臺互動\imgs\請求頭部欄位.png)]

  • 空行:最後一個請求頭欄位的後面是一個空行,通知伺服器請求頭部至此結束。請求訊息中的空行,用來分隔請求頭部與請求體。
  • 請求體:請求體中存放的,是要通過 POST 方式提交到伺服器的資料。只有 POST 請求才有請求體,GET 請求沒有請求體!

三、響應(響應報文)

響應訊息就是伺服器響應給使用者端的訊息內容,也叫作響應報文。

響應訊息的組成:

HTTP響應訊息由狀態行、響應頭部、空行 和 響應體 4 個部分組成。

[外連圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片儲存下來直接上傳(img-N0rfsHa8-1658387147225)(C:\Users\11933\Desktop\前端全棧\課件\前後臺互動\imgs\響應訊息組成部分.png)]

  • 狀態行:由 HTTP 協定版本、狀態碼和狀態碼的描述文字 3 個部分組成,他們之間使用空格隔開;
  • 響應頭部:用來描述伺服器的基本資訊。響應頭部由多行 鍵/值對 組成,每行的鍵和值之間用英文的冒號分隔。
  • 空行:在最後一個響應頭部欄位結束之後,會緊跟一個空行,用來通知使用者端響應頭部至此結束。響應訊息中的空行,用來分隔響應頭部與響應體。
  • 響應體:中存放的,是伺服器響應給使用者端的資源內容。

四、HTTP請求方法

HTTP 請求方法,屬於 HTTP 協定中的一部分,請求方法的作用是:用來表明要對伺服器上的資源執行的操作。最常用的請求方法是 GET 和 POST。

[外連圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片儲存下來直接上傳(img-vwQMQrAp-1658387147226)(C:\Users\11933\Desktop\前端全棧\課件\前後臺互動\imgs\http請求的方法.png)]

五、響應的狀態碼

[外連圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片儲存下來直接上傳(img-28YRkP8m-1658387147227)(C:\Users\11933\Desktop\前端全棧\課件\前後臺互動\imgs\http響應狀態碼.png)]

Ajax:

一、概念

AJAX 全稱為(Asynchronous JavaScript And XML),是非同步的JavaScript和XML。通過 ajax可以在瀏覽器向伺服器傳送非同步請求。最大的優勢,無重新整理獲取資料 。也就是說AJAX可以在不重新載入整個頁面的情況下,與伺服器交換資料。這種非同步互動的方式,使使用者單擊後,不必重新整理頁面也能獲取新資料。使用Ajax,使用者可以建立接近本地桌面應用的直接、高可用、更豐富、更動態的Web使用者介面。

二、XML

  • XML 指可延伸標記語⾔,HTML 超檔案標示語言
  • XML被設計用來傳輸和儲存資料
  • XML和HTML類似,不同的是HTML都是預定義的標籤,而XML沒有預定義標籤,全部都是自定義的標籤,用來表示一些資料。

最開始是前後臺進行資料互動的語言,現在是JSON。

'{"title":"三體","author":"zs","price":30}'<book>
    <title>三體</title>
    <author>劉慈欣</author>
    <price>30.00</price></book>

三、特點

優點:

  1. 可以無需重新整理頁面與伺服器進行通訊
  2. 允許你根據使用者事件來更新部分頁面內容

缺點:

  1. 沒有瀏覽歷史不能回退
  2. 存在跨越問題 同源策略:協定,域名,埠號
  3. SEO不友好

四、傳送請求

  • get方式,以及請求引數
// 1.建立物件var xhr=new XMLHttpRequest();// 2.初始化,設定請求方法和urlxhr.open("GET","http://127.0.0.1:3000/server?username=zs&password=1234");// 3.傳送xhr.send();// 4.繫結事件,處理伺服器端返回得結果// readstate  xhr得屬性  狀態  0,1,2,3,4xhr.onreadystatechange=function(){
    // 伺服器返回得結果
    if(xhr.readyState==4){
        // 判斷響應得狀態碼
        if(xhr.status==200){
            // 行,頭,體
            console.log(xhr.status);
            console.log(xhr.statusText);
            console.log(xhr.response);
            console.log(xhr.getAllResponseHeaders());
        }
    }}

專案:

一、對密碼進行加密處理

JavaScript使用CryptoJS加解密。CryptoJS時一個JavaScript的加解密的工具包。它支援多種的演演算法:MD5、SHA1、SHA2、SHA3、RIPEMD-160 雜湊雜湊,進行 AES、DES、Rabbit、RC4、Triple DES 加解密。在專案中如果要對前後端傳輸的資料雙向加密, 比如避免使用明文傳輸使用者名稱,密碼等資料。 就需要對前後端資料用同種方法進行加密,方便解密。

使用步驟:

  • 執行如下命令,安裝 CryptoJS
npm i crypto-js
  • /login.js 中,匯入 crypto-js
const crypto = require('crypto-js')
  • ASE進行純文字加密:
//加密var a=crypto.AES.encrypt("abc","key").toString();    //SecrectKey 祕鑰//解密var b=crypto.AES.decrypt(a,"key").toString(crypto.enc.Utf8);  //按照UTF8編碼解析出原始字串

二、表單校驗規則

在實際開發中,前後端都需要對錶單的資料進行合法性的驗證,而且,後端做為資料合法性驗證的最後一個關口,在攔截非法資料方面,起到了至關重要的作用。使用第三方資料驗證模組,來降低出錯率、提高驗證的效率與可維護性。

步驟:

  • 安裝 joi 包,為表單中攜帶的每個資料項,定義驗證規則:
npm install joi
  • 安裝 @escook/express-joi 中介軟體,來實現自動對錶單資料進行驗證的功能:
npm i @escook/express-joi
  • 新建 /schema/login.js 使用者資訊驗證規則模組:
const joi = require('joi')/**
 * string() 值必須是字串
 * alphanum() 值只能是包含 a-zA-Z0-9 的字串
 * min(length) 最小長度
 * max(length) 最大長度
 * required() 值是必填項,不能為 undefined
 * pattern(正規表示式) 值必須符合正規表示式的規則
 */// 使用者名稱的驗證規則const username = joi.string().required();// 密碼的驗證規則const password = joi.string().pattern(/^[\S]{6,12}$/).required();// 登入表單的驗證規則物件exports.login_schema = {
  // 表示需要對 req.body 中的資料進行驗證
  body: {
    username,
    password,
  },}
  • 修改 /router/admin/login.js 中的程式碼:
// 1. 匯入驗證表單資料的中介軟體const expressJoi = require('@escook/express-joi')// 2. 匯入需要的驗證規則物件const { login_schema } = require('../../schema/login');// 3登入功能router.post("/",expressJoi(login_schema),(req,res)=>{}];
  • index.js 的全域性錯誤級別中介軟體中,捕獲驗證失敗的錯誤,並把驗證失敗的結果響應給使用者端:
const joi = require('joi')// 錯誤中介軟體app.use(function (err, req, res, next) {
  // 資料驗證失敗
  if (err instanceof joi.ValidationError) return res.send(err);
  // 未知錯誤
  res.send(err)})

三、四種常見的POST提交資料方式

HTTP協定是以ASCII碼傳輸,建立在TCP/IP協定之上的應用層規範。規範把 HTTP 請求分為三個部分:狀態行、請求頭、訊息主體。協定規定 POST 提交的資料必須放在訊息主體(entity-body)中,但協定並沒有規定資料必須使用什麼編碼方式Content-Type。

伺服器端根據請求頭(headers)中的Content-Type欄位來獲知請求中的訊息主體是用何種方式編碼,再對主體進行解析。所以說到POST提交資料方案,包含了Content-Type 和訊息主體編碼方式兩部分。Content-Type的四種值分別代表四種方式,具體如下:

  • 方式一:application/x-www-form-urlencoded

瀏覽器的原生form表單,如果不設定enctype屬性,那麼最終就會以 application/x-www-form-urlencoded方式提交資料。Content-Type被指定為application/x-www-form-urlencoded提交的資料按照key=val&key=val的方式進行編碼,並且key和val都進行了URL轉碼。伺服器端例如 PHP 中,使用$_POST[′key′]可以獲取到值。

  • 方式二:multipart/form-data

常見的POST資料提交的方式。這種方式支援檔案上傳,不過必須要設定form的enctyped等於這個值。使用multipart/form-data方式會生成了一個boundary 來分割不同的欄位,為了避免與正文重複,boundary是一段很長的隨機拼接的字串。然後Content-Type指明資料是以mutipart/form-data來編碼幷包括進本次請求的boundary 值。訊息主體最後以 --boundary–標示結束。

  • 方式三:application/json

由於JSON規範的流行,現在越來越多的開發者將application/json這個Content-Type作為響應頭。用來告訴伺服器端訊息主體是序列化後的JSON字串。除了低版本IE之外各大瀏覽器都原生支援 JSON.stringify,伺服器端語言也都有處理JSON的函數,JSON能格式支援比鍵值對複雜得多的結構化資料,普通鍵值對中的值只能是字串,而使用json,鍵值對可以重複巢狀。

  • 方式四:text/xml

它是一種使用HTTP作為傳輸協定,XML作為編碼方式的遠端呼叫規範。不過後來使用很少。也許在十多年前,在json還未出來之前資料互動對接。

總之application/x-www-form-urlencoded和multipart/form-data兩種POST方式都是瀏覽器原生支援的,是普遍使用的兩種方式,application/json是現在比較流行的新趨勢。

四、multer

  • 安裝multer
npm i multer
  • 匯入multer
const multer  = require('multer')
  • 設定multer接收到的檔案儲存的資料夾和,存放的圖片的名字
//上傳檔案存放路徑、及檔案命名const storage = multer.diskStorage({
    destination: path.join(__dirname ,'../static/uploads'),  //確定上傳檔案的物理位置
    filename: function (req, file, cb) { //自定義設定檔案的名字,根據上傳時間的時間戳來命名
        let type = file.originalname.split('.')[1]
        cb(null, `${file.fieldname}-${Date.now().toString(16)}.${type}`)
    }})

1.sotrage是一個設定物件。他是通過multer.diskstorage儲存引擎生成的。multer.diskstorage需要傳遞一個設定物件,這裡的設定物件裡面接收兩個引數。第一個引數為destination,它的值為一個路徑字串,代表的含義是當multer處理完成前端傳遞過來的檔案之後要把這個檔案儲存在哪裡。這個資料夾無需手動建立,在接受檔案的時候會自動建立。這裡建議使用path模組進行拼接,不容易出錯。第二個引數為一個回撥函數,這裡形參要用三個進行佔位。multer中介軟體在解析前端提交的檔案的時候會呼叫這個方法,呼叫的時候會給這個filename指向的函數傳遞三個引數,第二個值為前端傳遞過來檔案資訊,第三個引數cb為一個函數,cb函數呼叫的第二個引數指定的就是當前解析完成後的儲存到destination指向的目錄的檔名。

  • 應用這個設定到multer範例裡面
const upload = multer({storage});
  • 在需要接收檔案的路由裡面應用upload.single(‘file’)中介軟體
(1).這個file是前端提交表單過來的時候表單的欄位名稱。(2).upload是用multer這個庫裡的頂級建構函式生成的範例。
  • 總體思路梳理:

實際網頁開發當中,我們前端需要向後端提交一些像mp4,mp3,圖片系列的東西,需要在後端進行接收。那麼這裡就可以使用Multer中介軟體來接收檔案,對前端傳遞過來的檔案做一些處理。

  1. multer是啥? Multer是Express官方推出的,用於node.js 處理前端以multipart/form-data請求資料處理的一箇中介軟體。注意: Multer 不會處理任何非 multipart/form-data 型別的表單資料

  2. 原理: Multer範例的single(‘###’) 是一個方法,這個方法被當作中介軟體放在某一個路由上時。就會給express 的 request 物件中新增一個 body 物件 以及 file 或 files 物件 。 body 物件包含表單的文字域資訊,file 或 files 物件包含物件表單上傳的檔案資訊。下圖就是req.file的模樣。當前端請求後臺介面。匹配當前路由的時候,先經過這個multer中介軟體,這個中介軟體就會解析前端傳過來的檔案,會把檔案儲存在上面第三步組態檔解析完成後的資料夾內,名字也會重新命名成上面第三步組態檔解析完成的檔名。同時,會在req的身上掛載一個file物件。這個file物件就是當前上傳檔案的資訊。我們可以通過req.file.filename拿到這個重新命名後的檔名,然後把這個檔名儲存到資料庫裡面。前端如果想存取之前上傳的圖片,後臺只需要把資料庫裡的檔名取到,隨後對映成我們請求的路徑,去請求public靜態資源下的存放這些檔案的資料夾就可以了。

  3. multer是一箇中介軟體,我建議把這個中介軟體寫成一個單獨的檔案,最後把設定好的multer範例暴露出去,在需要他的路由裡面當作中介軟體去應用它。就可以很快捷的處理前端傳送過來的檔案。而無需每個檔案都寫一遍。也更加符合我們模組化程式設計的思想。下圖是我multer檔案的設定。

五、富文字編輯器

富文字編輯器,Multi-function Text Editor, 簡稱 MTE, 是一種可內嵌於瀏覽器,所見即所得的文字編輯器。它提供類似於 Microsoft Word 的編輯功能,容易被不會編寫 HTML 的使用者並需要設定各種文字格式的使用者所喜愛。

富文字編輯器不同於文字編輯器,程式設計師可到網上下載免費的富文字編輯器內嵌於自己的網站或程式裡(當然付費的功能會更強大些),方便使用者編輯文章或資訊。

[外連圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片儲存下來直接上傳(img-9D1VzMYl-1658387147228)(C:\Users\11933\Desktop\前端全棧\課件\前後臺互動\imgs\富文字編輯器.png)]

layui 富文字編輯器(layedit):

  • 使用:

    <textarea id="demo" style="display: none;"></textarea>layui.use(['layedit'],function(){
        layedit.build("demo")})
  • layedit基礎的方法:

    方法名描述
    var index = layedit.build(id, options)用於建立編輯器的核心方法index:即該方法返回的索引引數 id: 範例元素(一般為textarea)的id值引數 options:編輯器的可設定項,下文會做進一步介紹
    layedit.set(options)設定編輯器的全域性屬性即上述build方法的options
    layedit.getContent(index)獲得編輯器的內容引數 index: 即執行layedit.build返回的值
    layedit.getText(index)獲得編輯器的純文字內容引數 index: 同上
    layedit.sync(index)用於同步編輯器內容到textarea(一般用於非同步提交)引數 index: 同上
    layedit.getSelection(index)獲取編輯器選中的文字引數 index: 同上
  • 編輯器屬性設定:

    屬性型別描述
    toolArray重新客製化編輯器工具列,如: tool: [‘link’, ‘unlink’, ‘face’]
    hideToolArray不顯示編輯器工具列,一般用於隱藏預設設定的工具bar
    heightNumber設定編輯器的初始高度
    uploadImageObject設定圖片上傳介面,如:uploadImage: {url: ‘/upload/’, type: ‘post’}
  • 富文字編輯器工具列:

     let richtextInex =  layedit.build('richtext', {
         tool: [
             'strong' //加粗
             , 'italic' //斜體
             , 'underline' //下劃線
             , 'del' //刪除線
    
             , '|' //分割線
    
             , 'left' //左對齊
             , 'center' //居中對齊
             , 'right' //右對齊
             , 'image' //插入圖片
         ],
         uploadImage:{url:'/uploadrichtext',type:'POST'}
     })

六、express-session

(一)、Session簡單介紹
session 是另一種記錄客戶狀態的機制,不同的是 Cookie 儲存在使用者端瀏覽器中,而 session 儲存在伺服器上。Session的用途:
session執行在伺服器端,當用戶端第一次存取伺服器時,可以將客戶的登入資訊儲存。
當客戶存取其他頁面時,可以判斷客戶的登入狀態,做出提示,相當於登入攔截。
session可以和Redis或者資料庫等結合做持久化操作,當伺服器掛掉時也不會導致某些客戶資訊(購物車)
丟失。

(二)、Session的工作流程
當瀏覽器存取伺服器並行送第一次請求時,伺服器端會建立一個session物件,生成一個類似於
key,value的鍵值對,然後將key(cookie)返回到瀏覽器(客戶)端,瀏覽器下次再存取時,攜帶key(cookie),
找到對應的session(value)。 客戶的資訊都儲存在session中。

(三)、Cookie和Session區別:

  • cookie 資料存放在客戶的瀏覽器上,session 資料放在伺服器上。

  • cookie 不是很安全,別人可以分析存放在原生的 COOKIE 並進行 COOKIE 欺騙 考慮到安全應當使用 session。

  • session 會在一定時間內儲存在伺服器上。當存取增多,會比較佔用你伺服器的效能 考慮到減輕伺服器效能方面,應當使用 COOKIE。

  • 單個 cookie 儲存的資料不能超過 4K,很多瀏覽器都限制一個站點最多儲存 20 個 cookie。

(四)、express-session的使用

  • 安裝 express-session:

    npm install express-session
  • 引入express-session:

    var session = require("express-session");
  • 設定官方檔案提供的中介軟體:

    app.use(session({
        secret: 'keyboard cat',
        resave: true,
        saveUninitialized: true
    }))
  • 使用:

    設定值 req.session.username = "張三";
    獲取值 req.session.username
  • express-session的常用引數:

1. name - cookie的名字(原屬性名為 key)。(預設:’connect.sid’)2. store - session儲存範例3. secret - 用它來對session cookie簽名,防止篡改4. cookie - session cookie設定 (預設:{ path: ‘/‘, httpOnly: true,secure: false, maxAge: null })5. genid - 生成新session ID的函數 (預設使用uid2庫)6. rolling - 在每次請求時強行設定cookie,這將重置cookie過期時間(預設:false)7. resave - 強制儲存session即使它並沒有變化 (預設: true)8. proxy - 當設定了secure cookies(通過」x-forwarded-proto」 header )時信任反向代理。當設定為true時,
」x-forwarded-proto」 header 將被使用。當設定為false時,所有headers將被忽略。當該屬性沒有被設定時,將使用Express的trust proxy。9. saveUninitialized - 強制將未初始化的session儲存。當新建了一個session且未設定屬性或值時,它就處於
未初始化狀態。在設定一個cookie前,這對於登陸驗證,減輕伺服器端儲存壓力,許可權控制是有幫助的。(預設:true)10. unset - 控制req.session是否取消(例如通過 delete,或者將它的值設定為null)。這可以使session保持
  • express-session的常用方法:
1. Session.destroy():刪除session,當檢測到使用者端關閉時呼叫。2. Session.reload():當session有修改時,重新整理session。3. Session.regenerate():將已有session初始化。4. Session.save():儲存session。
  • 使用案例:
//設定中介軟體app.use(session({
    secret: 'this is string key',   // 可以隨便寫。一個 String 型別的字串,作為伺服器端生成 session 的簽名
    name:'session_id',/*儲存在本地cookie的一個名字 預設connect.sid  可以不設定*/
    resave: false,   /*強制儲存 session 即使它並沒有變化,。預設為 true。建議設定成 false。*/
    saveUninitialized: true,   //強制將未初始化的 session 儲存。  預設值是true  建議設定成true
    cookie: {
        maxAge:5000    /*過期時間*/

    },   /*secure https這樣的情況才可以存取cookie*/

    //設定過期時間比如是30分鐘,只要遊覽頁面,30分鐘沒有操作的話在過期
    
    rolling:true //在每次請求時強行設定 cookie,這將重置 cookie 過期時間(預設:false)}))

七、表單事件

  • Form 物件屬性:
屬性描述
action接收請求的URL
elements表單中的所有控制元件元素集合
length表單控制元件的個數
enctype編碼型別 例:enctype=「multipart/form-data」
name表單元素名稱
  • Form 物件方法:
方法描述
reset()把表單的所有輸入元素重置為它們的預設值。
submit()提交表單。
  • Form 物件事件:
事件描述
onreset在重置表單元素之前呼叫。
onsubmit在提交表單之前呼叫。
  • 表單控制元件的屬性:
屬性描述
value獲取和設定值
disabled獲取或設定表單控制元件是否禁用值為true或 false
type讀取表單控制元件的型別
form所在表單元素物件
readOnly控制元件唯讀屬性 Boolean 不能更改只能複製和讀取
name獲取與設定name欄位名
  • 表單控制元件的事件:
事件描述
onblur當失去焦點的時候
onfocus當獲取焦點的時候
onchange當內容改變並失去焦點的時候
oninput在使用者輸入時觸發
  • 表單控制元件的方法:
方法描述
focus()獲得焦點
blur()失去焦點
select()選擇文字控制元件中的所有文字內容

以上就是總結Node.js模組開發及常用技巧分享的詳細內容,更多請關注TW511.COM其它相關文章!