express-CRUD
阿新 • • 發佈:2019-01-10
入口檔案
/** * app.js 入門模組 * 職責: * 建立服務 * 做一些服務相關配置 * 模板引擎 * body-parser 解析表單 post 請求體 * 提供靜態資源服務 * 掛載路由 * 監聽埠啟動服務 */ var express = require('express') var router = require('./router') var bodyParser = require('body-parser') var app = express() app.use('/node_modules/', express.static('./node_modules/')) app.use('/public/', express.static('./public/')) app.engine('html', require('express-art-template')) // 配置模板引擎和 body-parser 一定要在 app.use(router) 掛載路由之前 // parse application/x-www-form-urlencoded app.use(bodyParser.urlencoded({ extended: false })) // parse application/json app.use(bodyParser.json()) // 把路由容器掛載到 app 服務中 app.use(router) app.listen(3000, function () { console.log('running 3000...') }) module.exports = app
路由檔案
/** * router.js 路由模組 * 職責: * 處理路由 * 根據不同的請求方法+請求路徑設定具體的請求處理函式 * 模組職責要單一,不要亂寫 * 我們劃分模組的目的就是為了增強專案程式碼的可維護性 * 提升開發效率 */ var fs = require('fs') var Student = require('./student') // Express 提供了一種更好的方式 // 專門用來包裝路由的 var express = require('express') // 1. 建立一個路由容器 var router = express.Router() // 2. 把路由都掛載到 router 路由容器中 /* * 渲染學生列表頁面 */ router.get('/students', function (req, res) { 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. 傳送響應 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. 渲染編輯頁面 // 根據 id 把學生資訊查出來 // 使用模板引擎渲染頁面 Student.findById(parseInt(req.query.id), function (err, student) { if (err) { return res.status(500).send('Server error.') } res.render('edit.html', { student: student }) }) }) /* * 處理編輯學生 */ 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 error.') } res.redirect('/students') }) })
資料處理檔案 student.js
/** * student.js * 資料操作檔案模組 * 職責:操作檔案中的資料,只處理資料,不關心業務 * * 這裡才是我們學習 Node 的精華部分:奧義之所在 * 封裝非同步 API */ var fs = require('fs') var dbPath = './db.json' /** * 獲取學生列表 * @param {Function} callback 回撥函式 */ 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) }) } /** * 新增儲存學生 * @param {Object} student 學生物件 * @param {Function} callback 回撥函式 */ 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) } // 成功就沒錯,所以錯誤物件是 null 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 }) // 這種方式你就寫死了,有 100 個難道就寫 100 次嗎? // stu.name = student.name // stu.age = student.age // 遍歷拷貝物件 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) } // 成功就沒錯,所以錯誤物件是 null 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) } // 成功就沒錯,所以錯誤物件是 null callback(null) }) }) }