一绿饵、cmd終端常用命令
1云芦、dir ?????????顯示目錄里面的所有文件(包括文件夾和文件)
2厘擂、cd.. ????????回到上一級目錄
3、cd\ ?????????回到根目錄
4嚼吞、cd 路徑 ?????跳轉(zhuǎn)到指定的目錄(路徑可以是絕對路徑盒件,也可以是相對路徑)
相對路徑是相當(dāng)于當(dāng)前路徑的路徑;絕對路徑是相對于當(dāng)前盤符根路徑的路徑誊薄。
5履恩、盤符名稱: ???切換盤符(比如:d:,回車后就會(huì)切換到d盤)
6呢蔫、cls ?????????清屏(清空屏幕)
7切心、md 目錄名稱 ?創(chuàng)建目錄
8飒筑、rd 目錄名稱 ?刪除空目錄
9、del 文件名 ??刪除指定的文件
10绽昏、del 目錄名 ?刪除目錄里面的全部文件
11协屡、copy 命令用于復(fù)制文件
12、move 命令用于移動(dòng)文件
打開當(dāng)前目錄里面的文件或程序:文件名.擴(kuò)展名 回車
我們在cmd窗口中全谤,輸入文件名.擴(kuò)展名 回車肤晓,首先它會(huì)在當(dāng)前目錄中找該文件是否存在,存在則打開該文件认然。如果當(dāng)前目錄中沒有這個(gè)文件补憾,就會(huì)到系統(tǒng)變量的path中,遍歷所有的路徑卷员,找這個(gè)文件是否存在盈匾,存在則打開文件;如果還是沒有毕骡,則報(bào)錯(cuò)削饵。
二、模塊
js程序不能直接運(yùn)行未巫,必須要在瀏覽器中運(yùn)行窿撬;在網(wǎng)頁中引入js程序時(shí),一定要注意引入的順序叙凡,因?yàn)榍昂骿s可能是有關(guān)系的劈伴。綜上,引入nodejs解決問題狭姨。
在nodejs環(huán)境中宰啦,每一個(gè)獨(dú)立的js文件苏遥,就是一個(gè)獨(dú)立模塊饼拍。
每個(gè)獨(dú)立的模塊是一個(gè)私有的作用域,每一個(gè)獨(dú)立模塊其實(shí)就是獨(dú)立方法田炭。這個(gè)方法师抄,提供了5個(gè)參數(shù):exports, require, module, __filename, __dirname。
1教硫、exports對象
nodejs中叨吮,導(dǎo)出當(dāng)前模塊的成員,可以用exports瞬矩,也可以用module.exports茶鉴。其實(shí)exports對象,指向了module.exports對象景用,最終導(dǎo)出的是module.exports對象涵叮。
通常情況下exports
(1)使用exports對象導(dǎo)出
exports導(dǎo)出成員時(shí)惭蹂,不能重新給exports賦值一個(gè)新對象,只能一個(gè)一個(gè)導(dǎo)出割粮。
let?money =?10000
let?city =?'南京'
exports.money =?money
exports.city =?city
注意:不能采用下面的方式導(dǎo)出成員
?exports?=?{
? ? money:money,
? ? city:city
}
(2)使用module.exports
module.exports導(dǎo)出成員時(shí)盾碗,既可以一個(gè)一個(gè)導(dǎo)出,也可以通過賦值一個(gè)對象的方式導(dǎo)出舀瓢。
module.exports.fun1?=?fun1
module.exports?=?{
? ? money:money,
? ? city:city,
? ? fun1:fun1
}
2廷雅、require方法
用于導(dǎo)入其他模塊里面的成員。
在nodejs中京髓,通過require方法航缀,導(dǎo)入其他模塊。一般情況下堰怨,我們會(huì)通過解構(gòu)賦值的方式谬盐,直接從導(dǎo)入的對象中獲取需要的成員。
let?{money,city,fun1} =?require('./index03.js')
3诚些、module對象
是當(dāng)前模塊本身飞傀,它里面的exports對象屬性,也是用于導(dǎo)出當(dāng)前模塊里面的成員诬烹。
4砸烦、__filename變量
返回當(dāng)前模塊文件的絕對路徑。
console.log(__filename);// E:\kw\kwstudy\nodeJS\L01\index03.js
5绞吁、__dirname變量
返回當(dāng)前模塊文件所在目錄的絕對路徑幢痘。
console.log(__dirname);// E:\kw\kwstudy\nodeJS\L01
三、通過require導(dǎo)入模塊
1家破、require()
require方法颜说,用于導(dǎo)入模塊,方法的參數(shù)是:模塊的標(biāo)識(shí)汰聋。
導(dǎo)入模塊時(shí)门粪,模塊標(biāo)識(shí)如果沒有文件的后綴名,
(1)首先判斷該模塊是不是系統(tǒng)模塊
(2)如果不是系統(tǒng)模塊烹困,再判斷是不是第三方模塊
(3)如果導(dǎo)入的是自定義包里面的模塊玄妈,可以省略包里面的具體的文件
// 表示導(dǎo)入自定義math包里的模塊,默認(rèn)是math包里的index.js文件
let?math?=?require('./math')??
2髓梅、系統(tǒng)模塊
通過系統(tǒng)模塊的名稱導(dǎo)入拟蜻。
let?path?=?require('path')
3、第三方模塊
通過模塊的名稱導(dǎo)入(這個(gè)名稱是package.json文件中name屬性對應(yīng)的名稱)枯饿。
let?math?=?require('math')
4酝锅、自定義模塊
通過模塊的路徑導(dǎo)入,路徑可以是相對路徑奢方,也可以是絕對路徑搔扁。
四擒权、global
在node環(huán)境中,沒有window對象阁谆。有一個(gè)全局對象global碳抄,類似于瀏覽器環(huán)境中的window對象。
五场绿、npm
(1)下載包
備注:install的簡寫是i剖效,--save的簡寫是-S,--save-dev的簡寫是-D焰盗,--global的簡寫-g璧尸。
npm install 包名 ??????????????下載包 (默認(rèn)會(huì)將下載的包添加到生產(chǎn)環(huán)境依賴,生產(chǎn)環(huán)境依賴的包參與本項(xiàng)目的打包)
npm install 包名 --save ???????(--save表示下載包熬拒,并添加到生產(chǎn)環(huán)境依賴)
npm install 包名 --save-dev ???(--save-dev表示下載包爷光,并添加到開發(fā)環(huán)境依賴,只是開發(fā)時(shí)依賴該包澎粟,不參與本項(xiàng)目的打包)
npm install 包名 --global ?????安裝全局插件
使用npm下載第三方包后蛀序,會(huì)在項(xiàng)目根路徑中添加一個(gè)package-lock.json文件。該文件是可以刪除的活烙,它的作用是記錄第三方包的完整信息徐裸,方便下次下載包時(shí)快速定位該包的信息,省去了查找包的時(shí)間啸盏。
(2)升級包
npm update 包名 ???????????????對指定包進(jìn)行升級
npm update ????????????????????升級所有包
[if !supportLists](1)[endif]刪除包
備注:remove的簡寫是r
npm remove 包名 ???????????????移除包
npm uninstall 包名 ????????????卸載包(功能等同于移除包)
(4)下載所有依賴包
npm install/i ????????根據(jù)package.json文件中的依賴關(guān)系重贺,下載當(dāng)前項(xiàng)目所依賴的包
3、npm鏡像地址
(1)查看npm鏡像地址
npm config get registry
(2)修改npm鏡像地址
① npm config edit 打開npm的配置文件回懦,然后修改
registry=http://registry.npm.taobao.org/
② npm config set registry http://registry.npm.taobao.org
(3)還原npm原來的鏡像地址
npm config set registry https://registry.npmjs.org/
4气笙、安裝cnpm中國npm鏡像客戶端
npm install cnpm -g ???全局安裝cnpm
cnpm的所有命令跟npm一樣。(唯一的區(qū)別是:cnpm install 包名怯晕,不會(huì)將下載的包默認(rèn)添加到生產(chǎn)環(huán)境依賴潜圃。必須要加上--save。)
5贫贝、安裝nodemon工具
nodemon是一種工具秉犹,可以自動(dòng)監(jiān)測文件的變化,當(dāng)有變化時(shí)重新啟動(dòng)服務(wù)稚晚。(需要使用nodemon時(shí),先關(guān)閉自動(dòng)保存)
npm i nodemon -g ?????全局安裝nodemon
nodemon ./index.js運(yùn)行index.js文件
六型诚、yarn
1客燕、安裝yarn包管理工具
npm install yarn -g
2、yarn鏡像地址
(1)查看yarn鏡像地址
yarn config get registry
(2)修改yarn鏡像地址
yarn config set registry http://registry.npm.taobao.org/
(3)還原yarn原理的鏡像地址
yarn config set registry http://registry.npmjs.org/
3狰贯、yarn的常用命令
(1)下載所有依賴包
yarn install === npm install ???????????????注意:npm中install也搓,可以簡寫成i赏廓,yarn中不可以;但是yarn可以省略install傍妒。
(2)下載包
yarn add 包名 === npm install 包名 --save ???注意:--save可以省略幔摸,因?yàn)槟J(rèn)就是添加到生產(chǎn)依賴。
yarn add 包名 --dev === npm install 包名 --save-dev
yarn global add 包名 === npm install 包名 --global ???注意:npm中--global可以簡寫成-g颤练。
(3)刪除包
yarn remove 包名 === npm remove 包名 ????????注意:npm中remove既忆,可以簡寫為r,yarn中不可以嗦玖。
(4)升級包
yarn upgrade 包名 === npm update 包名
yarn upgrade === npm update
七患雇、系統(tǒng)模塊path
1、定義
系統(tǒng)模塊path宇挫,用于操作路徑相關(guān)苛吱。
let?path?=?require('path')
2、join() 路徑拼接
path.join('路徑','路徑',...) ??該方法會(huì)根據(jù)當(dāng)前nodejs所在的系統(tǒng)環(huán)境器瘪,返回正確格式的拼接路徑翠储。
不同的操作系統(tǒng),路徑的拼接符是不一樣的橡疼。windows系統(tǒng)中彰亥,路徑的拼接符是 / 或 \ ;linux系統(tǒng)中衰齐,路徑的拼接符是 / 任斋;我們用nodeJS開發(fā)的程序,將來部署到什么操作系統(tǒng)的服務(wù)器上是不確定的耻涛。所以废酷,使用join()方法,返回拼接路徑抹缕。
console.log(path.join('a','b','c','d'))// ?a\b\c\d
3澈蟆、resolve()
帶參數(shù),path.resolve(相對路徑)方法卓研,返回一個(gè)相對路徑的絕對路徑趴俘。
console.log(path.resolve('./file/a.txt'))?// ?E:\kw\kwstudy\nodeJS\1028\file\a.txt
不帶參數(shù),path.resolve()方法奏赘,返回當(dāng)前模塊所在目錄的絕對路徑寥闪。
console.log(path.resolve());// E:\kw\kwstudy\nodeJS\1028
全局變量__dirname,也是返回當(dāng)前模塊所在目錄的絕對路徑
console.log(__dirname);// E:\kw\kwstudy\nodeJS\1028
4磨淌、返回指定包(math)的絕對路徑
// E:\kw\kwstudy\nodeJS\1028\math
console.log(path.join(path.resolve(),'math'));
七疲憋、系統(tǒng)模塊path
1、定義
系統(tǒng)模塊path梁只,用于操作路徑相關(guān)缚柳。
let?path?=?require('path')
2埃脏、join() 路徑拼接
path.join('路徑','路徑',...) ??該方法會(huì)根據(jù)當(dāng)前nodejs所在的系統(tǒng)環(huán)境,返回正確格式的拼接路徑秋忙。
不同的操作系統(tǒng)彩掐,路徑的拼接符是不一樣的。windows系統(tǒng)中灰追,路徑的拼接符是 / 或 \ 堵幽;linux系統(tǒng)中,路徑的拼接符是 / 监嗜;我們用nodeJS開發(fā)的程序谐檀,將來部署到什么操作系統(tǒng)的服務(wù)器上是不確定的。所以裁奇,使用join()方法桐猬,返回拼接路徑。
console.log(path.join('a','b','c','d'))// ?a\b\c\d
3刽肠、resolve()
帶參數(shù)溃肪,path.resolve(相對路徑)方法,返回一個(gè)相對路徑的絕對路徑音五。
console.log(path.resolve('./file/a.txt'))?// ?E:\kw\kwstudy\nodeJS\1028\file\a.txt
不帶參數(shù)惫撰,path.resolve()方法,返回當(dāng)前模塊所在目錄的絕對路徑躺涝。
console.log(path.resolve());// E:\kw\kwstudy\nodeJS\1028
全局變量__dirname厨钻,也是返回當(dāng)前模塊所在目錄的絕對路徑
console.log(__dirname);// E:\kw\kwstudy\nodeJS\1028
4、返回指定包(math)的絕對路徑
// E:\kw\kwstudy\nodeJS\1028\math
console.log(path.join(path.resolve(),'math'));
八坚嗜、系統(tǒng)模塊fs
1夯膀、定義
系統(tǒng)模塊fs,用于操作文件相關(guān)苍蔬。
let?fs?=?require('fs')
2诱建、同步方式方式讀取文件
同步方式讀取文件,指的是文件的讀取過程必須是一個(gè)一個(gè)讀取碟绑。假如俺猿,后面還要讀取其他文件,必須要等到前面的文件讀取完成了格仲,再讀取下一個(gè)文件押袍。
(1)讀取文件 openSync/readSync/closeSync
① 打開文件,通過openSync方法打開文件抓狭,返回值是文件標(biāo)識(shí)(文件標(biāo)識(shí)是一個(gè)數(shù)字)
let?fd?=?fs.openSync('./file/a.txt','r')
② 讀取文件中的內(nèi)容伯病,通過readSync方法讀取文件。
參數(shù)1:文件標(biāo)識(shí)
參數(shù)2:buffer容器
創(chuàng)建一個(gè)buffer容器否过,用于接收讀取到的數(shù)據(jù)午笛,其實(shí)就是開辟一段內(nèi)存空間(單位是字節(jié))。注意:一個(gè)漢字占用三個(gè)字節(jié)空間苗桂。
let?buf?=?Buffer.alloc(30)// 創(chuàng)建30字節(jié)的buffer容器
fs.readSync(fd,buf)// 用buf接收fd文件數(shù)據(jù)
③ 文件讀取結(jié)束后药磺,需要關(guān)閉文件。
fs.closeSync(fd)// 關(guān)閉fd文件
[if !supportLists](2)[endif]一般方式讀取文件readFileSync()
fs.readFileSync(文件路徑)
let?buf?=?fs.readFileSync('./file/a.txt')
console.log('同步:'+buf.toString());
[if !supportLists]1煤伟、[endif]同步寫入文件
同步方式寫入文件的缺陷:如果要寫入多個(gè)文件癌佩,只能一個(gè)一個(gè)寫。
(1)寫入一個(gè)文件 openSync/writeSync/closeSync
① 打開文件便锨,通過openSync方法打開文件围辙,返回值是文件標(biāo)識(shí)(文件標(biāo)識(shí)是一個(gè)數(shù)字)
參數(shù)1:文件路徑,
參數(shù)2:打開文件的方式:r是讀放案,w是寫姚建,a是追加。
let?fd?=?fs.openSync('./file/b.txt','a')
② 向文件中寫入內(nèi)容(如果需要寫入中文吱殉,加一個(gè)'utf-8'掸冤;內(nèi)容是純英文可以省略)
fs.writeSync(fd,'HelloWorld你好','utf-8')
fs.writeSync(fd,'HelloWorld')
③ 文件寫入后,需要關(guān)閉文件
fs.closeSync(fd)
(2)一般方式寫入文件 writeFileSync()
writeFileSync()方法內(nèi)部已經(jīng)完成了文件的打開友雳、讀取稿湿、關(guān)閉操作。
try{
? ? fs.writeFileSync('./file/a.txt','HelloWorld',{flag:'a'})// 追加參數(shù)a要寫在對象中
? ? console.log('同步:寫入成功押赊!');
}catch{
? ? console.log('寫入失斀忍佟!');
}
4、異步方式讀取文件
異步方式讀取文件鲫忍,采用的都是回調(diào)函數(shù)的形式俯萌,相比較同步方式,代碼量變復(fù)雜了咽袜。優(yōu)勢是,可以同時(shí)操作多個(gè)文件枕稀。
(1)讀取文件 open/read/close
//01.打開文件
fs.open('./file/a.txt',(err,fd)=>{
?//回調(diào)函數(shù)的兩個(gè)參數(shù)分別是:錯(cuò)誤信息询刹,文件標(biāo)識(shí),如果能夠打開文件萎坷,錯(cuò)誤信息為null
if(!err){
?//02.讀取文件中的內(nèi)容
fs.read(fd,(err,num,buf)=>{
//回調(diào)函數(shù)的三個(gè)參數(shù)分別是:錯(cuò)誤信息凹联,讀取文件的字節(jié)數(shù),buffer內(nèi)容
if(!err){
console.log('讀取了'+num+'個(gè)字節(jié)');
console.log('內(nèi)容是:'+buf.toString());
? ? ? ? ? ? }
?//03.文件讀取結(jié)束后哆档,需要關(guān)閉文件
fs.close(fd,(err)=>{
if(!err){
? ? ? ? ? ? ? ? ? ? console.log('文件讀取完畢蔽挠!');
? ? ? ? ? ? ? ? }
? ? ? ? ? ? })
? ? ? ? })
? ? }
})
(2)一般方式讀取文件 readFile()
方法內(nèi)部,幫我們完成了文件的打開,讀取澳淑,關(guān)閉操作比原。
fs.readFile('./file/a.txt',(err,buf)=>{
if(!err){
console.log('異步:'+buf.toString());
? ? }
})
5、異步方式寫入文件
(1)寫入文件 open/read/close
// 01.打開文件
// 參數(shù)1:文件位置
// 參數(shù)2:打開文件的方式杠巡,r是讀量窘,w是寫,a是追加
fs.open('./file/b.txt','a',(err,fd)=>{
if(!err){
?// 02.向文件中寫入內(nèi)容
fs.write(fd,'HelloWorld',(err)=>{
if(!err){
?// 03.文件寫入后氢拥,需要關(guān)閉文件
fs.close(fd,(err)=>{
if(!err){
? ? ? ? ? ? ? ? ? ? ? ? console.log('寫入成功蚌铜!');
? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? })
? ? ? ? ? ? }
? ? ? ? })
? ? }
})
(2)一般方式寫入文件 writeFile()
fs.writeFile('./file/b.txt','HelloWorld',{flag:'a'},(err)=>{
if(!err){
? ? ? ? console.log('異步:寫入成功!');
? ? }
})
九嫩海、try..catch
將可能會(huì)發(fā)生異常的代碼放在try中冬殃,如果程序發(fā)生異常,會(huì)跳轉(zhuǎn)到catch中執(zhí)行保護(hù)代碼叁怪,
使程序不至于就此終止审葬。catch代碼塊可以傳遞一個(gè)參數(shù)e,里面保存的是發(fā)生異常的消息骂束。
// 文件系統(tǒng)在實(shí)際開發(fā)中的用法:
try{
? ? let?num1?=?10
? ? let?num3?=?num1?+?num4
? ? console.log(num3);
}catch(e){
?//通常情況下耳璧,需要將錯(cuò)誤信息寫入到日志文件中
?// console.log('上面的代碼發(fā)生了錯(cuò)誤',e.message);
fs.writeFile('./file/log.txt',e.message+' 發(fā)生時(shí)間:'+(new?Date())+'\r\n',{flag:'a'},(err)=>{
if(!err){
? ? ? ? ? ? console.log('錯(cuò)誤信息,寫入日志文件');
? ? ? ? }
? ? })
}
十展箱、同步API和異步API
1旨枯、同步API
同步API:只有當(dāng)前API執(zhí)行完成后,才能繼續(xù)執(zhí)行下一個(gè)API混驰。
同步API攀隔,可以通過返回值接收結(jié)果。
//同步API
function?fun1(){
? ? return?'大家好栖榨!我是一個(gè)同步方法'
}
//同步API昆汹,可以通過返回值接收結(jié)果
let?str1?=?fun1()
console.log(str1);// str1
2、異步API
異步API:當(dāng)前API的執(zhí)行不會(huì)阻塞后續(xù)代碼的執(zhí)行婴栽。
異步API時(shí)满粗,直接寫一個(gè)回調(diào)函數(shù)作為參數(shù)傳進(jìn)入,這個(gè)函數(shù)接收異步API返回值愚争。
//異步API
function?fun2(callback){
? ? setTimeout(() =>?{
? ? ? ? callback('大家好映皆!我是一個(gè)異步方法')
? ? }, 1000);
}
//調(diào)用異步API時(shí),直接寫一個(gè)回調(diào)函數(shù)作為參數(shù)傳進(jìn)入轰枝。
//回調(diào)函數(shù)捅彻,通常會(huì)寫成箭頭函數(shù)
fun2(str?=>?console.log(str))
十一、Promise 對象
1鞍陨、語法
ES6推出了一個(gè)全新的對象:Promise步淹,該對象用于處理回調(diào)地獄。
Promise的構(gòu)造函數(shù)接收一個(gè)參數(shù),是函數(shù)缭裆,并且傳入兩個(gè)參數(shù):resolve键闺,reject,分別表示異步操作執(zhí)行成功后的回調(diào)函數(shù)和異步操作執(zhí)行失敗后的回調(diào)函數(shù)幼驶。
Promise對象的then()方法用來獲取成功的返回結(jié)果艾杏;catch()方法用來獲取失敗的返回結(jié)果韧衣。
function?myReadFile(path) {
return?new?Promise((resolve) =>?{
fs.readFile(path, (err,?r) =>?{
if?(!err) {
resolve(r.toString())
? ? ? ? ? ? }
? ? ? ? })
? ? })
}
myReadFile('./file/a.txt').then(r=>?{
if?(r==?'中國') {
? ? ? ? return?myReadFile('./file/e.txt')
? ? }
}).then(r=>?{
if?(r==?'賽虹橋街道') {
console.log(r);
? ? }
})
2盅藻、async和await
async關(guān)鍵字,用于定義異步函數(shù)畅铭,異步函數(shù)中氏淑,可以使用await關(guān)鍵字,簡化then的步驟硕噩。await關(guān)鍵字提取Promise對象的返回的結(jié)果假残。
async?function?run() {
? ? let?a?=?await?myReadFile('./file/a.txt')
? ? if?(a?!=?'中國') return
? ? let?e?=?await?myReadFile('./file/e.txt')
? ? if?(e?!=?'賽虹橋街道') return
? ? console.log(e);
}
run()
十二、MongoDB數(shù)據(jù)庫
1炉擅、數(shù)據(jù)庫下載安裝
使用Node.js操作MongoDB數(shù)據(jù)庫需要依賴Node.js第三方包mongoose辉懒。
使用npm install mongoose命令下載。
2谍失、啟動(dòng)MongoDB
運(yùn)行net start mongoDB即可啟動(dòng)MongoDB眶俩,否則MongoDB將無法連接。
[if !supportLists]3快鱼、[endif]導(dǎo)入mongoose和數(shù)據(jù)庫連接
使用mongoose提供的connect方法連接數(shù)據(jù)庫颠印。注意:如果連接的數(shù)據(jù)庫(MySchool)不存在,會(huì)自動(dòng)創(chuàng)建數(shù)據(jù)庫(MySchool)抹竹。
// 導(dǎo)入mongoose
let?mongoose?=?require('mongoose')
// 連接數(shù)據(jù)庫
mongoose.connect('mongodb://localhost/MySchool',
{ useNewUrlParser:?true,useUnifiedTopology:?true?})
.then(() =>?console.log('數(shù)據(jù)庫連接成功'))
.catch(err=>?console.log('數(shù)據(jù)庫連接失敗',?err));
4线罕、創(chuàng)建表
(1)定義表規(guī)則
定義表規(guī)則:表里面的有哪些列,分別是什么數(shù)據(jù)類型窃判。
① 基本寫法
// 定義student表規(guī)則
const?studentSchema?=?new?mongoose.Schema({
?//定義具體的表規(guī)則
? ? name:?String,
? ? age:?Number,
? ? sex:String,
? ? hobbies:[String],
? ? isVip:?Boolean
});
② 定義表里具體屬性的規(guī)范
在創(chuàng)建集合規(guī)則時(shí)钞楼,可以設(shè)置當(dāng)前字段的驗(yàn)證規(guī)則,驗(yàn)證失敗就輸入插入失敗袄琳。
required: true ???必傳字段
minlength:3 ???字符串最小長度
maxlength: 20 ??字符串最大長度
min: 2 ???數(shù)值最小為2
max: 100 ???數(shù)值最大為100
enum: ['html', 'css', 'javascript', 'node.js']
trim: true ???去除字符串兩邊的空格
validate: 自定義驗(yàn)證器
default: 默認(rèn)值
let?studentSchema?=?new?mongoose.Schema({
?//name屬性的規(guī)范
? ? name:{
type:String,// 類型是String
require:true,// 不允許為空
minlength:2,// 最小長度為2
maxlength:8// 最大長度為8
? ? },
? ? sex:{
? ? ? ? type:String,
default:'男'// 性別的默認(rèn)值是“男”
? ? },
? ? age:{
? ? ? ? type:Number,? ?
min:3,// 年齡的范圍是3-100
? ? ? ? max:100
? ? },
? ? hobbies:{
? ? ? ? type:[String],?
require:false// 愛好允許為空
? ? }
})
(2)創(chuàng)建表對象
注意:數(shù)據(jù)庫中的表名會(huì)自動(dòng)改成復(fù)數(shù)格式(students)
const?Student?=?mongoose.model('Student', studentSchema)
[if !supportLists]5询件、[endif]向表中添加數(shù)據(jù)
方法(1) 通過表實(shí)例對象
① 創(chuàng)建表實(shí)例對象
// 5.1.
const?stu1?=?new?Student({
? ? name:?'張三',
? ? age:?20,
? ? sex:?'男',
? ? hobbies:?['學(xué)習(xí)','睡覺','打球'],
? ? isVip:true
});
② 表實(shí)例對象通過save方法將數(shù)據(jù)保存到數(shù)據(jù)庫的數(shù)據(jù)表中
stu1.save((err,result)=>{
? ? if(!err){
?//添加成功,打印添加的結(jié)果
? ? ? ? console.log(result);
? ? }
})
方法(2) create方法跨蟹,通過回調(diào)函數(shù)返回結(jié)果
通過數(shù)據(jù)表的create的方法雳殊,直接向數(shù)據(jù)表中添加數(shù)據(jù)(通過回調(diào)函數(shù)返回結(jié)果)。
Student.create({
? ? name:?'李四',
? ? age:?22,
? ? sex:?'女',
? ? hobbies:?['看電視','睡覺','看電影'],
? ? isVip:false
},(err,result)=>{
if(!err){
console.log(result);
? ? }
})
方法(3) create方法窗轩,通過Promise對象返回結(jié)果
通過數(shù)據(jù)表的create的方法夯秃,直接向數(shù)據(jù)表中添加數(shù)據(jù)(通過Promise對象返回結(jié)果)。
Student.create({
? ? name:?'王五',
? ? age:?24,
? ? sex:?'男',
? ? hobbies:?['敲代碼','睡覺','寫字'],
? ? isVip:true
}).then(result=>{
console.log(result);
}).catch(err=>{
console.log(err);
})
6、查詢語句
(1)查詢?nèi)啃畔ind()
find方法返回的是數(shù)組仓洼。
// 查詢student表的全部數(shù)據(jù)
Student.find().then(r=>{
? ? console.log(r);
})
(2)根據(jù)條件查詢find(條件)
返回的是符合條件的數(shù)組介陶。如果沒有滿足條件的結(jié)果,就返回一個(gè)空數(shù)組色建。
Student.find({name:'李白'}).then(r=>{
? ? console.log(r);
})
(3)返回表中的第一個(gè)對象findOne()
findOne方法返回的是對象哺呜。
Student.findOne().then(r=>{
console.log(r);
})
(4)根據(jù)條件查詢 findOne(條件)
查詢第一個(gè)滿足條件的,返回的是對象箕戳,如果沒有滿足條件的結(jié)果某残,就返回null。
Student.findOne({name:'李白'}).then(r=>{
? ? console.log(r);
})
(5)查詢某個(gè)范圍內(nèi)的數(shù)據(jù)
① 查詢大于某數(shù)值的數(shù)據(jù) $gt
// 查詢年齡大于20歲的學(xué)生信息
Student.find({age:{$gt:20}}).then(r=>{
console.log(r);
})
② 查詢大于某數(shù)值的數(shù)據(jù) $lt
// 查詢年齡小于20歲的學(xué)生信息
Student.find({age:{$lt:20}}).then(r=>{
console.log(r);
})
③ 查詢兩數(shù)之間的數(shù)據(jù) {$gt:num1,$lt:num2}}
// 查詢年齡在20歲到40歲之間的學(xué)生信息
Student.find({age:{$gt:20,$lt:40}}).then(r=>{
console.log(r);
})
④ 查詢兩數(shù)之間的數(shù)據(jù)(包括兩數(shù)) {$gte:num1,$lte:num2}}
// 查詢年齡在20歲到40歲之間的學(xué)生信息(包括20和40)
Student.find({age:{$gte:20,$lte:40}}).then(r=>{
console.log(r);
})
(6)根據(jù)正則表達(dá)式匹配查詢條件(用于模糊查詢)
$regex 正則陵吸,用于模糊查詢玻墅。
select方法,篩選查詢列壮虫。注意:_id列默認(rèn)會(huì)返回澳厢,如果不需要查詢id,就加上-_id囚似。
// 查詢姓名中包含'劉'的學(xué)生信息剩拢,只返回name、sex饶唤、age列
Student.find({name:{$regex:/劉/i}}).select('name sex age -_id').then(r=>{
? ? console.log(r);
})
注意:如果正則條件是模板字符串徐伐,需要使用new RegExp()創(chuàng)建。
Student.find({ name:?{ $regex:?new?RegExp(`${name}`, 'i') } }).then(r=>?{res.send(r)})
(7)匹配包含
① $in 滿足其中一個(gè)元素的數(shù)據(jù)
?// 查詢愛好中包含‘睡覺’或‘學(xué)習(xí)’的學(xué)生信息
Student.find({hobbies:{$in:['睡覺','學(xué)習(xí)']}}).select('name sex age hobbies -_id').then(r=>{
? ? console.log(r);
})
② $all 滿足所有元素的數(shù)據(jù)
// 查詢愛好中包含‘睡覺’和‘學(xué)習(xí)’的學(xué)生信息
Student.find({hobbies:{$all:['睡覺','學(xué)習(xí)']}}).select('name sex age hobbies -_id').then(r=>{
console.log(r);
})
(8)對查詢結(jié)果排序sort()
① 升序排列
// 根據(jù)年齡升序查詢學(xué)生信息
Student.find().sort('age').select('name sex age -_id').then(r=>{
? ? console.log(r);
})
② 降序排列
// 根據(jù)年齡降序查詢學(xué)生信息
Student.find().sort('-age').select('name sex age -_id').then(r=>{
? ? console.log(r);
})
③ 根據(jù)性別升序搬素,再根據(jù)年齡降序
// 先返回相同性別的學(xué)生呵晨,相同性別的學(xué)生再根據(jù)年齡降序
Student.find().sort('sex -age').select('name sex age -_id').then(r=>{
? ? console.log(r);
})
(9)分頁查詢
skip()跳過多少條數(shù)據(jù);limit()限制查詢數(shù)量熬尺。
// 每頁2條數(shù)據(jù)摸屠,顯示第2頁
let?pageIndex?=?2//定義頁碼
let?pageSize?=?2//定義每頁數(shù)量
Student.find().skip((pageIndex-1)*pageSize).limit(pageSize).select('name sex age -_id').then(r=>{
console.log(r);
})
(10)修改指定對象的信息
① 修改單個(gè)對象 updateOne()
updateOne({查詢條件}, {要修改的值})
Student.updateOne({_id:'617f5d951df9a826303015fa'},{name:'張飛',age:38}).then(r=>{
console.log(r);
})
② 修改多個(gè)對象 updateMany()
updateMany({查詢條件}, {要更改的值})
Student.updateMany({sex:'女'},{age:25}).then(r=>{
? ? console.log(r);
})
(11)刪除數(shù)據(jù)
① 刪除單個(gè) findOneAndDelete()
刪除成功后,返回刪除的對象
Student.findOneAndDelete({ _id:?'617f5d951df9a826303015fa'?}).then(r=>?{
? ? console.log(r)
})
② 刪除單個(gè) deleteOne()
刪除成功后粱哼,返回刪除的數(shù)量
Student.deleteOne({ _id:?'617f5d951df9a826303015fc'?}).then(r=>?{
? ? console.log(r)
})
③ 刪除多個(gè) deleteMany()
刪除成功后季二,返回刪除的數(shù)量
Student.deleteMany({sex:'女'}).then(r=>{
console.log(r);
})
十三、Express框架
1揭措、定義
Express是一個(gè)基于Node平臺(tái)的web應(yīng)用開發(fā)框架胯舷,它提供了一系列的強(qiáng)大特性,幫助你創(chuàng)建各種Web應(yīng)用绊含。
使用npm install express 命令進(jìn)行下載桑嘶。
2、基本步驟
(1)導(dǎo)入express
let?express?=?require('express')
(2)通過express函數(shù)躬充,創(chuàng)建并返回一個(gè)web服務(wù)器對象
let?app?=?express()
(3)啟動(dòng)服務(wù)器逃顶,并監(jiān)聽一個(gè)端口號(端口號是自定義的)
app.listen(8848,()=>{
? ? console.log('服務(wù)器成功開啟讨便,端口號是8848');
})
3、中間件
(1)定義
中間件就是一堆方法以政,可以接收客戶端發(fā)來的請求霸褒、可以對請求做出響應(yīng),也可以將請求繼續(xù)交給下一個(gè)中間件繼續(xù)處理盈蛮。
(2)app.use中間件用法
app.use 匹配所有的請求方式废菱,可以直接傳入請求處理函數(shù),代表接收所有的請求抖誉。所有的請求殊轴,都會(huì)先走use,作用是攔截器寸五。
實(shí)際開發(fā)中梳凛,我們用use中間件方法里面去判斷用戶的權(quán)限,從而確定該用戶能否繼續(xù)請求相關(guān)的接口梳杏。
app.use((req,res,next)=>{
?//表示:允許跨域請求
?res.setHeader('Access-Control-Allow-Origin','*')
?//next方法,表示繼續(xù)往下執(zhí)行
? ? next()
})
4淹接、跨域
(1)定義
同源策略:協(xié)議名十性,主機(jī)名(域名或ip地址),端口號必須完全相同塑悼。違背同源策略就是跨域劲适。
ajax請求,必須要遵循同源策略厢蒜。
(1)解決跨域
設(shè)置響應(yīng)頭霞势,允許跨域請求。
?response.setHeader('Access-Control-Allow-Origin','*')
(2)允許自定義請求頭信息
響應(yīng)頭*表示所有類型的頭信息都可以接受斑鸦。
?response.setHeader('Access-Control-Allow-Headers','*')
5愕贡、get請求接口
(1)get請求參數(shù)的獲取
req.query接收前端傳遞的GET請求參數(shù),框架內(nèi)部會(huì)將GET參數(shù)轉(zhuǎn)換為對象并返回巷屿。
(2)定義get請求接口
req是請求對象固以,里面保存的是客戶端傳過來的請求參數(shù)。
res是響應(yīng)對象嘱巾,用于給客戶端響應(yīng)結(jié)果憨琳。
res.send()將結(jié)果返回給前端。
app.get('/getStudents',(req,res)=>{
?res.send('hello')
})
6旬昭、post請求接口
(1)post請求參數(shù)的獲取
req.body接收前端傳遞過來的POST請求參數(shù)篙螟。
接收POST請求參數(shù),服務(wù)器需要進(jìn)行設(shè)置问拘。
通過express.json()中間件遍略,解析表單中的JSON格式數(shù)據(jù)慢味。
通過express.urlencoded()中間件,解析表單中的url-encoded格式數(shù)據(jù)墅冷。
// 設(shè)置允許接收json格式的數(shù)據(jù)({"name":"張三","age":20})
app.use(express.json())
// 設(shè)置允許接收urlencoded格式的數(shù)據(jù)("name=張三&age=20")
app.use(express.urlencoded({extended:false}))
(2)定義post請求接口
app.post('/add', (req,?res) =>?{
console.log(req.body);// 接收請求參數(shù)
?res.send('hello')
})
十四纯路、AJAX
1、原生AJAX
(1)GET請求
GET請求的參數(shù)寞忿,使用?直接拼接在url地址后面驰唬,如果有多個(gè)參數(shù)使用&符號。
參數(shù)例如:name=${name}&pageIndex=${pageIndex}
// 01.創(chuàng)建xhr對象
let?xhr?= new?XMLHttpRequest()
// 02.初始化請求
xhr.open('GET',`http://localhost:5566/students?name=${name}`)
// 03.發(fā)送請求
xhr.send()
// 04.監(jiān)聽事件腔彰,并接收結(jié)果
xhr.onreadystatechange?= function(){
//請求完成
? ? ?if(xhr.readyState===4){
//請求成功
? ? ? ? ?if(xhr.status===200){? ? ?
console.log(xhr.response);//打印響應(yīng)結(jié)果
? ? ? ? ?}
? ? ?}
?}
(2)POST請求
① 設(shè)置Content-Type請求頭
POST請求時(shí)叫编,需要設(shè)置Content-Type請求頭,告訴服務(wù)器傳遞的數(shù)據(jù)格式霹抛。
如果是urlencoded格式的數(shù)據(jù):
xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded")
如果是json字符串格式的數(shù)據(jù):
xhr.setRequestHeader('Content-Type','application/json')
② 參數(shù)傳遞
post請求的參數(shù)搓逾,在發(fā)送時(shí)傳遞。
傳遞urlencoded格式的數(shù)據(jù):
xhr.send(`name=polo&age=35`)
傳遞json字符串格式的數(shù)據(jù):
let?params?= {
? ? ?name:name,
hobbies:hobbies.split(',')//愛好杯拐,轉(zhuǎn)為數(shù)組
?}
xhr.send(JSON.stringify(params))// 將對象轉(zhuǎn)為json格式字符串
③ 基本格式
??let?xhr?= new?XMLHttpRequest()
? xhr.open('POST','http://localhost:5566/deleteStudent')
? xhr.setRequestHeader('Content-Type','application/json')
xhr.send(JSON.stringify({_id:id}))
? xhr.onreadystatechange?= function(){
? ? ? if(xhr.readyState===4){
? ? ? ? ? if(xhr.status===200){
? ? ? ? ? ? ? ? console.log(xhr.response);
? ? ? ? ? }
? ? ? }
}
[if !supportLists]2霞篡、[endif]jQuery AJAX
[if !supportLists](1)[endif]GET請求
$.get(請求地址, {參數(shù)名: 參數(shù)值}, 回調(diào)函數(shù))
$.get('http://localhost:5566/students',{name:"張三"},r=>{
console.log(r);// r表示請求成功時(shí)返回的結(jié)果數(shù)據(jù)
? })
[if !supportLists](2)[endif]POST請求
$.post(請求地址, {參數(shù)名: 參數(shù)值}, 回調(diào)函數(shù))
$.post('http://localhost:5566/deleteStudent',{_id:id},r=>{
console.log(r);// r表示請求成功時(shí)返回的結(jié)果數(shù)據(jù)
? })
[if !supportLists](3)[endif]通用型方法ajax
① get請求
? ? ? ? ? ? $.ajax({
type:?"get",// 請求的接口地址
url:?url,// 請求方式get 或 post
dataType:?"json",?// 返回的數(shù)據(jù)類型
?// 請求成功后的回調(diào)函數(shù)
success:?function?(r) {
console.log(r)
? ? ? ? ? ? ? ? },
?// 請求失敗后調(diào)用的函數(shù)
error:?function?(err) {
? ? ? ? ? ? ? ? ? ? console.log('請求錯(cuò)誤')
? ? ? ? ? ? ? ? }
? ? ? ? ? ? });
② post請求
發(fā)送post請求時(shí),如果請求參數(shù)是json字符串格式端逼,需要設(shè)置contentType請求頭為'application/json'朗兵。contentType默認(rèn)值 "application/x-www-form-urlencoded"。
let?params?= {
? ? ?????name:name,
? ? ?????hobbies:hobbies.split(',')
???}
$.ajax({
url:url,// 請求的接口地址
type:'POST',// 請求方式get 或 post
data:JSON.stringify(params),// 請求的參數(shù)
? ? ? ? ?contentType:'application/json',
success:function(r){
console.log(r);// r表示請求成功時(shí)返回的結(jié)果數(shù)據(jù)
? ? ? ? ?}
? ? })
3顶滩、axios AJAX
(1)引入axios庫
src="https://cdn.bootcdn.net/ajax/libs/axios/0.21.1/axios.js">
(2)GET請求
① get請求的參數(shù)可以直接用余掖?拼接在URL中。
axios.get('/user?ID=12345').then(function?(response) {
console.log(response);
}).catch(function?(error) {
console.log(error);
? ? ? ? });
② get請求的參數(shù)可以寫在params對象中礁鲁。
注意:get請求的返回結(jié)果包含很多信息盐欺,需要將結(jié)果中的data解構(gòu)出來。data中存放的才是需要的數(shù)據(jù)仅醇。
? ? ? axios.get('http://localhost:5566/students', {
? ? ? ? ? ? params:?{
? ? ? ? ? ? ???name:name
? ? ? ? ? ?}
}).then(({?data}) =>?{
? ? ? ? ? ?console.log(data)
? ? ? })
(3)POST請求
post請求參數(shù)直接寫在對象中傳入冗美。
let?params?= {
? ? ?????name:name,
? ? ?????hobbies:hobbies.split(',')
?}
axios.post(`http://localhost:5566/deleteStudent`, params?).then(({?data}) =>?{
? ? ? ? ?console.log(data)
})
(4)通用方式axios
? ? ? ? ? ? axios({? ? ?
method:?'POST',//請求方法
url:?'/axios-server',//url
params:?{//請求參數(shù)
? ? ? ? ? ? ? ? ? ? vip:?10,
? ? ? ? ? ? ? ? ? ? level:?30
? ? ? ? ? ? ? ? }, ? ? ? ? ?
headers:?{//設(shè)置請求頭信息
? ? ? ? ? ? ? ? ? ? a:?100,
? ? ? ? ? ? ? ? ? ? b:?200
? ? ? ? ? ? ? ? },
?//請求體參數(shù)
? ? ? ? ? ? ? ? data:?{
? ? ? ? ? ? ? ? ? ? username:?'admin',
? ? ? ? ? ? ? ? ? ? password:?'admin'
? ? ? ? ? ? ? ? }
}).then(response=>?{
console.log(response);
?//響應(yīng)狀態(tài)碼
console.log(response.status);
?//響應(yīng)狀態(tài)字符串
console.log(response.statusText);
?//響應(yīng)頭信息
console.log(response.headers);
?//響應(yīng)體
console.log(response.data);
? ? ? ? ? ? })
4、fetchAJAX
(1)fetch定義
fetch是一個(gè)瀏覽器內(nèi)置的全新的請求API着憨。之前我們使用的jquery和axios的請求方法只是對XMLHttpRequest對象的封裝墩衙。
fetch()函數(shù)的第一個(gè)參數(shù)是url地址,第二個(gè)參數(shù)是配置對象甲抖。
(2)GET請求
GET請求的參數(shù)漆改,使用?直接拼接在url地址后面,如果有多個(gè)參數(shù)使用&符號准谚。
fetch(`http://localhost:5566/students?stuName=${stuName}`,{
method:'GET',//設(shè)置請求方式(默認(rèn)是GET)
}).then(response=>{
?// 第一個(gè)then挫剑,用于返回請求的狀態(tài)信息(檢查請求是否成功等等)
?// 再通過請求狀態(tài)對象的.json()方法,返回請求結(jié)果
returnresponse.json()
}).then(r?=>{
console.log(r)// 返回請求結(jié)果
?})
(3)POST請求
發(fā)送post請求時(shí)柱衔,請求參數(shù)如果是json字符串格式樊破,需要配置請求頭headers愉棱,設(shè)置Content-Type為'application/json'。
? ? ? ? ? ? let?params?= {
? ? ? ? ? ? ? ? name:name,
? ? ? ? ? ? ? ? hobbies:hobbies.split(','),
? ? ? ? ? ? }
? ? ? ? ? ? fetch(url,{
? ? ? ? ? ? ? ? method:'POST',
?//配置請求頭信息
? ? ? ? ? ? ? ? headers:{
? ? ? ? ? ? ? ? ? ? 'Content-Type':'application/json'
? ? ? ? ? ? ? ? },
body:JSON.stringify(params)// post請求參數(shù)
}).then(r=>{
returnr.json()
}).then(r=>{
console.log(r)// 返回請求結(jié)果
? ? ? ? ? ? })