不會就問就查詢!科技利民,學海無涯2!
一、概念
二、組成部分
1、瀏覽器中JavaScript:
2、Node.js中JavaScript:
三、特點
四、用途
五、主要知識點
六、安裝使用
node --version/node -v
;node aa.js
node.js
var fs = require('fs')
fs.readFile('檔案路徑',回撥函數function(error,data){ if(error){ console.log('友好地提示:讀取失敗') } else{ console.log(data)} })
,
toString()
;fs.readFile('./hello.txt',function(error,data){ console.log(data.toString())})
fs.writeFile('檔案路徑',‘檔案內容’,回撥函數function(error){})
on
方法的回撥函數中;req.url
res.write([響應內容]);res.end();
res.end([響應內容]);
JSON.stringify();
轉成json字串(序列化:用於傳輸);var http = require('http')
var server = http.createServer()//返回一個範例
server.on('request',function(request,response){
console.log('當前存取的路徑是'+ request.url)
//這行程式碼時展示在伺服器上的;url是埠號後面的部分,預設`/`根路徑
var url = req.url;
if(url == '/'){
response.end('hello 首頁');//中文會有亂碼,要設定響應內容型別
}
else{
response.setHeader('Content-Type','text/plain;charset=utf-8');
//告訴瀏覽器響應數據型別爲普通文字,字元編碼格式是utf-8;
response.write('hello 其他');
//中文會有亂碼,要設定響應內容型別
response.end();
}
//響應到用戶端頁面中,end()方法表示響應結束,否則瀏覽器一直等待。
})
//監聽用戶端開啓網址,伺服器收到請求時回撥
server.listen(3000,function(){
console.log('伺服器啓動成功了,可以通過 http://127.0.0.1:3000/ 來進行存取!')
})
//當服務啓動後回撥,80埠時用戶端不需要輸埠;
七、Node中的JavaScript
var [模組名] = require('[模組名]')
;
fs,http,os,path,
Express
web開發框架,需要下載參照;exports
物件導出內部變數、方法;.js
;但必須寫相對路徑./,../
,否則會被認爲是核心模組,報錯!八、伺服器端的ip與埠號
九、響應內容型別
問題原因:
伺服器預設發送的json字串數據(讀取檔案時檔案內容編碼成的二進制所採用的規則由檔案建立時的編碼環境決定,一般用開發工具建立的檔案都是utf-8)就是utf-8
編碼,但是瀏覽器預設不知道是什麼編碼,會按當前操作系統預設的編碼格式,如:中文操作系統的預設編碼規則:GBK
,兩者規則不同導致中文亂碼。
(對於直接傳二進制數據流時,因爲不同編碼規則對數位、字母的編碼都一樣,在通過二進制解碼html檔案前部分字母是都很正常,中文操作系統用GBK
正常解碼二進制數據,識別看到meta
便知道用UTF-8
,所以在傳html檔案時要宣告型別和編碼規則,元數據meta
中定義的編碼格式等同於在伺服器端響應編碼格式)
解決方案:
宣告響應數據的型別(普通文字text/plain
、html程式碼text/html
等),並告訴瀏覽器編碼格式charset=utf-8
;
不管以字串形式還是二進制傳的都可以視情況需要在伺服器設定響應數據型別:提供數據型別和編碼格式給瀏覽器
發送的數據與對應響應型別:
Content-Type 對照表
- 圖片需要指定響應型別,但不需要指定編碼格式;
- 一般只爲字元數據(中文、字母、數位、符號等)指定編碼格式
utf-8
;
如:res.setHeader('Content-Type','text/plain;charset = utf-8')
如:res.setHeader('Content-Type','text/html;charset = utf-8')
- 特別地:對於響應讀取html檔案的內容時,可以不寫上述宣告是因爲瀏覽器自動識別html程式碼,並且html程式碼中
meta元數據
也可以宣告編碼格式。
十、程式碼書寫風格與分號的使用
常見程式碼書寫風格規範:
一般推薦不加分號,必須加分號的情況:
``
開頭的程式碼前加;
()
開頭的程式碼前加;()
[]
開頭的程式碼前加;[]
十一、node.js實現 Apache功能
1、實現瀏覽器輸入域名+埠號/檔名,就顯示伺服器上指定檔案對應的內容;
if語句
判斷使用者輸入的路徑;fs
模組,針對不同路徑找到對應檔案並讀取內容(可以直接響應,因爲fs.readFile()
預設返回的data
就是二進制(以十六進制顯示),如果要對data
進行處理可以toString()
轉爲字串);2、實現在瀏覽器顯示檔案目錄功能;
http
核心模組建立服務;fs.readdir(path[, options], callback)
核心模組讀取檔案目錄資訊,返回陣列形式,用於模板引擎替換目錄數據;{{each [陣列名]}} <p>陣列中的{{$value}}</p> {{/each}}
,遍歷陣列中每一項從而生產每一項fs.readFile(path[, options], callback)
核心模組讀取用於目錄顯示的html模板檔案並結合模板引擎如:art-template
第三方模組替換目錄內容(所以要data.toString()
將二進制先轉爲字串,當做替換模板使用);res.end(newData)
,實現在瀏覽器顯示目錄、點選目錄。補充:第三方
art-template
模板引擎規則是識別字串內{{}}
中的變數名;(可在前端html頁面中使用,也可以在後端node中安裝使用)
補充:在Node
中使用方式:
var template = require('art-tmplate')
var ret = template.render(data.toString(),{name:'jack'})
//改後的新字串
十二、用戶端渲染與伺服器端渲染
ajax等非同步操作請求數據
,速度更快;但不利於SEO,爬蟲抓不到非同步數據(在原始碼中看不到數據:如京東商品的評論區分頁功能);十三、伺服器對靜態資源的處理
背景:
當我們在html頁面中使用link、script、img、iframe、video、audio
等需要再次發請求引入靜態資源的標籤時,其實就是自動又向伺服器發了一次請求(請求路徑分爲:網路路徑、url檔案路徑會拼接在伺服器地址後面;),所以伺服器端也會對這些請求做響應。(如果沒有響應,瀏覽器就會一直處於等待狀態,沒法渲染頁面)
處理方式:
伺服器將靜態資源統一放到一個資料夾public
中,然後在html頁面中通過檔案路徑參照,這樣可以通過req.url
判斷只要是以/public/
開頭的就直接把這個url
當做檔案路徑去找這個檔案,然後響應回去;所以html頁面中使用的路徑要是檔案路徑。
十四、伺服器對錶單提交的處理
req.url
返回的是整個根目錄及以後的部分;包含了路徑和query
資訊;get
請求時,伺服器要想得到query
數據,單從req.url
中不容易獲取,所以有了專門處理路徑的核心模組:var url = require('url')
;parse
方法可以得到一個路徑物件;var pathObj = url.parse(req.url,true)
;第二個參數用於將query
的屬性值以物件形式呈現,預設是字串,這裏會涉及編碼格式;pathObj.pathname
路徑字串來決定響應內容;pathObj.query
物件;302狀態碼
(臨時重定向,再次發請求,瀏覽器不記住重定向後的地址,相當於每次都是第一次,還是會向原網址發請求),瀏覽器收到這個狀態碼,就直接去響應頭中找Location
;在響應頭中設定Location
告訴瀏覽器重定向的路徑;res.statusCode = 302 res.setHeader('Location','/') res.end()
十四、Node.js的測試方法
F12
偵錯工具>node
命令列直接輸命令,可以直接用node中API,按ctrl+c+c
退出。十五、Node.js的模組系統
模組分類:
- 核心模組
- 第三方模組
- 自定義模組
1、Node.js中的模組化基於Commen.JS;
module.exports
物件;內部預設var module.exports={}; var exports = module.exports; return module.exports
module.exports=
;導出多個用:exports.屬性名=
或module.exports={}
2、require載入規則
module.exports
;require('fs')
:引入核心模組require('./aa.js')
:引入自定義模組(路徑方式)require('art-template')
:引入第三方模組node_module
檔案下的同名檔案中找package.json
中的main
屬性對應的值,如index.js
,然後去這個檔案並執行;如果main
沒有,那預設找index.js
;本資料夾沒有則往外找package.json、index.js
,直到找到根目錄。3、package.json
會自動記錄同檔案中npm下載時帶--save、--save-dev
的第三方模組;不帶不記錄;
4、使用npm init
會自動生成package.json
檔案;
5、使用npm install
會自動根據package.json
中記錄下載包;用於拷貝專案時下載包。
6、npm命令
7、解決npm被牆問題(國外網站存取慢):
nrm
源管理器;可以用npm
命令,但是源變了;npm install --global cnpm
;這是可以用新源:cnpm init
;cnpm
是淘寶映象,每10分鐘從npm中更新一次包數據。npm config list
檢視:npm config set registry https://registry.npm.taobao.org
;這樣還是npm命令,源變了;十六、Node.js的第三方模組 :Express
1、輕便的web伺服器開發框架;(封裝的http
核心模組)
2、安裝npm install express --save
3、存取路徑:
app.use('/public/',express.static('./public/'))
;使用者可以輸入以/public/
開頭的路徑;app.get('/',function(req,res){})
;使用者存取根目錄時的情況;express
內部的設定方案時:返回404
頁面。4、在express中的res
響應方法會自動結束,不用res.end()
十七、Node.js的路徑問題
1、fs
檔案操作中檔案路徑的相對路徑中./
可以省略;
2、require
模組載入時的相對路徑中./
不能省,省略就是載入核心模組/第三方模組;
3、相對路徑含義:
./aa.js
:當前目錄中的aa.js
/aa.js
:當前磁碟根目錄中../aa.js
:上一級目錄中c:/aa.js
:C槽根目錄中十八、Node.js的服務自動重新啓動
nodemon
:用於修改程式碼儲存後自動重新啓動伺服器;
node install --global nodemom
nodemon aa.js
十九、express的靜態資源服務
1、通過路由匹配存取指定資源:app.get('/',function(req,res){})、app.post('/',function(req,res){})
2、通過公開指定目錄存取目錄內檔案:
app.use('/public/',express.static('./public/'))
:以/public/
爲根目錄開頭的路徑,後面的部分會去相應檔案中找,並以正確編碼顯示;app.use(express.static('./public/'))
:只要路由中沒有定義的,會直接擷取根目錄/
後面部分,去./public/
資料夾內部中找,找到就顯示;3、使用模板引擎模組art-template
npm install --save art-template express-art-template
.art
結尾的檔案,並使用模板引擎;可以在app.engine
中更改設定;
app.engine('art',require('express-art-template'))
//可改後綴名views
資料夾中查詢這個模板檔案(res.render('index.art')
不傳物件參數就是直接傳頁面資訊);
app.get('/',function(req,res) { res.render('index.art',{ user:{ name:'aaa' } }) })
//自動結束響應res.redirect('/')
4、獲取請求數據
req.query
//就是物件形式body-parser
,,res.body
也是物件形式;二十、使用express實現增刪改查數據(Create Update Read Delete )
1、CURD起步
npm init
,初始化package.json
express、art-template、express-art-template
2、以.json
檔案爲數據儲存方式,對檔案數據進行CURD
fs
核心模組,讀取檔案數據;toString()
轉爲json字串(或者fs.readFile('./aa.json','utf8',function(err,data){})
);JSON.parse(data)
轉爲json物件;JSON.parse(data).students
,用來做模板引擎數據;3、設定伺服器端路由:router.js
var router = express.Router()
–router.jsapp.use(router)
–app.js4、建立操作頁面
5、封裝對學生數據的操作:students.js
利用ID獲取數據和儲存編輯時注意:
- 通過
req.query、req.body
獲取的提交數據是物件形式,但物件中屬性值都是字串型別(所以id屬性也是),需要轉變student.id = parseInt(student.id)
;- 通過
JSON.parse(data)
將json檔案中字串轉爲物件形式時,內部屬性值原本是什麼型別還不變;刪除前彈框確認:node環境中沒有confirm,所以在模板頁面中判斷;
<a href="/students/delete?id={{$value.id}}" onclick="if(confirm('確定刪除?')==false)return false;">刪除</a>
編輯頁面男女性別選中的判斷:
<script>
window.onload = function () {
if ("{{student.gender}}" == 0) {//express-art-template模組的語法
document.getElementsByName('gender')[0].checked = 'checked';
} else {
document.getElementsByName('gender')[1].checked = 'checked';
}
}
</script>
6、es6方法
Array.prototype.find = function(Func){
for(var i = 0;i<this.length;i++){
if(Func(this[i],i)){
return this[i]//i;返回‘i’,就是findIndex方法
}
}
}
var id = '1'
var stu = students.find(function(item,index){
return item.id == parseInt(id)
})
var id = 1
var delId = students.findIndex(function(item,index){
return item.id == parseInt(id)
})
7、非同步程式設計–回撥函數
用於得到一個函數內部非同步操作的結果,在非同步函數內部呼叫執行;
正常函數
–>傳參數:
–>正常函數中使用非同步操作
–>在非同步操作中呼叫這個回撥函數
–>並將非同步操作的值傳給這個回撥函數作參數
;function add(x,y,callback){
//var x = 10
//var y = 20
//var callback = function(sum){...}
setTimout(function(){
var sum = x+y
callback(sum)
},1000)
}
add(10,20,function(sum){
return sum
})//30,函數內部執行function
二十一、JavaScript模組化及其他補充
npm init
時會自動生成package.json
,當下載包時,會自動生成package-lock.json
檔案,記錄下載包以其依賴包的資訊(真正版本號、下載地址等),這樣當拷貝專案時npm install
時就會參考這個檔案;
二十二、MongoDB數據庫
MongoDB 是一個基於分佈式檔案儲存的數據庫。由 C++ 語言編寫。旨在爲 WEB 應用提供可延伸的高效能數據儲存解決方案。
MongoDB 是一個介於關係數據庫和非關係數據庫之間的產品,是非關係數據庫當中功能最豐富,最像關係數據庫的。
1、(NoSQL)MongoDB 是一個面向文件儲存的數據庫,操作起來比較簡單和容易。
2、下載、安裝、設定環境變數:bin檔案目錄(用於全域性使用)
navicat
數據庫管理工具;Navicat
也支援mongodb數據庫了:Navicat for MongoDB
;3、檢查安裝是否成功:mongod --version
4、基本使用:
手動建立數據儲存目錄:在某盤根目錄下建立:D:\data\db
修改數據庫儲存目錄:mongod --dbpath=數據庫儲存目錄路徑
//mongod --dbpath=D:\Mongodb\4.0\data
;修改前關閉本地MongoDB服務;
開啓數據庫服務命令:> mongod
關閉數據庫:ctrl+c
連線數據庫:mongo
關閉連線:exit
檢視所有數據庫:show dbs
;預設由系統數據庫
檢視當前數據庫:db
;預設有個test
數據庫,只有新增數據後才能 纔能在檢視所有數據庫時看到;
切換至指定數據庫,沒有就建立:use [數據庫名稱]
;也是新增數據後才能 纔能用show dbs
看到;
建立一條數據:db.stu.insertOne({"name":"Jack"})
檢視當前數據庫中集合:show collections
//stu,類似陣列
檢視集閤中數據:db.stu.find() //{"_id":ObjectId("[自動生成]"),"name":"Jack"}