一、模塊化
模塊化 做為一種現(xiàn)代化的設(shè)計方法,這個概念最早起源于生產(chǎn)制造行業(yè)。如今這個概念已經(jīng)被各行各業(yè)來衍生應(yīng)用,在軟件開發(fā)中也大量的采用了模塊化思想。
所謂的模塊化思想 ,將一個大程序按照功能劃分為若干個小的模塊,每個小程序模塊完成一個特定的功能,所有的模塊按某種方法組裝起來,成為一個整體,完成整個系統(tǒng)所要求功能的程序設(shè)計方法?!就扑]:node.js視頻教程】
(一)、為什么需要模塊化
模塊化可以使你的代碼低耦合,功能模塊直接不相互影響。
為什么需要模塊化:
模塊化思想解決問題:
可維護(hù)性:每個模塊都是單獨定義的,之間相互獨立。模塊盡可能的需要和外部撇清關(guān)系,方便我們獨立的對其進(jìn)行維護(hù)與改造。維護(hù)一個模塊比在全局中修改邏輯判斷要好的多。
命名沖突:為了避免在JavaScript中的全局污染,我們通過模塊化的方式利用函數(shù)作用域來構(gòu)建命名空間,避免命名沖突。
文件依賴:一個功能可能依賴一個或多個其他文件,使用是除了引入它本身還需要考慮依賴文件,通過模塊化 我們只需要引入文件,無需考慮文件依賴(模塊化可以幫助我們解決文件依賴問題)。
可復(fù)用性:雖然粘貼復(fù)制很簡單,但是要考慮到我們之后的維護(hù)以及迭代。
(二)、什么是Nodejs模塊
為了讓Nodejs的文件可以相互調(diào)用,Nodejs基于CommonJS規(guī)范提供了一個簡單的模塊系統(tǒng)。(nodejs實現(xiàn)并遵守CommonJS規(guī)范的)。
把具有公共功能的,抽離成一個單獨的js文件作位一個模塊。默認(rèn)情況下,模塊里的方法或?qū)傩?,外面是訪問不到的。如果想要在外面訪問這些屬性,方法,就必須在模塊里通過exports
和module.exports
暴露,在需要使用的地方通過require()
進(jìn)行引入。
//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 規(guī)定:
每個模塊內(nèi)部,module 變量代表當(dāng)前模塊
module 變量是一個對象,它的 exports 屬性(即 module.exports)是對外的接口
加載某個模塊,其實是加載該模塊的 module.exports 屬性。require() 方法用于加載模塊。
(三)、nodejs中的模塊分類與加載方式
Node.js 中根據(jù)模塊來源的不同,將模塊分為了 3 大類,分別是:
內(nèi)置模塊(內(nèi)置模塊是由 Node.js 官方提供的,例如 fs、path、http 等)
自定義模塊(用戶創(chuàng)建的每個 .js 文件,都是自定義模塊)
第三方模塊(包)(由第三方開發(fā)出來的模塊,并非官方提供的內(nèi)置模塊,也不是用戶創(chuàng)建的自定義模塊,使用前需要先下載)
//1.加載內(nèi)置模塊不需要指定路徑 var http = require('http'); //2.加載用戶的自定義模塊 var sum = require('./sum.js'); //3.加載第三方模塊 const md5=require("md5");
(四)、模塊作用域
和函數(shù)作用域類似,在自定義模塊中定義的變量、方法等成員,只能在當(dāng)前模塊內(nèi)被訪問,這種模塊級別的訪問限制,叫做模塊作用域。
模塊作用域的好處:防止了全局變量污染的問題
二、npm與包
(一)、包的介紹
Node.js 中的第三方模塊又叫做包。包是由第三方個人或團隊開發(fā)出來的,免費供所有人使用。
Node.js 的內(nèi)置模塊僅提供了一些底層的 API,導(dǎo)致在基于內(nèi)置模塊進(jìn)行項目開發(fā)的時,效率很低。 包是基于內(nèi)置模塊封裝出來的,提供了更高級、更方便的 API,極大的提高了開發(fā)效率。
國外有一家 IT 公司,叫做 npm, Inc. 這家公司旗下有一個非常著名的網(wǎng)站: https://www.npmjs.com/ ,它是全球最大的包共享平臺。
我們可以使用這個包管理工具, npm ,來對包進(jìn)行管理,這個包管理工具隨著 Node.js 的安裝包一起被安裝到了用戶的電腦上。檢測其版本。npm -v
(二)、npm的使用
npm init
進(jìn)行初始化,生成package.json
文件,記錄項目的信息,記錄包的信息
npm install 包名
npm i 包名
下載包,放到node_modules
文件夾里
npm i 包名 --save
npm i 包名 -S
(開發(fā)環(huán)境中)
npm i 包名 --save-dev
npm i 包名 -D
(生產(chǎn)環(huán)境中)
npm list
列舉當(dāng)前目錄下安裝的包
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 內(nèi)置的幾個 npm 源的地址:
$ nrm ls
結(jié)果如下:
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
查看當(dāng)前的鏡像源:
npm config get register
(四)、淘寶cnpm工具
淘寶 NPM 鏡像是一個完整 npmjs.org 鏡像,你可以用此代替官方版本(只讀),同步頻率目前為 10分鐘 一次以保證盡量與官方服務(wù)同步。
你可以使用淘寶定制的 cnpm (gzip 壓縮支持) 命令行工具代替默認(rèn)的 npm:
npm install -g cnpm -registry=https://registry.npm.taobao.org
安裝包
cnpm install [模塊名]
三、路由
路由:根據(jù)不同的路徑返回不同的頁面。
案例:server.js;static;route.js;route對象;render();api.js;封裝server.js到index.js;合并對象
獲取請求參數(shù):login頁面發(fā)get,post請求,到/api/login
靜態(tài)資源托管:
express
Express是一個基于 Node.js 平臺,快速、開放、極簡的 Web 開發(fā)框架。
一、下載與安裝
$ npm install express --save
案例:第一個express案例。
二、路由
所謂的路由 就是客戶端用來與后端服務(wù)器進(jìn)行交互的一種方式,客戶端采用特定的URL與請求方法來訪問服務(wù)器端,服務(wù)器端通過響應(yīng)返回特定資源。
路由的定義由如下結(jié)構(gòu)組成:
app.METHOD(PATH, HANDLER)
名稱
描述
app
app 是一個 express 實例
METHOD
METHOD用于指定要匹配的HTTP請求方式
PATH
PATH是服務(wù)器端的路徑
HANDLER
是當(dāng)路由匹配時需要執(zhí)行的處理程序(回調(diào)函數(shù))
路由路徑和請求方法一起定義了請求的端點,它可以是字符串,字符串模式以及正則表達(dá)式。
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可以一次或者多次的重復(fù)})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')})
可以為請求處理提供多個回調(diào)函數(shù),其行為類似中間件。
案例:中間件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.應(yīng)用級中間件
在Express程序中,使用 app.use()
和 app.METHOD()
方法將中間件綁定到應(yīng)用程序?qū)ο?app)。
凡是掛載在app身上的都是應(yīng)用級中間件。
app.use() : 應(yīng)用中的每個請求都可以執(zhí)行其代碼
//萬能中間件var express = require('express')var app = express()app.use(function (req, res, next) { console.log('Time:', Date.now()) next()})
//特定路由的應(yīng)用中間件app.use("/login",function (req, res, next) { console.log('Time:', Date.now())})
2.路由級中間件
路由器級中間件的工作方式與應(yīng)用級中間件相同,只是它綁定到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.錯誤處理中間件
與其他中間件函數(shù)相同的方式定義錯誤處理中間件函數(shù),但是使用四個參數(shù)(err, req, res, next)
,放到最后。
app.use(function (err, req, res, next) { console.error(err.stack) res.status(404).send('Something broke!')})
4.內(nèi)置中間件
express.static提供靜態(tài)資源,例如 HTML 文件、圖像等。
express.json使用 JSON 有效負(fù)載解析傳入請求。注意:可用于 Express 4.16.0+
application/json
由于JSON規(guī)范的流行,現(xiàn)在越來越多的開發(fā)者將application/json這個Content-Type作為響應(yīng)頭。用來告訴服務(wù)端消息主體是序列化后的JSON字符串。除了低版本IE之外各大瀏覽器都原生支持 JSON.stringify,服務(wù)端語言也都有處理JSON的函數(shù),JSON能格式支持比鍵值對復(fù)雜得多的結(jié)構(gòu)化數(shù)據(jù),普通鍵值對中的值只能是字符串,而使用json,鍵值對可以重復(fù)嵌套。
// 應(yīng)用級別中間件,獲取post--json參數(shù)app.use(express.json());
express.urlencoded解析帶有 URL 編碼負(fù)載的傳入請求。 注意:可用于 Express 4.16.0+
application/x-www-form-urlencoded 瀏覽器的原生form表單,如果不設(shè)置enctype屬性,那么最終就會以 application/x-www-form-urlencoded方式提交數(shù)據(jù)。Content-Type被指定為application/x-www-form-urlencoded提交的數(shù)據(jù)按照key=val&key=val的方式進(jìn)行編碼,并且key和val都進(jìn)行了URL轉(zhuǎn)碼。
// 應(yīng)用級別中間件,獲取post--form參數(shù)app.use(express.urlencoded({extended:false}));
5.第三方中間件
四、獲取請求參數(shù)
req.query 是一個可獲取客戶端get請求 查詢字符串 轉(zhuǎn)成的對象,默認(rèn)為{}。
req.body 包含在請求體中提交的數(shù)據(jù)鍵值對。默認(rèn)情況下undefined,當(dāng)使用解析中間件express.json()
、express.urlencoded()
五、靜態(tài)資源托管
為了提供諸如圖像、CSS 文件和 JavaScript 文件之類的靜態(tài)文件,請使用 Express 中的 express.static 內(nèi)置中間件函數(shù)。
語法:
express.static
內(nèi)置中間件函數(shù)語法:
express.static(root, [options])
root參數(shù)指定提供靜態(tài)資源的根目錄。
靜態(tài)資源示例:
例如,通過如下代碼就可以將 public 目錄下的圖片、CSS 文件、JavaScript 文件對外開放訪問了:
app.use(express.static('public'))
現(xiàn)在,你就可以訪問 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 在靜態(tài)目錄查找文件,因此,存放靜態(tài)文件的目錄名不會出現(xiàn)在 URL 中。
多個靜態(tài)資源目錄:
如果要使用多個靜態(tài)資源目錄,請多次調(diào)用 express.static
中間件函數(shù):
app.use(express.static('public')) app.use(express.static('uploads'))
訪問靜態(tài)資源文件時,express.static
中間件函數(shù)會根據(jù)目錄的添加順序查找所需的文件。
虛擬路徑:(非得添加static,沒有意義)
express.static
中間件函數(shù)可以為某些靜態(tài)資源服務(wù)創(chuàng)建虛擬路徑前綴(該路徑實際上并不存在于文件系統(tǒng)中),請指定靜態(tài)目錄的掛載路徑,如下所示:
app.use('/static', express.static('public'))
現(xiàn)在,你就可以通過帶有 /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
六、模板引擎
一、.服務(wù)端渲染 SSR
后端嵌套模板,后端渲染模板 (后端把頁面組裝起來)
做好靜態(tài)頁面,動態(tài)效果
把前端代碼提供給后端,后端要把靜態(tài)html以及里面的假數(shù)據(jù)給刪掉,通過模板進(jìn)行動態(tài)生成html的內(nèi)容
[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-jL70ca3p-1658387147221)(C:Users11933Desktop前端全棧課件前后臺交互imgs服務(wù)器端渲染.png)]
二、前后端分離,BSR
(前后端分離,通過通用的json數(shù)據(jù)形式,不挑后端的語言)
做好靜態(tài)頁面,動態(tài)效果
json模擬,ajax動態(tài)創(chuàng)建頁面
真實接口數(shù)據(jù),前后聯(lián)調(diào)
[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-pXRCidw2-1658387147223)(C:Users11933Desktop前端全棧課件前后臺交互imgs前后端分離.png)]
三、模板引擎
模板引擎 能夠在應(yīng)用程序中使用靜態(tài)模板文件。在運行時,模板引擎將模板文件中的變量替換為實際值,并將模板轉(zhuǎn)換為發(fā)送給客戶端的 HTML 文件。這種方法使設(shè)計 HTML 頁面變得更加容易。
Express模板引擎
與 Express 一起使用的一些流行模板引擎是Pug、 Mustache和EJS。Express 應(yīng)用程序生成器默認(rèn)使用Pug,但它也支持其他幾個。
需要在應(yīng)用中進(jìn)行如下設(shè)置才能讓Express渲染模板引擎:
views,放模板文件的目錄。例如:app.set('views', './views')
。
view engine,要使用的模板引擎。例如,要使用 Pug 模板引擎:app.set('view engine', 'pug')
.
在路由中渲染模板
在路由渲染模板并將渲染后的 HTML 字符串發(fā)送到客戶端。
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')); //設(shè)置模板存儲位置app.set('view engine','ejs');
注意:此時指定的模板目錄為views
,且模板文件的后綴名為.ejs
。
設(shè)置模板后綴為html
在app.js中添加如下代碼,配置Express使用ejs模板引擎。并指定模板后綴名為html。
app.set('views',path.join(__dirname,'views')); //設(shè)置模板存儲位置app.set('view engine','html');app.engine('html',require('ejs').renderFile); //使用ejs模板引擎解析html
注意:此時指定的模板目錄為views
,且模板文件的后綴名為.html
。
ejs模板語法
<%= %> 輸出標(biāo)簽 <%- %> 輸出html標(biāo)簽(html會被瀏覽器解析) <%# %> 注釋標(biāo)簽 <% %> 流程控制標(biāo)簽(寫的是if,else,for) <%- include("user/show",{user:user})%> 導(dǎo)入公共的模板內(nèi)容
MVC框架:
是一種設(shè)計模式,是軟件架構(gòu)得模式,是在web開發(fā)過程中總結(jié)的一些套路或者是模塊化的內(nèi)容。M是指業(yè)務(wù)模型(module),V是指用戶界面(view),C則是控制器(controller)。使用mvc最大的優(yōu)勢就是分層,目的是將M和V的實現(xiàn)代碼分離,存在的目的則是確保M和V的同步,一旦M改變,V應(yīng)該同步更新。MVC是相互獨立的,M,C(后端); V(前端)。路由規(guī)劃為Controller。
JSON:
一、概念:
JSON(J
avaS
cript O
bject N
otation, JS對象表示法)簡單來講,JSON 就是 Javascript 對象和數(shù)組的字符串表示法,因此,JSON 的本質(zhì)是字符串。
作用:JSON 是一種輕量級的文本數(shù)據(jù)交換格式,在作用上類似于 XML,專門用于存儲和傳輸數(shù)據(jù),但是 JSON 比 XML 更小、更快、更易解析。
現(xiàn)狀:JSON 是在 2001 年開始被推廣和使用的數(shù)據(jù)格式,到現(xiàn)今為止,JSON 已經(jīng)成為了主流的數(shù)據(jù)交換格式。
二、JSON的兩種結(jié)構(gòu)
JSON 就是用字符串來表示 Javascript 的對象和數(shù)組。所以,JSON 中包含對象和數(shù)組兩種結(jié)構(gòu),通過這兩種結(jié)構(gòu)的相互嵌套,可以表示各種復(fù)雜的數(shù)據(jù)結(jié)構(gòu)。
對象結(jié)構(gòu):對象結(jié)構(gòu)在 JSON 中表示為 { } 括起來的內(nèi)容。數(shù)據(jù)結(jié)構(gòu)為 { key: value, key: value, … } 的鍵值對結(jié)構(gòu)。其中,key 必須是使用英文的雙引號包裹的字符串,value 的數(shù)據(jù)類型可以是數(shù)字、字符串、布爾值、null、數(shù)組、對象6種類型。
{ "name": "zs", "age": 20, "gender": "男", "hobby": ["吃飯", "睡覺"]}
數(shù)組結(jié)構(gòu):數(shù)組結(jié)構(gòu)在 JSON 中表示為 [ ] 括起來的內(nèi)容。數(shù)據(jù)結(jié)構(gòu)為 [ “java”, “javascript”, 30, true … ] 。數(shù)組中數(shù)據(jù)的類型可以是數(shù)字、字符串、布爾值、null、數(shù)組、對象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 的最外層必須是對象或數(shù)組格式
不能使用 undefined 或函數(shù)作為 JSON 的值
JSON 的作用:在計算機與網(wǎng)絡(luò)之間存儲和傳輸數(shù)據(jù)
JSON 的本質(zhì):用字符串來表示 Javascript 對象數(shù)據(jù)或數(shù)組數(shù)據(jù)
四、JSON和JS對象的關(guān)系
JSON 是 JS 對象的字符串表示法,它使用文本表示一個 JS 對象的信息,本質(zhì)是一個字符串。
//這是一個對象var obj = {a: 'Hello', b: 'World'}//這是一個 JSON 字符串,本質(zhì)是一個字符串var json = '{"a": "Hello", "b": "World"}'
五、JSON和JS對象的互轉(zhuǎn)
要實現(xiàn)從 JSON 字符串轉(zhuǎn)換為 JS 對象,使用 JSON.parse() 方法
要實現(xiàn)從 JS 對象轉(zhuǎn)換為 JSON 字符串,使用 JSON.stringify() 方法
HTTP
一、概念
HTTP 協(xié)議即超文本傳送協(xié)議 (HyperText Transfer Protocol) ,它規(guī)定了客戶端與服務(wù)器之間進(jìn)行網(wǎng)頁內(nèi)容傳輸時,所必須遵守的傳輸格式。(是一種約定與規(guī)則)
二、請求(請求報文)
客戶端發(fā)起的請求叫做 HTTP 請求,客戶端發(fā)送到服務(wù)器的消息,叫做 HTTP 請求消息,又叫做 HTTP 請求報文。
請求消息的組成
HTTP 請求消息由請求行(request line)、請求頭部( header ) 、空行 和 請求體 4 個部分組成。
[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-G502I2rT-1658387147224)(C:Users11933Desktop前端全棧課件前后臺交互imgs請求消息組成部分.png)]
請求行:由請求方式(get,post)、URL (/login?)和 HTTP 協(xié)議版本 3 個部分組成,他們之間使用空格隔開。
請求頭部:用來描述客戶端的基本信息,從而把客戶端相關(guān)的信息告知服務(wù)器。請求頭部由多行 鍵/值對 組成,每行的鍵和值之間用英文的冒號分隔。
[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-ImfA8U4y-1658387147225)(C:Users11933Desktop前端全棧課件前后臺交互imgs請求頭部字段.png)]
空行:最后一個請求頭字段的后面是一個空行,通知服務(wù)器請求頭部至此結(jié)束。請求消息中的空行,用來分隔請求頭部與請求體。
請求體:請求體中存放的,是要通過 POST 方式提交到服務(wù)器的數(shù)據(jù)。只有 POST 請求才有請求體,GET 請求沒有請求體!
三、響應(yīng)(響應(yīng)報文)
響應(yīng)消息就是服務(wù)器響應(yīng)給客戶端的消息內(nèi)容,也叫作響應(yīng)報文。
響應(yīng)消息的組成:
HTTP響應(yīng)消息由狀態(tài)行、響應(yīng)頭部、空行 和 響應(yīng)體 4 個部分組成。
[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-N0rfsHa8-1658387147225)(C:Users11933Desktop前端全棧課件前后臺交互imgs響應(yīng)消息組成部分.png)]
狀態(tài)行:由 HTTP 協(xié)議版本、狀態(tài)碼和狀態(tài)碼的描述文本 3 個部分組成,他們之間使用空格隔開;
響應(yīng)頭部:用來描述服務(wù)器的基本信息。響應(yīng)頭部由多行 鍵/值對 組成,每行的鍵和值之間用英文的冒號分隔。
空行:在最后一個響應(yīng)頭部字段結(jié)束之后,會緊跟一個空行,用來通知客戶端響應(yīng)頭部至此結(jié)束。響應(yīng)消息中的空行,用來分隔響應(yīng)頭部與響應(yīng)體。
響應(yīng)體:中存放的,是服務(wù)器響應(yīng)給客戶端的資源內(nèi)容。
四、HTTP請求方法
HTTP 請求方法,屬于 HTTP 協(xié)議中的一部分,請求方法的作用是:用來表明要對服務(wù)器上的資源執(zhí)行的操作。最常用的請求方法是 GET 和 POST。
[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-vwQMQrAp-1658387147226)(C:Users11933Desktop前端全棧課件前后臺交互imgshttp請求的方法.png)]
五、響應(yīng)的狀態(tài)碼
[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-28YRkP8m-1658387147227)(C:Users11933Desktop前端全棧課件前后臺交互imgshttp響應(yīng)狀態(tài)碼.png)]
Ajax:
一、概念
AJAX 全稱為(Asynchronous JavaScript And XML),是異步的JavaScript和XML。通過 ajax可以在瀏覽器向服務(wù)器發(fā)送異步請求。最大的優(yōu)勢,無刷新獲取數(shù)據(jù)
。也就是說AJAX可以在不重新加載整個頁面的情況下,與服務(wù)器交換數(shù)據(jù)。這種異步交互的方式,使用戶單擊后,不必刷新頁面也能獲取新數(shù)據(jù)。使用Ajax,用戶可以創(chuàng)建接近本地桌面應(yīng)用的直接、高可用、更豐富、更動態(tài)的Web用戶界面。
二、XML
XML 指可擴展標(biāo)記語?,HTML 超文本標(biāo)記語言
XML被設(shè)計用來傳輸和存儲數(shù)據(jù)
XML和HTML類似,不同的是HTML都是預(yù)定義的標(biāo)簽,而XML沒有預(yù)定義標(biāo)簽,全部都是自定義的標(biāo)簽,用來表示一些數(shù)據(jù)。
最開始是前后臺進(jìn)行數(shù)據(jù)交互的語言,現(xiàn)在是JSON。
'{"title":"三體","author":"zs","price":30}'<book> <title>三體</title> <author>劉慈欣</author> <price>30.00</price></book>
三、特點
優(yōu)點:
可以無需刷新頁面與服務(wù)器進(jìn)行通信
允許你根據(jù)用戶事件來更新部分頁面內(nèi)容
缺點:
沒有瀏覽歷史不能回退
存在跨越問題 同源策略:協(xié)議,域名,端口號
SEO不友好
四、發(fā)送請求
// 1.創(chuàng)建對象var xhr=new XMLHttpRequest();// 2.初始化,設(shè)置請求方法和urlxhr.open("GET","http://127.0.0.1:3000/server?username=zs&password=1234");// 3.發(fā)送xhr.send();// 4.綁定事件,處理服務(wù)端返回得結(jié)果// readstate xhr得屬性 狀態(tài) 0,1,2,3,4xhr.onreadystatechange=function(){ // 服務(wù)器返回得結(jié)果 if(xhr.readyState==4){ // 判斷響應(yīng)得狀態(tài)碼 if(xhr.status==200){ // 行,頭,體 console.log(xhr.status); console.log(xhr.statusText); console.log(xhr.response); console.log(xhr.getAllResponseHeaders()); } }}
項目:
一、對密碼進(jìn)行加密處理
JavaScript使用CryptoJS
加解密。CryptoJS
時一個JavaScript的加解密的工具包。它支持多種的算法:MD5、SHA1、SHA2、SHA3、RIPEMD-160 哈希散列,進(jìn)行 AES、DES、Rabbit、RC4、Triple DES 加解密。在項目中如果要對前后端傳輸?shù)臄?shù)據(jù)雙向加密, 比如避免使用明文傳輸用戶名,密碼等數(shù)據(jù)。 就需要對前后端數(shù)據(jù)用同種方法進(jìn)行加密,方便解密。
使用步驟:
npm i crypto-js
在 /login.js
中,導(dǎo)入 crypto-js
:
const crypto = require('crypto-js')
//加密var a=crypto.AES.encrypt("abc","key").toString(); //SecrectKey 秘鑰//解密var b=crypto.AES.decrypt(a,"key").toString(crypto.enc.Utf8); //按照UTF8編碼解析出原始字符串
二、表單校驗規(guī)則
在實際開發(fā)中,前后端都需要對表單的數(shù)據(jù)進(jìn)行合法性的驗證,而且,后端做為數(shù)據(jù)合法性驗證的最后一個關(guān)口 ,在攔截非法數(shù)據(jù)方面,起到了至關(guān)重要的作用。使用第三方數(shù)據(jù)驗證模塊 ,來降低出錯率、提高驗證的效率與可維護(hù)性。
步驟:
安裝 joi
包,為表單中攜帶的每個數(shù)據(jù)項,定義驗證規(guī)則:
npm install joi
安裝 @escook/express-joi
中間件,來實現(xiàn)自動對表單數(shù)據(jù)進(jìn)行驗證的功能:
npm i @escook/express-joi
新建 /schema/login.js
用戶信息驗證規(guī)則模塊:
const joi = require('joi')/** * string() 值必須是字符串 * alphanum() 值只能是包含 a-zA-Z0-9 的字符串 * min(length) 最小長度 * max(length) 最大長度 * required() 值是必填項,不能為 undefined * pattern(正則表達(dá)式) 值必須符合正則表達(dá)式的規(guī)則 */// 用戶名的驗證規(guī)則const username = joi.string().required();// 密碼的驗證規(guī)則const password = joi.string().pattern(/^[S]{6,12}$/).required();// 登錄表單的驗證規(guī)則對象exports.login_schema = { // 表示需要對 req.body 中的數(shù)據(jù)進(jìn)行驗證 body: { username, password, },}
修改 /router/admin/login.js
中的代碼:
// 1. 導(dǎo)入驗證表單數(shù)據(jù)的中間件const expressJoi = require('@escook/express-joi')// 2. 導(dǎo)入需要的驗證規(guī)則對象const { login_schema } = require('../../schema/login');// 3登錄功能router.post("/",expressJoi(login_schema),(req,res)=>{}];
在 index.js
的全局錯誤級別中間件中,捕獲驗證失敗的錯誤,并把驗證失敗的結(jié)果響應(yīng)給客戶端:
const joi = require('joi')// 錯誤中間件app.use(function (err, req, res, next) { // 數(shù)據(jù)驗證失敗 if (err instanceof joi.ValidationError) return res.send(err); // 未知錯誤 res.send(err)})
三、四種常見的POST提交數(shù)據(jù)方式
HTTP協(xié)議是以ASCII碼傳輸,建立在TCP/IP協(xié)議之上的應(yīng)用層規(guī)范。規(guī)范把 HTTP 請求分為三個部分:狀態(tài)行、請求頭、消息主體。協(xié)議規(guī)定 POST 提交的數(shù)據(jù)必須放在消息主體(entity-body)中,但協(xié)議并沒有規(guī)定數(shù)據(jù)必須使用什么編碼方式Content-Type。
服務(wù)端根據(jù)請求頭(headers)中的Content-Type字段來獲知請求中的消息主體是用何種方式編碼,再對主體進(jìn)行解析。所以說到POST提交數(shù)據(jù)方案,包含了Content-Type 和消息主體編碼方式兩部分。Content-Type的四種值分別代表四種方式,具體如下:
方式一:application/x-www-form-urlencoded
瀏覽器的原生form表單,如果不設(shè)置enctype屬性,那么最終就會以 application/x-www-form-urlencoded方式提交數(shù)據(jù)。Content-Type被指定為application/x-www-form-urlencoded提交的數(shù)據(jù)按照key=val&key=val的方式進(jìn)行編碼,并且key和val都進(jìn)行了URL轉(zhuǎn)碼。服務(wù)端例如 PHP 中,使用$_POST[′key′]可以獲取到值。
常見的POST數(shù)據(jù)提交的方式。這種方式支持文件上傳,不過必須要設(shè)置form的enctyped等于這個值。使用multipart/form-data方式會生成了一個boundary 來分割不同的字段,為了避免與正文重復(fù),boundary是一段很長的隨機拼接的字符串。然后Content-Type指明數(shù)據(jù)是以mutipart/form-data來編碼并包括進(jìn)本次請求的boundary 值。消息主體最后以 –boundary–標(biāo)示結(jié)束。
由于JSON規(guī)范的流行,現(xiàn)在越來越多的開發(fā)者將application/json這個Content-Type作為響應(yīng)頭。用來告訴服務(wù)端消息主體是序列化后的JSON字符串。除了低版本IE之外各大瀏覽器都原生支持 JSON.stringify,服務(wù)端語言也都有處理JSON的函數(shù),JSON能格式支持比鍵值對復(fù)雜得多的結(jié)構(gòu)化數(shù)據(jù),普通鍵值對中的值只能是字符串,而使用json,鍵值對可以重復(fù)嵌套。
它是一種使用HTTP作為傳輸協(xié)議,XML作為編碼方式的遠(yuǎn)程調(diào)用規(guī)范。不過后來使用很少。也許在十多年前,在json還未出來之前數(shù)據(jù)交互對接。
總之a(chǎn)pplication/x-www-form-urlencoded和multipart/form-data兩種POST方式都是瀏覽器原生支持的,是普遍使用的兩種方式,application/json是現(xiàn)在比較流行的新趨勢。
四、multer
npm i multer
const multer = require('multer')
配置multer接收到的文件存儲的文件夾和,存放的圖片的名字
//上傳文件存放路徑、及文件命名const storage = multer.diskStorage({ destination: path.join(__dirname ,'../static/uploads'), //確定上傳文件的物理位置 filename: function (req, file, cb) { //自定義設(shè)置文件的名字,根據(jù)上傳時間的時間戳來命名 let type = file.originalname.split('.')[1] cb(null, `${file.fieldname}-${Date.now().toString(16)}.${type}`) }})
1.sotrage是一個配置對象。他是通過multer.diskstorage存儲引擎生成的。multer.diskstorage需要傳遞一個配置對象,這里的配置對象里面接收兩個參數(shù)。第一個參數(shù)為destination,它的值為一個路徑字符串,代表的含義是當(dāng)multer處理完成前端傳遞過來的文件之后要把這個文件存儲在哪里。這個文件夾無需手動創(chuàng)建,在接受文件的時候會自動創(chuàng)建。這里建議使用path模塊進(jìn)行拼接,不容易出錯。第二個參數(shù)為一個回調(diào)函數(shù),這里形參要用三個進(jìn)行占位。multer中間件在解析前端提交的文件的時候會調(diào)用這個方法,調(diào)用的時候會給這個filename指向的函數(shù)傳遞三個參數(shù),第二個值為前端傳遞過來文件信息,第三個參數(shù)cb為一個函數(shù),cb函數(shù)調(diào)用的第二個參數(shù)指定的就是當(dāng)前解析完成后的保存到destination指向的目錄的文件名。
const upload = multer({storage});
在需要接收文件的路由里面應(yīng)用upload.single(‘file’)中間件
(1).這個file是前端提交表單過來的時候表單的字段名稱。(2).upload是用multer這個庫里的頂級構(gòu)造函數(shù)生成的實例。
實際網(wǎng)頁開發(fā)當(dāng)中,我們前端需要向后端提交一些像mp4,mp3,圖片系列的東西,需要在后端進(jìn)行接收。那么這里就可以使用Multer中間件來接收文件,對前端傳遞過來的文件做一些處理。
multer是啥? Multer是Express官方推出的,用于node.js 處理前端以multipart/form-data請求數(shù)據(jù)處理的一個中間件。注意: Multer 不會處理任何非 multipart/form-data 類型的表單數(shù)據(jù)
原理: Multer實例的single(‘###’) 是一個方法,這個方法被當(dāng)作中間件放在某一個路由上時。就會給express 的 request 對象中添加一個 body 對象 以及 file 或 files 對象 。 body 對象包含表單的文本域信息,file 或 files 對象包含對象表單上傳的文件信息。下圖就是req.file的模樣。當(dāng)前端請求后臺接口。匹配當(dāng)前路由的時候,先經(jīng)過這個multer中間件,這個中間件就會解析前端傳過來的文件,會把文件保存在上面第三步配置文件解析完成后的文件夾內(nèi),名字也會重命名成上面第三步配置文件解析完成的文件名。同時,會在req的身上掛載一個file對象。這個file對象就是當(dāng)前上傳文件的信息。我們可以通過req.file.filename拿到這個重命名后的文件名,然后把這個文件名保存到數(shù)據(jù)庫里面。前端如果想訪問之前上傳的圖片,后臺只需要把數(shù)據(jù)庫里的文件名取到,隨后映射成我們請求的路徑,去請求public靜態(tài)資源下的存放這些文件的文件夾就可以了。
multer是一個中間件,我建議把這個中間件寫成一個單獨的文件,最后把配置好的multer實例暴露出去,在需要他的路由里面當(dāng)作中間件去應(yīng)用它。就可以很快捷的處理前端發(fā)送過來的文件。而無需每個文件都寫一遍。也更加符合我們模塊化編程的思想。下圖是我multer文件的配置。
五、富文本編輯器
富文本編輯器,Multi-function Text Editor, 簡稱 MTE, 是一種可內(nèi)嵌于瀏覽器,所見即所得的文本編輯器。它提供類似于 Microsoft Word 的編輯功能,容易被不會編寫 HTML 的用戶并需要設(shè)置各種文本格式的用戶所喜愛。
富文本編輯器不同于文本編輯器,程序員可到網(wǎng)上下載免費的富文本編輯器內(nèi)嵌于自己的網(wǎng)站或程序里(當(dāng)然付費的功能會更強大些),方便用戶編輯文章或信息。
[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-9D1VzMYl-1658387147228)(C:Users11933Desktop前端全棧課件前后臺交互imgs富文本編輯器.png)]
layui 富文本編輯器(layedit):
使用:
<textarea id="demo" style="display: none;"></textarea>layui.use(['layedit'],function(){ layedit.build("demo")})
layedit基礎(chǔ)的方法:
方法名
描述
var index = layedit.build(id, options)
用于建立編輯器的核心方法index:即該方法返回的索引參數(shù) id: 實例元素(一般為textarea)的id值參數(shù) options:編輯器的可配置項,下文會做進(jìn)一步介紹
layedit.set(options)
設(shè)置編輯器的全局屬性即上述build方法的options
layedit.getContent(index)
獲得編輯器的內(nèi)容參數(shù) index: 即執(zhí)行l(wèi)ayedit.build返回的值
layedit.getText(index)
獲得編輯器的純文本內(nèi)容參數(shù) index: 同上
layedit.sync(index)
用于同步編輯器內(nèi)容到textarea(一般用于異步提交)參數(shù) index: 同上
layedit.getSelection(index)
獲取編輯器選中的文本參數(shù) index: 同上
編輯器屬性設(shè)置:
屬性
類型
描述
tool
Array
重新定制編輯器工具欄,如: tool: [‘link’, ‘unlink’, ‘face’]
hideTool
Array
不顯示編輯器工具欄,一般用于隱藏默認(rèn)配置的工具bar
height
Number
設(shè)定編輯器的初始高度
uploadImage
Object
設(shè)定圖片上傳接口,如: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 是另一種記錄客戶狀態(tài)的機制,不同的是 Cookie 保存在客戶端瀏覽器中,而 session 保存在服務(wù)器上。Session的用途: session運行在服務(wù)器端,當(dāng)客戶端第一次訪問服務(wù)器時,可以將客戶的登錄信息保存。 當(dāng)客戶訪問其他頁面時,可以判斷客戶的登錄狀態(tài),做出提示,相當(dāng)于登錄攔截。 session可以和Redis或者數(shù)據(jù)庫等結(jié)合做持久化操作,當(dāng)服務(wù)器掛掉時也不會導(dǎo)致某些客戶信息(購物車) 丟失。
(二)、Session的工作流程 當(dāng)瀏覽器訪問服務(wù)器并發(fā)送第一次請求時,服務(wù)器端會創(chuàng)建一個session對象,生成一個類似于 key,value的鍵值對,然后將key(cookie)返回到瀏覽器(客戶)端,瀏覽器下次再訪問時,攜帶key(cookie), 找到對應(yīng)的session(value)。 客戶的信息都保存在session中。
(三)、Cookie和Session區(qū)別:
cookie 數(shù)據(jù)存放在客戶的瀏覽器上,session 數(shù)據(jù)放在服務(wù)器上。
cookie 不是很安全,別人可以分析存放在本地的 COOKIE 并進(jìn)行 COOKIE 欺騙 考慮到安全應(yīng)當(dāng)使用 session。
session 會在一定時間內(nèi)保存在服務(wù)器上。當(dāng)訪問增多,會比較占用你服務(wù)器的性能 考慮到減輕服務(wù)器性能方面,應(yīng)當(dāng)使用 COOKIE。
單個 cookie 保存的數(shù)據(jù)不能超過 4K,很多瀏覽器都限制一個站點最多保存 20 個 cookie。
(四)、express-session的使用
安裝 express-session:
npm install express-session
引入express-session:
var session = require("express-session");
設(shè)置官方文檔提供的中間件:
app.use(session({ secret: 'keyboard cat', resave: true, saveUninitialized: true }))
使用:
設(shè)置值 req.session.username = "張三"; 獲取值 req.session.username
express-session的常用參數(shù):
1. name - cookie的名字(原屬性名為 key)。(默認(rèn):’connect.sid’)2. store - session存儲實例3. secret - 用它來對session cookie簽名,防止篡改4. cookie - session cookie設(shè)置 (默認(rèn):{ path: ‘/‘, httpOnly: true,secure: false, maxAge: null })5. genid - 生成新session ID的函數(shù) (默認(rèn)使用uid2庫)6. rolling - 在每次請求時強行設(shè)置cookie,這將重置cookie過期時間(默認(rèn):false)7. resave - 強制保存session即使它并沒有變化 (默認(rèn): true)8. proxy - 當(dāng)設(shè)置了secure cookies(通過”x-forwarded-proto” header )時信任反向代理。當(dāng)設(shè)定為true時, ”x-forwarded-proto” header 將被使用。當(dāng)設(shè)定為false時,所有headers將被忽略。當(dāng)該屬性沒有被設(shè)定時,將使用Express的trust proxy。9. saveUninitialized - 強制將未初始化的session存儲。當(dāng)新建了一個session且未設(shè)定屬性或值時,它就處于 未初始化狀態(tài)。在設(shè)定一個cookie前,這對于登陸驗證,減輕服務(wù)端存儲壓力,權(quán)限控制是有幫助的。(默認(rèn):true)10. unset - 控制req.session是否取消(例如通過 delete,或者將它的值設(shè)置為null)。這可以使session保持
1. Session.destroy():刪除session,當(dāng)檢測到客戶端關(guān)閉時調(diào)用。2. Session.reload():當(dāng)session有修改時,刷新session。3. Session.regenerate():將已有session初始化。4. Session.save():保存session。
//配置中間件app.use(session({ secret: 'this is string key', // 可以隨便寫。一個 String 類型的字符串,作為服務(wù)器端生成 session 的簽名 name:'session_id',/*保存在本地cookie的一個名字 默認(rèn)connect.sid 可以不設(shè)置*/ resave: false, /*強制保存 session 即使它并沒有變化,。默認(rèn)為 true。建議設(shè)置成 false。*/ saveUninitialized: true, //強制將未初始化的 session 存儲。 默認(rèn)值是true 建議設(shè)置成true cookie: { maxAge:5000 /*過期時間*/ }, /*secure https這樣的情況才可以訪問cookie*/ //設(shè)置過期時間比如是30分鐘,只要游覽頁面,30分鐘沒有操作的話在過期 rolling:true //在每次請求時強行設(shè)置 cookie,這將重置 cookie 過期時間(默認(rèn):false)}))
七、表單事件
屬性
描述
action
接收請求的URL
elements
表單中的所有控件元素集合
length
表單控件的個數(shù)
enctype
編碼類型 例:enctype=“multipart/form-data”
name
表單元素名稱
方法
描述
reset()
把表單的所有輸入元素重置為它們的默認(rèn)值。
submit()
提交表單。
事件
描述
onreset
在重置表單元素之前調(diào)用。
onsubmit
在提交表單之前調(diào)用。
屬性
描述
value
獲取和設(shè)置值
disabled
獲取或設(shè)置表單控件是否禁用值為true或 false
type
讀取表單控件的類型
form
所在表單元素對象
readOnly
控件只讀屬性 Boolean 不能更改只能復(fù)制和讀取
name
獲取與設(shè)置name字段名
事件
描述
onblur
當(dāng)失去焦點的時候
onfocus
當(dāng)獲取焦點的時候
onchange
當(dāng)內(nèi)容改變并失去焦點的時候
oninput
在用戶輸入時觸發(fā)
方法
描述
focus()
獲得焦點
blur()
失去焦點
select()
選擇文本控件中的所有文本內(nèi)容