您好,登錄后才能下訂單哦!
今天小編給大家分享一下Node.js模塊開發及常用技巧實例分析的相關知識點,內容詳細,邏輯清晰,相信大部分人都還太了解這方面的知識,所以分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后有所收獲,下面我們一起來了解一下吧。
模塊化做為一種現代化的設計方法,這個概念最早起源于生產制造行業。如今這個概念已經被各行各業來衍生應用,在軟件開發中也大量的采用了模塊化思想。
所謂的模塊化思想,將一個大程序按照功能劃分為若干個小的模塊,每個小程序模塊完成一個特定的功能,所有的模塊按某種方法組裝起來,成為一個整體,完成整個系統所要求功能的程序設計方法。
模塊化可以使你的代碼低耦合,功能模塊直接不相互影響。
為什么需要模塊化:
程序復雜度上升代碼越寫越多,在一個文件里代碼就會越來越長,不易維護。(把完成特定功能的代碼分組,分別放到不同的文件里,這樣,每個文件包含的代碼就相對較少)
JavaScript 有復雜的依賴關系的時候就很容易出現一些變量的屬性或方法被覆蓋或改寫,導致變量污染。這是因為js沒有命名空間,不像其他語言通過命名空間可以有效的避免重名問題。
想要存在JavaScript 私有的變量
模塊化思想解決問題:
可維護性:每個模塊都是單獨定義的,之間相互獨立。模塊盡可能的需要和外部撇清關系,方便我們獨立的對其進行維護與改造。維護一個模塊比在全局中修改邏輯判斷要好的多。
命名沖突:為了避免在JavaScript中的全局污染,我們通過模塊化的方式利用函數作用域來構建命名空間,避免命名沖突。
文件依賴:一個功能可能依賴一個或多個其他文件,使用是除了引入它本身還需要考慮依賴文件,通過模塊化 我們只需要引入文件,無需考慮文件依賴(模塊化可以幫助我們解決文件依賴問題)。
可復用性:雖然粘貼復制很簡單,但是要考慮到我們之后的維護以及迭代。
為了讓Nodejs的文件可以相互調用,Nodejs基于CommonJS規范提供了一個簡單的模塊系統。(nodejs實現并遵守CommonJS規范的)。
把具有公共功能的,抽離成一個單獨的js文件作位一個模塊。默認情況下,模塊里的方法或屬性,外面是訪問不到的。如果想要在外面訪問這些屬性,方法,就必須在模塊里通過exports
和module.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() 方法用于加載模塊。
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");
和函數作用域類似,在自定義模塊中定義的變量、方法等成員,只能在當前模塊內被訪問,這種模塊級別的訪問限制,叫做模塊作用域。
模塊作用域的好處:防止了全局變量污染的問題
Node.js 中的第三方模塊又叫做包。包是由第三方個人或團隊開發出來的,免費供所有人使用。
Node.js 的內置模塊僅提供了一些底層的 API,導致在基于內置模塊進行項目開發的時,效率很低。
包是基于內置模塊封裝出來的,提供了更高級、更方便的 API,極大的提高了開發效率。
國外有一家 IT 公司,叫做 npm, Inc. 這家公司旗下有一個非常著名的網站: https://www.npmjs.com/ ,它是全球最大的包共享平臺。
我們可以使用這個包管理工具, npm ,來對包進行管理,這個包管理工具隨著 Node.js 的安裝包一起被安裝到了用戶的電腦上。檢測其版本。npm -v
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 是一個管理 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
淘寶 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是一個基于 Node.js 平臺,快速、開放、極簡的 Web 開發框架。
$ npm install express --save
案例:第一個express案例。
所謂的路由就是客戶端用來與后端服務器進行交互的一種方式,客戶端采用特定的URL與請求方法來訪問服務器端,服務器端通過響應返回特定資源。
路由的定義由如下結構組成:
app.METHOD(PATH, HANDLER)
名稱 | 描述 |
---|---|
app | app 是一個 express 實例 |
METHOD | METHOD用于指定要匹配的HTTP請求方式 |
PATH | PATH是服務器端的路徑 |
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!')})
在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())})
路由器級中間件的工作方式與應用級中間件相同,只是它綁定到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
與其他中間件函數相同的方式定義錯誤處理中間件函數,但是使用四個參數
(err, req, res, next)
,放到最后。
app.use(function (err, req, res, next) { console.error(err.stack) res.status(404).send('Something broke!')})
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}));
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
中間件函數會根據目錄的添加順序查找所需的文件。
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
后端嵌套模板,后端渲染模板 (后端把頁面組裝起來)
做好靜態頁面,動態效果
把前端代碼提供給后端,后端要把靜態html以及里面的假數據給刪掉,通過模板進行動態生成html的內容
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-jL70ca3p-1658387147221)(C:\Users\11933\Desktop\前端全棧\課件\前后臺交互\imgs\服務器端渲染.png)]
BSR
(前后端分離,通過通用的json數據形式,不挑后端的語言)
做好靜態頁面,動態效果
json模擬,ajax動態創建頁面
真實接口數據,前后聯調
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-pXRCidw2-1658387147223)(C:\Users\11933\Desktop\前端全棧\課件\前后臺交互\imgs\前后端分離.png)]
模板引擎能夠在應用程序中使用靜態模板文件。在運行時,模板引擎將模板文件中的變量替換為實際值,并將模板轉換為發送給客戶端的 HTML 文件。這種方法使設計 HTML 頁面變得更加容易。
與 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!' }) })
npm install ejs
在app.js中添加如下代碼,配置Express使用ejs模板引擎。
app.set('views',path.join(__dirname,'views')); //設置模板存儲位置app.set('view engine','ejs');
注意:此時指定的模板目錄為
views
,且模板文件的后綴名為.ejs
。
在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
。
<%= %> 輸出標簽 <%- %> 輸出html標簽(html會被瀏覽器解析) <%# %> 注釋標簽 <% %> 流程控制標簽(寫的是if,else,for) <%- include("user/show",{user:user})%> 導入公共的模板內容
是一種設計模式,是軟件架構得模式,是在web開發過程中總結的一些套路或者是模塊化的內容。M是指業務模型(module),V是指用戶界面(view),C則是控制器(controller)。使用mvc最大的優勢就是分層,目的是將M和V的實現代碼分離,存在的目的則是確保M和V的同步,一旦M改變,V應該同步更新。MVC是相互獨立的,M,C(后端); V(前端)。路由規劃為Controller。
JSON(
J
avaS
criptO
bjectN
otation, JS對象表示法)簡單來講,JSON 就是 Javascript 對象和數組的字符串表示法,因此,JSON 的本質是字符串。
作用:JSON 是一種輕量級的文本數據交換格式,在作用上類似于 XML,專門用于存儲和傳輸數據,但是 JSON 比 XML 更小、更快、更易解析。
現狀:JSON 是在 2001 年開始被推廣和使用的數據格式,到現今為止,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 的最外層必須是對象或數組格式
不能使用 undefined 或函數作為 JSON 的值
JSON 的作用:在計算機與網絡之間存儲和傳輸數據
JSON 的本質:用字符串來表示 Javascript 對象數據或數組數據
JSON 是 JS 對象的字符串表示法,它使用文本表示一個 JS 對象的信息,本質是一個字符串。
//這是一個對象var obj = {a: 'Hello', b: 'World'}//這是一個 JSON 字符串,本質是一個字符串var json = '{"a": "Hello", "b": "World"}'
要實現從 JSON 字符串轉換為 JS 對象,使用 JSON.parse() 方法
要實現從 JS 對象轉換為 JSON 字符串,使用 JSON.stringify() 方法
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 協議中的一部分,請求方法的作用是:用來表明要對服務器上的資源執行的操作。最常用的請求方法是 GET 和 POST。
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-vwQMQrAp-1658387147226)(C:\Users\11933\Desktop\前端全棧\課件\前后臺交互\imgs\http請求的方法.png)]
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-28YRkP8m-1658387147227)(C:\Users\11933\Desktop\前端全棧\課件\前后臺交互\imgs\http響應狀態碼.png)]
AJAX 全稱為(Asynchronous JavaScript And XML),是異步的JavaScript和XML。通過 ajax可以在瀏覽器向服務器發送異步請求。最大的優勢,
無刷新獲取數據
。也就是說AJAX可以在不重新加載整個頁面的情況下,與服務器交換數據。這種異步交互的方式,使用戶單擊后,不必刷新頁面也能獲取新數據。使用Ajax,用戶可以創建接近本地桌面應用的直接、高可用、更豐富、更動態的Web用戶界面。
XML 指可擴展標記語?,HTML 超文本標記語言
XML被設計用來傳輸和存儲數據
XML和HTML類似,不同的是HTML都是預定義的標簽,而XML沒有預定義標簽,全部都是自定義的標簽,用來表示一些數據。
最開始是前后臺進行數據交互的語言,現在是JSON。
'{"title":"三體","author":"zs","price":30}'<book> <title>三體</title> <author>劉慈欣</author> <price>30.00</price></book>
可以無需刷新頁面與服務器進行通信
允許你根據用戶事件來更新部分頁面內容
沒有瀏覽歷史不能回退
存在跨越問題 同源策略:協議,域名,端口號
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)})
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
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中間件來接收文件,對前端傳遞過來的文件做一些處理。
multer是啥? Multer是Express官方推出的,用于node.js 處理前端以multipart/form-data請求數據處理的一個中間件。注意: Multer 不會處理任何非 multipart/form-data 類型的表單數據
原理: Multer實例的single(‘###’) 是一個方法,這個方法被當作中間件放在某一個路由上時。就會給express 的 request 對象中添加一個 body 對象 以及 file 或 files 對象 。 body 對象包含表單的文本域信息,file 或 files 對象包含對象表單上傳的文件信息。下圖就是req.file的模樣。當前端請求后臺接口。匹配當前路由的時候,先經過這個multer中間件,這個中間件就會解析前端傳過來的文件,會把文件保存在上面第三步配置文件解析完成后的文件夾內,名字也會重命名成上面第三步配置文件解析完成的文件名。同時,會在req的身上掛載一個file對象。這個file對象就是當前上傳文件的信息。我們可以通過req.file.filename拿到這個重命名后的文件名,然后把這個文件名保存到數據庫里面。前端如果想訪問之前上傳的圖片,后臺只需要把數據庫里的文件名取到,隨后映射成我們請求的路徑,去請求public靜態資源下的存放這些文件的文件夾就可以了。
multer是一個中間件,我建議把這個中間件寫成一個單獨的文件,最后把配置好的multer實例暴露出去,在需要他的路由里面當作中間件去應用它。就可以很快捷的處理前端發送過來的文件。而無需每個文件都寫一遍。也更加符合我們模塊化編程的思想。下圖是我multer文件的配置。
富文本編輯器,Multi-function Text Editor, 簡稱 MTE, 是一種可內嵌于瀏覽器,所見即所得的文本編輯器。它提供類似于 Microsoft Word 的編輯功能,容易被不會編寫 HTML 的用戶并需要設置各種文本格式的用戶所喜愛。
富文本編輯器不同于文本編輯器,程序員可到網上下載免費的富文本編輯器內嵌于自己的網站或程序里(當然付費的功能會更強大些),方便用戶編輯文章或信息。
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-9D1VzMYl-1658387147228)(C:\Users\11933\Desktop\前端全棧\課件\前后臺交互\imgs\富文本編輯器.png)]
使用:
<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: 同上 |
編輯器屬性設置:
屬性 | 類型 | 描述 |
---|---|---|
tool | Array | 重新定制編輯器工具欄,如: tool: [‘link’, ‘unlink’, ‘face’] |
hideTool | Array | 不顯示編輯器工具欄,一般用于隱藏默認配置的工具bar |
height | Number | 設定編輯器的初始高度 |
uploadImage | Object | 設定圖片上傳接口,如:uploadImage: {url: ‘/upload/’, type: ‘post’} |
富文本編輯器工具欄:
let richtextInex = layedit.build('richtext', { tool: [ 'strong' //加粗 , 'italic' //斜體 , 'underline' //下劃線 , 'del' //刪除線 , '|' //分割線 , 'left' //左對齊 , 'center' //居中對齊 , 'right' //右對齊 , 'image' //插入圖片 ], uploadImage:{url:'/uploadrichtext',type:'POST'} })
(一)、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模塊開發及常用技巧實例分析”這篇文章的所有內容,感謝各位的閱讀!相信大家閱讀完這篇文章都有很大的收獲,小編每天都會為大家更新不同的知識,如果還想學習更多的知識,請關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。