NodeJS官網網址:https://nodejs.org/en/javascript
使用require方法加載fs核心模塊html
var fs = require('fs');
1、讀取文件
// 第一個參數就是堯讀取的文件路徑
// 第二個參數是一個回調函數
// error
// 若是讀取失敗,error就是錯誤對象
// 若是讀取成功,error就是null
// data
// 若是讀取成功,data就是讀取到的數據
// 若是讀取失敗,error就是錯誤對象 data就是undefinedjava
fs.readFile('hello1.txt',function(error,data){ if(error){ console.log('讀取信息失敗'); }else{ console.log(data.toString()); } })
//返回 <Buffer 68 65 6c 6c 6f>node
//第一個參數,文件路徑 //第二個參數,文件內容 //第三個參數,回調函數 // error形參 // 成功: // 文件寫入成功 error是null // 失敗: // 文件寫入失敗 error就是錯誤對象 fs.writeFile('waveHi.md','this is my first node.js',function(error){ if(error){ console.log('寫入失敗'); }else{ console.log('文件寫入成功'); } })
3、加載http核心模塊
jquery
var http = require('http'); // var http 變量名可自行隨意命名,可是require裏面的必須使用http 使用htp.createServer()方法建立一個web服務器 // 返回一個Server實例 var server = http.createServer(); // 當客戶請求過來,就會自動觸發服務器的request請求事件,而後執行第二個參數,回調處理函數 server.on('request',function(){ console.log('收到客戶端的請求了'); }) 綁定端口號,啓動服務器 server.listen(3000,function(){ console.log('服務器啓動成功了,能夠經過http://127.0.0.1:3000來訪問'); });
4、響應對象給客戶端發送響應消息web
server.on('request',function(request,response){ console.log('收到客戶端的請求了,請求路徑是' + request.url); //這裏能夠經過if條件句來判斷響應迴應的東西 //response對象有一個方法:write能夠用來給客戶端發送響應數據 //write能夠寫不少次,但最後必定要用end來結束,不然客戶端會一直等待 response.write('hello'); response.write(' nodejs'); //告訴客戶端,個人話說完了,能夠關閉了 response.end(); //因爲如今咱們的服務的能力還很是的弱,不管什麼請求都只能相應hello nodejs })
5、監聽request請求事件ajax
server.on('request',function(req,res){ console.log('收到請求,請求路徑是' + req.url); console.log("請求個人客戶端號是:",req.socket.remoteAddress,req.socket.remotePort); //根據不一樣的請求路徑發送不一樣的響應結果 //一、獲取請求路徑 // req.url獲取到的是端口號以後的那一部分路徑 // 也就是說全部的url都是以/開頭的 //二、判斷路徑處理響應 var url = req.url; if(url === '/products'){ var products = [ { name:'小米 X', price: 8888 },{ name:'華爲 X', price: 9999 },{ name:'vivo X', price: 6666 } ] res.end(JSON.stringify(products)); //將數組轉化爲字符串 }else{ res.end(1111); } //相應內容只能是二進制數據或者字符串 //數字、對象、數組、布爾值都不能夠 })
6、Content-type,提示系統輸入的內容類型mongodb
//在服務端默認發送的數據,實際上是utf8編碼的內容 //可是瀏覽器不知道你的內容是按照utf8編碼的 //瀏覽器在不知道服務器相應內容的編碼的狀況下會按照當前操做系統的默認編碼去解析 //中文操做系統默認是gbk //解決方法就是正確的告訴瀏覽器我給你發送的內容是什麼編碼類型的 //在http協議中,Content-Type就是用來告知對方我給你發送的數據內是什麼內容 server.on('request',function(req,res){ var url = req.url; if(url === '/plain'){ //text/plain就是普通文本 res.setHeader('Content-type','text/plain; charset=utf-8'); res.end('hello world 你好世界'); }else if(url === '/html'){ //若是你發送的是html格式的字符串,則也要告訴瀏覽器我給你發送的是text/html格式的內容 res.setHeader('Content-type','text/html; charset=utf-8'); res.end('<p>hello html<a>點我</a></p>') } })
不一樣的資源對應的Content-type是不同的,集體參照:http://tool.oschina.net/commonsexpress
*發送的並非文件,本質上來說發送的是文件的內容
*當瀏覽器收到服務器響應以後,就會根據你的Content-type進行對應的解析npm
server.on('request',function(req,res){ var url = req.url; if(url == '/'){ /*res.end('<!DOCTYPE html><html><head><title></title></head><body><h1>首頁</h1></body></html>')*/ fs.readFile('./resource/index.html',function(err,data){ if(err){ res.setHeader('Content-type','text/plain;charset=utf-8') res.end('文件讀取失敗,請稍後重試!'); }else{ res.setHeader('Content-type','text/html;charset=utf-8') res.end(data); } }) }else if(url === '/a.jpg'){ fs.readFile('./resource/a.jpg',function(err,data){ if(err){ res.setHeader('Content-type','text/plain;charset=utf-8') res.end('文件讀取失敗,請稍後重試!'); }else{ //data默認是二進制數據,能夠經過.toString()轉爲咱們能識別的字符串 //res.end()支持兩種數據類型,一種是二進制,一種是字符串 //圖片就不須要制定編碼了,由於咱們常說的編碼通常指的是:字符編碼 res.setHeader('Content-type','image/jpeg;charset=utf-8') res.end(data); } }) } })
圖片不須要指定編碼
通常字符數據才制定編碼
7、關於 art-template 的使用基礎
//1.安裝 npm install art-template //2.在須要使用的文件模塊中加載art-template // 只須要使用require方法加載就能夠了,require('art-template') //3.查文檔,使用模板引擎的API var fs = require('fs'); var tplStar = `<!DOCTYPE html> <html> <head> <title></title> </head> <body> 你們好 我叫{{ name }} 今年 {{ age }} 歲 來自 {{ province }} 喜歡:{{ each hobbies }} {{ $value }} {{/each}} </body> </html>`; var template = require('art-template'); fs.readFile('./tpl.html', function (err, data) { if(err) { return console.log('讀取文件失敗了') } //默認讀取到的data是二進制數據 //而模板引擎的render方法須要接受的是字符串 //因此咱們在這裏須要把data二進制數據轉爲 字符串 才能夠給模板引擎使用 var ret = template.render(data.toString(), { name: 'jack', age: 18, province: '北京市', hobbies: [ '寫代碼', '唱歌', '看書' ], title:'我的信息' }) console.log(ret); })
在瀏覽器中使用 art-template
<!DOCTYPE html> <html> <head> <title></title> </head> <body> <!-- 注意:在瀏覽器中須要引用 lib/template-web.js文件 強調:模板引擎不關心你的字符串內容,只關心本身能認識的模板標記語法,例如{{}}, {{}}語法被稱之爲mustache語法 --> <script src="node_modules/art-template/lib/template-web.js"></script> <script type="text/template" id="tpl"> <!DOCTYPE html> <html> <head> <title></title> </head> <body> 你們好 我叫{{ name }} 今年 {{ age }} 歲 來自 {{ province }} 喜歡:{{ each hobbies }} {{ $value }} {{/each}} </body> </html> </script> <script> var ret = template('tpl', { name: 'jack', age: 18, province: '北京市', hobbies: [ '寫代碼', '唱歌', '看書' ] }) console.log(ret); </script> </body> </html>
8、node中模塊系統
var foo = 'bar'; function add(x, y) { return x + y; } //模塊須要直接導出某個成員, 而非掛載的方式 //這個時候必須使用下面這種方式 //module.exports = add; module.exports = { add: function (x, y) { return x + y; }, str: 'hello' }
// exports 是一個對象
//能夠經過屢次爲這個變量添加新成員實現對外導出多個內部成員
能夠經過如下方式調用
var fooExports = require('./foo') console.log(fooExports);
在 Node 中,每一個模塊內部都一個有本身的module
該 module 對象中,有一個成員叫:exports
Node 爲了簡化操做, 專門提供一個exports = module.exports
給 exports 賦值會斷開和 module.exports之間的聯繫
exports.foo = 'bar';//{foo: bar} module.exports.a = 123;//{foo: bar, a:123} exports = { a: 456 } //此時 exports != module,exports // 最終 return 的是 module.exports // 不管是exports的什麼成員都沒有用 module.exports.foo = 'haha' //{foo: haha, a:123} exports.c = 456 // 已經無關,不能混淆 exports = module.exports; // 從新創建了和module.exports 之間的引用關係 // 下面語句生效 exports.a = 789; // 前面不管寫的什麼,這裏所有推翻,從新賦值 // 最終獲得的是function module.exports = function () { console.log('hello'); } // 真正去使用的時候: // 導出多個成員:exports.xxx = xxx // 導出多個成員也能夠: module.exports = { // } // 導出單個成員:module.exports = xxx
9、require 優先從緩存加載
10、遍歷
art-template中的 each,JQuery中的forEach的用法
+ art-template(模板引擎)和JQuery(加強DOM操做的庫)沒有任何關係
* each 是 art-template 的模板語法,專屬的
{{each 數組}}
<li>{{ $value}}</li>
{{/each}} 這是art-template 模板引擎支持的語法, 只能在模板字符串中使用
each 在JQuery中的應用
$.each(數組, function)或者
$('div').each(function) 通常用於 Jquery 選擇器選擇到的僞數組實例對象
forEach 是EcmaScript 5 中的一個數組遍歷函數,是 javaScript 生支持的遍歷方法,可以遍歷任何能夠被遍歷的成員
forEach
<!DOCTYPE html> <html> <head> <title></title> </head> <body> <div></div> <div></div> <div></div> <div></div> <div></div> <script src="node_modules/jquery/dist/jquery.js"></script> <script type="text/javascript"> /*;['a', 'b', 'c'].forEach(function (item, index) { console.log(item); })*/ // 遍歷 JQuery 元素 /*$.each(['a','bb','c'], function (index, item) { console.log(item); })*/ console.log($('div')); //僞數組是對象 //對象的原型鏈中沒有 forEach //對象的原型鏈是 Object.prototype //這個 each 是 JQuery 提供的 // 這個 each 在 JQuery 的原型鏈中 /*$("div").each(function (index, item) { console.log(item); })*/ // JQuery 不是專門用來遍歷 JQuery 元素的 // 1.方便的遍歷JQuery元素 // 2.能夠在不兼容forEach的低版本瀏覽器中使用 Jquery 的 each方法 [].slice.call($('div')).forEach(function (item) {console.log(item);}) </script> </body> </html>
11、Express
原生的http在某些方面表現不足以應對咱們的開發需求,因此咱們就須要使用框架來加快咱們的開發效率,讓咱們的代碼高度統一。
在 Node中,有不少 Web 開發框架,咱們這裏以學習 express爲主。
官方網址:http://expressjs.com/
安裝:
//cmd命令行輸入 npm install --save express
引用:
var express = require('express') var app = express()
調用靜態資源:
app.use('/node_modules', express.static('./node_modules'))
app.use('/public', express.static('./public'))
12、頁面跳轉渲染
* 職責:
* 建立服務
* 作一些服務相關配置
* 模板引擎
* body-parser 解析表單 post 請求體
* 提供靜態資源
* 掛載路由
* 監聽端口啓動服務
var fs = require('fs') var Student = require('./student') 專門用來包裝路由的 var express = require('express') // 1. 建立一個路由器 var router = express.Router() // 2. 把路由器掛載到 router路由器中 router.get('/students', function (req, res) { // readFile 的第二個參數仍是可選的,傳入 utf-8 是告訴他把讀取的文件直接按照utf-8編碼 /*fs.readFile('./db.json','utf8', function (err, data) { if(err) { return res.status(500).send('Server error.') } //文件中讀取到的數據必定是字符串,因此必定要手動轉成對象纔可使用 res.render('index.html', { fruits: [ '蘋果', '香蕉', '橘子' ], students: JSON.parse(data).students }) })*/ Student.find(function (err, students) { if(err) { return res.status(500).send('Server error.') } res.render('index.html', { fruits: [ '蘋果', '香蕉', '橘子' ], students: students }) }) }) router.get('/students/new', function (req, res) { res.render('new.html') }) router.post('/students/new', function (req, res) { // 1. 獲取表單數據 // 2. 處理 // 將數據保存到 db.json文件中用以持久化 // 3. 發送響應 //先讀取出來,轉成對象 //而後往對象中 push 數據 //而後把對象轉爲字符串 // 而後把字符串再次寫入文件 Student.save(req.body, function (err) { if(err) { return res.status(500).send('Server error.') } res.redirect('/students') }) }) router.get('/students/edit', function (req, res) { // 1.在客戶端的列表中處理鏈接問題(須要有 id 參數) // 2,獲取要編輯的學生id // 3.渲染編輯頁面 Student.findById(parseInt(req.query.id), function (err, student) { if(err) { return res.status(500).send('Server error.') } console.log(student) res.render('edit.html', { student: student }) }) //console.log(req.query.id) }) router.post('/students/edit', function (req, res) { // 1. 獲取表單數據 // req.body // 2. 更新 // Student.updateById() // 3. 發送響應 Student.updateById(req.body,function (err) { if (err) { return res.status(500).send('Server error') } res.redirect('/students') }) }) router.get('/students/delete', function (req, res) { // 1. 獲取要刪除的 id // 2. 根據 id 執行刪除操做 // 3. 根據操做結果發送響應數據 Student.deleteById(req.query.id, function (err){ if(err) { return res.status(500).send('Server eror.') } res.redirect('/students') }) }) // 3. 把router 導出 module.exports = router
封裝異步API
var fs = require('fs') var dbPath = './db.json' exports.find = function (callback) { fs.readFile(dbPath,'utf8', function (err, data) { if (err) { return callback(err) } callback(null, JSON.parse(data).students) }) } /** * 根據 id 獲取學生信息對象 * @param {Number} id 學生 id * @param {function} callback 回調函數 */ exports.findById = function (id, callback) { fs.readFile(dbPath,'utf8', function (err, data) { if (err) { return callback(err) } var students = JSON.parse(data).students var ret = students.find(function (item) { return item.id === parseInt(id) }) callback(null, ret) }) } /** * 添加保存學生 */ exports.save = function (student, callback) { fs.readFile(dbPath,'utf8', function (err, data) { if (err) { return callback(err) } var students = JSON.parse(data).students // 處理id惟一的不重複 student.id = students[students.length - 1].id + 1 //把用戶傳遞的對象保存到數組中 students.push(student) // 把對象數據轉換爲字符串 var fileData = JSON.stringify({ students: students }) // 把字符串保存在文件中 fs.writeFile(dbPath, fileData, function (err) { if(err) { return callback(err) } callback(null) }) }) } /** 更新學生 */ exports.updateById = function (student, callback) { fs.readFile(dbPath,'utf8', function (err, data) { if (err) { return callback(err) } var students = JSON.parse(data).students //注意:這裏記得把 id 統一轉換爲數字類型 student.id = parseInt(student.id) //你要修改誰,就須要把誰找出來 //EcmaScript 6 中的一個數組方法:find // 須要接收一個函數做爲參數 // 當某個遍歷項符合 item.id === student.id 條件的時候,find 會終止遍歷,同時返回遍歷項 var stu = students.find(function (item) { return item.id === student.id }) for(var key in student) { stu[key] = student[key] } // 把對象數據轉換爲字符串 var fileData = JSON.stringify({ students: students }) // 把字符串保存在文件中 fs.writeFile(dbPath, fileData, function (err) { if(err) { return callback(err) } callback(null) }) }) } /** * 刪除學生 */ exports.deleteById = function (id, callback) { fs.readFile(dbPath, 'utf8', function (err, data) { if (err) { return callback(err) } var students = JSON.parse(data).students // findIndex 方法專門用來根據條件查找元素下標 var deleteId = students.findIndex(function (item) { return item.id === parseInt(id) }) // 根據下標從數組中刪除對應的學生對象 students.splice(deleteId, 1) // 把對象數據轉換爲字符串 var fileData = JSON.stringify({ students: students }) // 把字符串保存在文件中 fs.writeFile(dbPath, fileData, function (err) { if(err) { return callback(err) } callback(null) }) }) }
封裝 ajax 的方法:
//setTimeout //readFile //writeFile //readdir //ajax // 每每異步API 都伴隨着一個回調函數 function get (url, callback) { var oReq = new XMLHttpRequest() // 當請求加載成功以後要調用指定的函數 oReq.onload = function () { callback(oReq.responseText) } oReq.open("get", url, true) oReq.send() } get('db.json', function (data) { console.log(data) })
find 和 findIndex
// EcmaScript 6 對數組新增了不少方法 // find // findIndex // find 接受一個方法做爲參數,方法內部返回一個條件 // find 會便利全部元素,執行你給定的帶有條件返回值的函數 // 符合該條件的元素會做爲 find 方法的返回值 // 若是遍歷結束尚未符合 該條件的元素則返回undefined、 var users = [ {id: 1, name: '張三'}, {id: 2, name: '張三'}, {id: 3, name: '張三'}, {id: 4, name: '張三'} ] Array.prototype.myFind = function (conditionFunc) { for (var i = 0; i < this.length; i++) { if (conditionFunc(this[i], i)) { return this[i] } } } var ret = users.myFind(function (item, index) { return item.id === 4 }) console.log(ret)
十3、封裝promise API
var fs = require('fs'); function pReadFile(filePath) { return new Promise(function (resolve, reject) { fs.readFile(filePath, 'utf8', function (err, data) { if (err) { reject(err) } else { resolve(data) } }) }) } pReadFile('./data/a.txt') .then(function (data) { console.log(data) return pReadFile('./data/b.txt') }, function (err) { console.log('讀取文件失敗了', err) }) .then(function (data) { console.log(data) return pReadFile('./data/c.txt') }, function (err) { console.log('讀取文件失敗了', err) }) .then(function (data) { console.log(data) }, function (err) { console.log('讀取文件失敗了', err) })
mongoose 全部API都支持promise
var mongoose = require('mongoose') var Schema = mongoose.Schema mongoose.connect('mongodb://localhost/test', {useNewUrlParser: true}) var userSchema = new Schema({ username: { type: String, required: true // 必須有 }, password: { type: String, required: true }, email: { type: String } }) var User = mongoose.model('User', userSchema) User.find() .then(function (data) { console.log(data) }) User.findOne({ username: 'Leslie' }) .then(function (user) { if (user) { console.log('用戶已存在') } else { return new User({ username: 'Leslie', password: '123', email: 'dewfvr' }).save() } }).then(function (ret) { })