~~~
//當前項目(包)的入口文件
//實現get方式添加新聞
//實現顯示新聞詳情頁
//1.加載http模塊
var http = require('http');
var fs = require('fs');
var path = require('path');
var mime = require('mime');
//加載url模塊
var url = require('url');
//加載underscore
var _ = require('underscore');
//加載querystring模塊
var querystring = require('querystring');
//2.創建http服務
http.createServer(function(req, res) {
//為res對象添加一個render()函數,方便后續使用
//第二個參數tplData的作用是用來傳遞html頁面中要使用的模板數據
res.render = function(filename, tplData) {
fs.readFile(filename, function(err, data) {
if (err) {
res.writeHead(404, 'Not Found', { 'Content-Type': 'text/html;charset=utf-8' });
res.end("404,page not found.");
return;
}
if (tplData) {
//如果用戶傳遞了模版數據,表示要進行模板替換
var fn = _.template(data.toString('utf8'));
data = fn(tplData);
}
res.setHeader("Content-Type", mime.getType(filename));
res.end(data);
})
}
//設計路由
//當用戶請求 / 或者 /index的時候,顯示新聞列表---get請求
//當用戶請求 /item的時候,顯示新聞詳情---get請求
//當用戶請求 /submit的時候,顯示添加新聞頁面---get請求
//當用戶請求 /add時,將用戶提交的新聞保存到data.json文件中---get請求
//當用戶請求 /add時,將用戶提交的新聞保存到data.json文件中---post請求
//將用戶請求的url和method轉換為小寫字母
req.url = req.url.toLowerCase();
req.method = req.method.toLowerCase();
//通過url模塊,調用url.parse()方法解析用戶請求的url(req.url)
var urlObj = url.parse(req.url, true);
//根據用戶請求的路徑,將對應的html頁面顯示出來
if (req.url === '/' || req.url === '/index' && req.method === 'get') {
//1.讀取data.json文件中的數據,并將讀取到的數據轉換為arr 數組
fs.readFile(path.join(__dirname, "data", 'data.json'), 'utf8', function(err, data) {
if (err && err.code !== 'ENOENT') {
throw err;
}
var arr_news = JSON.parse(data || '[]'); //字符串解析為數組
//讀取index.html 并返回
//2.在服務器端使用模板引擎,將arr中的數據和index.html文件中的內容結合,渲染給客戶端
res.render(path.join(__dirname, 'views', 'index.html'), { arr: arr_news });
});
} else if (urlObj.pathname === '/item' && req.method === 'get') {
//讀取detail.html并返回
//1.獲取當前用戶請求的新聞的id
//urlObj.query.id
//2.讀取 data.json文件中的數據,根據 id 找到對應新聞
fs.readFile(path.join(__dirname, "data", 'data.json'), 'utf8', function(err, data) {
if (err && err.code !== 'ENOENT') {
throw err;
}
var list_news = JSON.parse(data || '[]');
var model = null;
//循環 list_news中的數據,找到和id值相等的數據
for (var i = 0; i < list_news.length; i++) {
//判斷集合中是否有與用戶提交的id相等的新聞
if (list_news[i].id.toString() === urlObj.query.id) {
//如果找到了對等的新聞 則將其記錄下來
model = list_news[i];
break;
}
}
if (model) {
res.render(path.join(__dirname, 'views', 'detail.html'), { item: model });
} else {
res.end("NO such item");
}
})
} else if (req.url === '/submit' && req.method === 'get') {
//讀取submit.html并返回
res.render(path.join(__dirname, 'views', 'submit.html'));
} else if (req.url.startsWith('/add') && req.method === 'get') {
//表示get方法提交一條新聞
//要獲取用戶提交過來的數據,需要用到url模塊(這個模塊是node.js內置模塊,不是第三方模塊)
//1.獲取用戶get提交過來的新聞數據
//urlObj.query.title
//urlObj.query.url
//urlObj.query.text
//2.1讀取 data.json文件中的數據,并將讀取到的數據轉化為一個數組
//此處讀取文件的時候可以直接寫一個utf8編碼,這樣的話,回調函數中的data就是一個字符串了
fs.readFile(path.join(__dirname, "data", 'data.json'), 'utf8', function(err, data) {
//因為第一次訪問網站 ,data.json文件本身就不存在,所以肯定是有錯誤的,但是這種錯誤,我們并不認為是網站出錯了,所以不需要拋出異常
//ENOENT沒有這樣的文件或者目錄
if (err && err.code !== 'ENOENT') {
throw err;
}
//如果讀取到了數據,就把讀取到的數據data轉換成arr數組,相反如果沒有讀取到數據就把[]轉換為數組
var arr = JSON.parse(data || '[]'); //字符串解析為數組
//在把新聞添加到list之前,為新聞添加一個id屬性
urlObj.query.id = arr.length;
arr.push(urlObj.query);
//2.把用戶提交的數據保存到data.json文件中
//把arr數組中的數據寫入到data.json文件中
fs.writeFile(path.join(__dirname, 'data', 'data.json'), JSON.stringify(arr), function(err) {
if (err) {
throw err;
}
console.log('ok');
//3.跳轉到新聞列表頁
//通過設置http響應報文頭實現瀏覽器重定向操作
//以3開頭的都表示要做跳轉
res.writeHead(302, 'Found', { 'Location': '/' })
res.end();
});
});
} else if (req.url === '/add' && req.method === 'post') {
//表示post方法提交一條新聞
//1.讀取data.json文件中的數據
fs.readFile(path.join(__dirname, 'data', 'data.json'), 'utf8', function(err, data) {
if (err && err.code !== "ENOENT") {
throw err;
}
var arr = JSON.parse(data || '[]');
//2.獲取用戶 post 提交的數據
//post提交數據的時候數據量比較大,所以會分多次提交,每次提交一部分數據,此時要想在服務器中獲取用戶提交的所有數據,必須監聽request事件的data事件
//當request對象的end事件被觸發的時候表示瀏覽器把所有的數據都提交到服務器了
//監聽request的對象的data事件和end事件代碼如下:
//聲明一個數組,用來保存用戶每次提交過來的數據
var list = [];
req.on('data', function(chunk) {
//此處的 春款參數,就是瀏覽器本次提交過來的一部分數據
//chunk的數據類型是buffer
list.push(chunk);
});
req.on('end', function() {
//在這個事件中只要把array中的所有數據匯總起來就好了
//把list的每個buffer對象,集合起來轉換為一個buffer對象
//title=vvvvv&url=http%3A%2F%2Flocalhost%3A8888%2Fsubmit&text=vvvvvvvvvvvv
var postBody = Buffer.concat(list);
postBody = postBody.toString('utf8'); //buffer對象轉化為字符串
//把post請求的查詢字符串,轉換為一個json對象
postBody = querystring.parse(postBody);
//console.log(postBody);
//在把新聞添加到list之前,為新聞添加一個id屬性
postBody.id = arr.length;
//將用戶提交的新聞push到arr數組中
arr.push(postBody);
//將新的arr數組,在寫入到data.json文件中
fs.writeFile(path.join(__dirname, 'data', 'data.json'), JSON.stringify(arr), function(err) {
if (err) {
throw err;
}
console.log('ok');
//3.跳轉到新聞列表頁
res.writeHead(302, 'Found', { 'Location': '/' })
res.end();
});
});
});
//2.將讀取到的數據轉化為arr數組
//3.向arr數組中push一條新聞數據
//4.把arr數組轉換為字符串重新寫入data.json文件中
//5.重定向
} else if (req.url.startsWith('/resources') && req.method === 'get') {
//如果用戶請求是以/resources開頭,并且是get請求,就認為用戶是要請求靜態資源
res.render(path.join(__dirname, req.url));
} else {
res.writeHead(404, 'Not Found', {
'Content-Type': 'text/html;charset=utf-8'
});
res.end("404,page not found.");
}
}).listen(8888, function() {
console.log("http://localhost:8888");
})
~~~
首頁的id

詳情頁里的模板

具體設計代碼:

- node.js
- 第一章 node.js介紹
- 第二章 node.js安裝和配置
- 第三章 node.js開發網站和傳統php等開發網站的區別
- 第四章 REPL介紹
- 第五章 創建javascript文件編寫程序
- 第六章 寫入文件操作
- 第七章 異步操作
- 1.try-catch
- 第八章 讀取文件
- 第九章 __dirname和__filename獲取正在執行的js文件的路徑
- 第十章 通過path模塊進行路徑拼接
- 10.1 作業:創建文件夾
- 第十一章 編寫http服務程序
- 1.通過服務器端設置響應報文頭解決亂碼問題
- 2.通過設置http響應報文頭來解決瀏覽器顯示html問題
- 3.根據不同請求做出不同響應
- 4.根據用戶不同請求-讀取不同的html文件響應
- 5.根據用戶不同請求,返回不同html文件(帶圖片)
- 6.根據用戶不同請求,返回不同html文件(帶css)
- 7.模擬apache
- 第十二章 請求url就是一個標示符
- 第十三章 request和response對象介紹
- 13-1 request對象
- 13-2 response對象
- 第十四章 npm介紹
- node.js進階
- 1.Modules和Packages區別
- 2.package.json文件介紹
- 3.package-lock.json文件介紹
- 4.HackerNews項目
- 4.1 搭建代碼結構
- 4.2 根據不同路由響應不同的html頁面
- 4.3 封裝render函數
- 4.4 render函數掛載到res上
- 4.5 獲取用戶get提交的數據
- 4.6 將用戶提交的數據寫入到data.json文件中
- 4.7 瀏覽器重跳轉
- 4.8 get方式提交數據被覆蓋
- 4.9 post方式請求提交
- 4.10 underscore
- 4.11 顯示從submit添加進來的數據
- 4.12 添加新聞時增加一個id屬性
- 4.13 顯示新聞詳情
- 4.14 封裝讀取data.json文件的方法
- 4.15 封裝寫入data.json文件的方法
- 4.16 封裝獲取用戶post提交的數據的方法
- 4.17 總結:使用封裝的函數改造原來的代碼
- 0.項目地址
- 5. require加載機制
- 5-1 node.js中模塊的分類
- 5-2 require函數加載模塊原理
- 6. CommonJS規范
- 7.module.exports
- 8. exports和module.exports的區別
- 9. HackerNews項目優化
- 9-1 模塊化思路
- 9-2 封裝context.js模塊
- 9-3 提取router.js模塊
- 9-4 提取handler.js模塊(handler.index方法封裝)
- 9-4 提取router.js模塊02(順帶封裝handler.js模塊中的方法)
- 9-5 模塊化后代碼執行順序
- 9-6 封裝config.js模塊
- node.js2
- 1. buffer類型介紹
- 2. express框架
- 2.1 expres實現hello world
- 2.2 res.send()和res.end()的區別
- 2.3 app.get和app.use注冊路由的區別
- 2.4 app.all()注冊路由
- 2.5 通過正則表達式注冊路由
- 2.6 通過req.params獲取路由中的參數
- 2.7 通過express模擬Apache實現靜態資源托管服務
- 2.8 res對象的常見方法
- 3.基于express的hackernews項目
- 3.1 封裝路由模塊
- 3.2 封裝handler.js模塊
- 3.3 res.sendFile和res.render
- 3.4 ejs模板引擎使用