hello,小夥伴們,我是大家的pubdreamcc
,本篇博文出至於個人GitHub倉庫node學習教程資料
,歡迎小夥伴們點贊和star
,大家的點贊是我持續更新的動力。javascript
GitHub倉庫地址:node學習教程html
本篇文章對應的源碼:Student-Management-System前端
好了,廢話很少說了,今天繼續咱們express
的學習~java
今天咱們實現一個案例,用express實現基本的C-R-U-D(增刪改查)學生信息管理系統。學習這個案例一方面讓咱們熟悉業務開發的流程,一方面能夠鞏固以前學習的express知識。node
app.js -- 入口模塊git
router.js -- 路由模塊github
student.js -- 操做數據模塊(封裝操做數據的基本API)數據庫
Db.json -- 模擬數據庫,保存數據的文件express
views文件夾 -- 頁面視圖文件npm
public文件夾 -- 靜態資源文件
git clone
克隆項目到本地
npm install
進入項目文件夾,下載相關依賴
node app.js
node啓動項目
public
靜態文件夾,views
頁面視圖文件夾。項目中前端頁面使用了bootstrap
快速搭建,全部須要開放bootstrap樣式文件和頁面相關的腳本文件。在views
文件夾中存放主頁面: index.html
,編輯學生信息頁面:edit.html
,添加學生頁面:add.html
。
Db.json
,模擬數據庫存放學生信息數據由於咱們沒有涉及到數據庫,因此暫時把學生數據存放在Db.json文件中,在數據文件中,咱們須要一個數組:students
,用來存放每個學生的信息。一般數據文件都是一個json格式文件,因此嚴格按照json格式要求來模擬數據。
{ "students": [ { "id": 1, "name": "牛魔王", "age": 18, "hobbies": "打人" } ... ] }
在入口模塊中啓動服務器,配置art-template
模板引擎,配置express中間件body-parser
解析post
請求提交的數據,最後把路由容器router
掛載到app服務器實例上。由於node中解析代碼是從上至下,因此路由容器掛載必須在各項配置以後,不然會出錯。
const express = require('express') const router = require('./router') const bodyParser = require('body-parser') const app = express() // 開發靜態資源 app.use('/public/', express.static('./public')) app.use('/node_modules/', express.static('./node_modules')) // 配置模板引擎 app.engine('html', require('express-art-template')) // 配置body-parser,獲得post請求體數據 app.use(bodyParser.urlencoded({ extended: false })) // 注意:配置模板引擎和body-parser,開放靜態資源必須放在路由容器掛載以前 // 掛載路由容器 app.use(router) // 綁定端口號,開啓服務 app.listen(3000, () => { console.log('running...') })
router.js
,專門處理每一個路由由於項目中須要處理多個路由,因此咱們分離出一個路由模塊,用來處理路由信息。模塊的分離使得node中每一個模塊各司其職,職能單一,同時也便於後期代碼維護。
router.js
模塊中每一個路由都須要涉及到操做數據文件,因此咱們在此以外須要封裝一些數據操做的API。封裝異步 API這裏纔是咱們學習 Node 的精華部分:奧義之所在。
// 路由模塊 const express = require('express') const Student = require('./student') // 獲得路由容器 const router = express.Router() /* * 下面就是把每條路由都掛載到路由容器中 */ // 請求'/',顯示所有學生信息 router.get('/', (req, res) => { // 調用Student.find()API,獲取全部學生信息 。。。 }) // 請求/add',顯示添加學生信息的界面 router.get('/add', (req, res) => { res.render('add.html') }) // 表單post提交數據到'/add',處理數據後重定向至'/' router.post('/add', (req, res) => { /* *獲取表單提交的數據 *添加到數據文件中 *重定向至首頁,顯示新提交的學生信息 */ 。。。 }) // 請求'/edit',展現編輯學生信息界面 router.get('/edit', (req, res) => { // 調用 Student.findById()API,經過id值獲取學生信息渲染在頁面上 。。。 }) // 獲取post請求提交的數據,更新學生信息,重定向到'/' router.post('/edit', (req, res) => { /** * 獲取新修改的post請求提交的學生信息 * 處理數據文件,修改學生信息 * 重定向到'/' */ }) // 當請求'/delete',根據id值刪除相應的學生信息,重定向到'/' router.get('/delete', (req, res) => { // 調用 Student.deleteById()API,經過id值查找到對應學生,刪除其信息 。。。 }) module.exports = router
student.js
數據操做的模塊,只負責操做數據(增長新數據,修改數據,刪除數據等),不關心業務邏輯。
注意:咱們在操做數據文件的時候,永遠只能是:先讀取出來原有的字符串數據,轉換成對象,處理完成以後,再把對象轉換成JSON格式字符串,最後再保存到數據文件中。文件中永遠存放的是字符串格式的數據。
因爲是這種操做順序,因此student.js中頻繁使用到node核心模塊fs
,反覆調用fs.readFile()
讀取文件內容,fs.writeFile()
修改文件中的數據。
// 引入fs核心模塊 const fs = require('fs') // 保存學生信息 /** * 保存新添加的學生信息到數據文件中 * 參數: * 1. 新加的學生信息對象 * 2. callback回調函數,拿到異步操做的結果 * callback中的參數: * 第一個參數err * 成功是null, 失敗是錯誤對象 * 第二個參數是結果 * 成功是數組,失敗是undefined */ exports.save = (student, callback) => { fs.readFile('./Db.json', 'utf8', (err, data) => { if (err) { return callback(err) } // 獲得全部學生信息 let students = JSON.parse(data).students // 爲新加的學生添加一個惟一的id屬性(原來最大id屬性值基礎上加1) if (students.length === 0) { // 若是原始數據文件中沒有學生信息 student.id = 1 } else { student.id = parseInt(students[students.length-1].id) + 1 } students.push(student) // 把新增長學生信息後的對象轉換成字符串保存到數據文件中 let dataStr = JSON.stringify({ students: students }) fs.writeFile('./Db.json', dataStr, err => { if (err) { // 若是寫入失敗,則把錯誤對象傳遞給它 return callback(err) } // 成功就沒錯,因此錯誤對象是 null callback(null) }) }) } 。。。
因爲篇幅緣由,這裏只羅列了添加學生信息API的實現代碼。這裏還有一個很是重要的知識點:怎樣獲取到一個函數內部異步操做的結果?
只能是經過回調函數。
或許有一些其餘的內置模塊,包括封裝的API也能夠拿到異步操做的結果,可是其底層都是利用了回調函數的思想。好比常見的Node內置events
事件模塊等。
這裏只需強調一點,在編寫視圖文件的時候,須要把一些動態的數據用模板語法包裹起來,可以使得模板引擎正確的渲染模板文件便可。
須要學習資料和案例源碼的夥伴能夠去GitHub上查看,若是您對這案例或者學習資料有更好的見解,歡迎issue,或者評論,謝謝。