實作幼教平台的幼教資源部分功能,主要熟悉Node中前後端互動以及和資料庫進行互動
幼教平台完整項目代碼
這個項目陸陸續續看了有兩三遍,終于完整的整理完了,Node的項目主要還是做後端伺服器的提供接口的,前端界面還是主要用Vue、react來做,Vue可以參考實戰Vue:基于Vue的移動端購物商城
前端界面展示

項目目錄結構
(一)項目初始化(不借助express-genertor)
建立文檔school
在school文檔下建立app.js入口檔案
進行npm初始化
使用express搭建伺服器
① 安裝express
npm install express --save
② 啟動伺服器
③ 比對基礎路徑
④ 完成設定
配置babel,實作高階文法轉化
① 配置轉化環境:根目錄建立
.babelrc
,并在裡面添加如下代碼
安裝并設定為開發依賴
npm install babel-preset-env --save-dev
② 安裝babel-register轉化工具
npm i babel-register --save-dev
設定不再使用app.js向外暴露,建立src檔案夾,将app.js放在src目錄下。建立main.js。
main.js中,首先引入文法轉換工具,然後引入app.js。就可以将app.js中的高階文法轉換為低階文法。
babel高階文法轉化示範
① 安裝
npm install -g babel-cli
全局安裝
npm install babel-cli --save-dev
項目中安裝
② 通過
babel 檔案名
進行示範
③ 通過
babel src -d dist
将src中檔案轉換為低階文法版本
設定package.json中,實作開發和生産分離
設定完成後,就可以使用
npm run dev
指令進行項目運作,并且可以使用es6文法了,同時使用
npm run build
指令進行打包将高階文法轉化為低階文法,使用
npm run start
指令運作低階文法版本
(二)項目分析
幼教平台是一個全棧項目,應該分為三部分
在實際開發過程中,一般先打通後端接口,前端隻需要進行請求即可。
前端主要做幼教資源部分,一通百通,其他界面都類似:
背景管理系統
(三)項目開發
1. 配置依賴資源
建立public、views檔案夾,引入靜态資源
① 建立public檔案夾,存放公共資源
② 建立views檔案夾,存放所有界面
③ 因為要區分前後端,是以public和views中,各自建立back、web檔案夾
內建靜态資源檔案
将靜态界面以及資源内容放到對應檔案夾中
配置全局路徑
① src目錄下建立config.js,并在裡面設定路徑代碼
② 在app.js中引入并配置全局資源
配置新的模闆引擎(使用Nunjucks)
① 安裝Nunjucks
npm install nunjucks --save
② 在app.js中進行配置
配置全局路由
① 建立routes檔案夾,存放各種路由
② routes檔案夾下,建立index.js。該檔案用于配置首頁路由
③ 配置index.js。因為最後在文法轉換的時候,src檔案夾下的檔案進行轉換,是以在index.js中,使用common.js或者es6文法均可。
④ 在app.js中,引入路由并進行路由挂載
⑤ 此時就可以通過
通路後端界面
⑥ 同理,可以在index.js中配置前端路由
配置nodemon:自動重新開機項目工程
① 安裝
npm install -g nodemon
② 更改package.json中的開發指令
伺服器啟動後
此時更改代碼後,就可以自動更新了
2. 路由重定向
伺服器接收指令後,使用
res.redirect(url)
進行路由重定向
在這裡,将
'/'’
重定向為
'/web'
,也就是通路
後,會直接重定向到
3. 配置公共代碼模闆
後端界面可以将頭部以及側邊欄進行抽離,别的界面在使用的時候,直接使用Nunjucks進行內建就可以
設定完基礎模闆後,在index.html中進行繼承即可
4. 配置簡單的404界面
-
- 書寫簡單404界面
實戰Node:幼教平台幼教資源部分實作 - 在app.js所有中間件最後配置404錯誤界面
實戰Node:幼教平台幼教資源部分實作 - 此時通路沒有的資源就會出現錯誤提示
實戰Node:幼教平台幼教資源部分實作
5. 配置前台界面
-
- 配置幼教資源以及具體文章路由
實戰Node:幼教平台幼教資源部分實作 - 在界面上,将a标簽跳轉連結,改為路由的形式
實戰Node:幼教平台幼教資源部分實作
6. 幼教資源中輪播圖的實作
在routes中,建立sowing.js,用來配置輪播圖接口路由,并配置基礎路由代碼
路由設計
① 圖示:實作以下界面資料動态化
② 新增一張輪播圖
ⅰ請求方法:POST
ⅱ請求路徑:/sowing/add
ⅲ 請求參數
-
- image_url 圖檔路徑
- image_link 跳轉連結
- image_title 圖檔标題
- s_time 上架時間
- e_time 下架時間
- l_edit 最後編輯
- c_time 添加時間
③ 擷取所有輪播圖
ⅰ請求方法:GET
ⅱ請求路徑:/sowing/api/list
④ 通過ID擷取一條輪播圖
ⅰ請求方法:GET
ⅱ請求路徑:/sowing/api/singer/:sowingId
ⅲ 注意:通過url拼接的方法,擷取輪播圖ID
⑤ 根據ID修改輪播圖
ⅰ請求方法:POST
ⅱ請求路徑:/sowing/api/edit
ⅲ 請求參數
-
- ID 輪播圖ID
- image_url 新圖檔路徑
- image_link 新跳轉連結
- image_title 新圖檔标題
- s_time 新上架時間
- e_time 新下架時間
- l_edit 新最後編輯
- c_time 新添加時間
⑥ 根據ID删除輪播圖
ⅰ請求方法:GET
ⅱ請求路徑:/sowing/api/remove/:sowingId
ⅲ 注意:通過url拼接擷取輪播圖ID
背景管理輪播圖實作
可以直接使用req.body擷取資料的原因是配置了POST請求中間件。
① 新增一張輪播圖
配置接口API
配置添加輪播圖頁面路由
② 擷取所有輪播圖
配置接口API
加載輪播圖清單路由配置
這裡采用的是伺服器端渲染的方法,是以首先查詢了所有的資料,并将資料作為參數傳遞給sowing_list界面,并在界面中調用模闆文法進行渲染
③ 通過ID擷取一張輪播圖/font>
- 配置接口API
實戰Node:幼教平台幼教資源部分實作
④ 根據ID修改輪播圖
配置接口API
修改輪播圖路由配置
在輪播圖清單中,點選删除按鈕後,可以通過兩種方式在編輯界面擷取資料:① 直接将所有資料從清單界面擷取,傳遞到編輯界面。② 向編輯界面傳遞一個圖檔id,編輯界面通過id調用接口,擷取一張輪播圖的資料。這裡采用第二種方式。
在輪播圖編輯界面中,首先需要通過路徑截取id,擷取一張輪播圖資料,并注入界面。
圖檔縮略圖的地方,需要監聽檔案變化,當檔案變化的時候,監聽事件并讀取檔案,當檔案讀取完畢,将縮略圖路徑指派為新的圖檔路徑
當使用者修改完資料送出後,發起新的送出表單請求
⑤ 根據ID删除輪播圖
-
- 配置接口API
實戰Node:幼教平台幼教資源部分實作 - 修改删除路由配置
實戰Node:幼教平台幼教資源部分實作
前端展示界面實作
① 後端在傳回路由的時候,直接将所有的輪播圖資料查詢出來,并且傳回
② 前端直接使用模闆文法進行渲染即可
7. 使用者中心版塊
使用者模型
接口處理
① 添加管理者接口,在後面/user會被屏蔽,不會進行使用者名密碼的判斷
② 使用者和密碼登入接口
在驗證使用者存在後,如果密碼比對成功,會将user._id使用者的id資訊存儲在req.session.token中,即在session中存儲用戶端的資訊。同時,再傳回的結果中,将使用者ID存儲在token中,友善前端存儲在localStorage中
在前端界面,也将md5加密後的使用者名密碼傳遞到伺服器進行處理
③ 登出
④ 擷取使用者資訊——部分
使用者資訊修改
⑤ 擷取使用者資訊——全部
前端個人中心界面展示
⑥ 根據ID(token)修改一條資料資訊
⑦ 根據ID(token)修改密碼
路由配置
權限控制
在伺服器端,使用session存儲使用者資料,并将session儲存到MongoDB資料庫。同時,使用中間件進行判斷。
Node.js:使用session存儲使用者資訊 ① 在middle_wares檔案夾下,建立login_pass.js檔案,同時設定中間件
② 在app.js中,進行引入并挂載中間件
③ 在所有的輪播圖接口前面,加上/back
④ 這樣在通路後端接口或頁面的時候,就必須先登入才能通路了。
8. 後端幼教資源管理
使用者模型
接口處理
① 圖檔上傳到upload檔案夾
② 向資料庫中插入一條新記錄
③ 根據ID修改文章
④ 根據ID删除文章
路由配置
9. 前端幼教資源展示
-
-
接口設定
① 擷取總頁數
② 擷取清單頁資料實戰Node:幼教平台幼教資源部分實作 ③ 前台擷取資源清單實戰Node:幼教平台幼教資源部分實作 ④ 前台擷取詳情頁資料實戰Node:幼教平台幼教資源部分實作 ⑤ 前端詳情頁頁面閱讀量處理實戰Node:幼教平台幼教資源部分實作 實戰Node:幼教平台幼教資源部分實作 - 界面動态請求接口加載資料渲染界面
實戰Node:幼教平台幼教資源部分實作
10. 使用Mongoose與MongoDB互動,存儲資料
使用
npm i mongoose --save
安裝mongoose
模組化:Schema(模式對象),Schema對象定義限制了資料庫中的文檔結構
① 在根目錄下,建立models檔案夾,存放所有模型
② 在models下建立Sowing.js,規定輪播圖模式,模式的作用就是mongoose在與資料庫進行互動,進行增删改查的時候,進行借鑒使用的
③ 在Sowing.js中,進行導入mongoose并連接配接資料庫,并監聽連接配接成功或失敗
④ 建立模式Schema,并建立一個Model向外暴露。Mongoose 的一切始于 Schema。每個 schema 都會映射到一個 MongoDB collection ,并定義這個collection裡的文檔的構成。
在sowing.js輪播圖路由中,引入Sowing模式,并進行相關操作,配置接口。
11. Node中POST請求
Node.js:POST請求、檔案上傳
12. Node中,使用中間件處理POST請求
在根目錄下建立middle_wares檔案夾存儲中間件。
過濾get請求
如果是普通表單(application/x-www-form-urlencoded)送出,要處理,以拼接的形式;如果有檔案(圖檔、音視訊····multipart/form-data),不要處理
其他情況,需要進行處理。
① 資料流拼接
② 使用querystring解析和格式化字元串。
完整的POST中間件
import querystring from 'querystring'
// 處理post請求
export default (req, res, next) => {
// 1. 過濾get請求
if (req.method.toLowerCase() === 'get') {
return next();
}
// 2. 如果是普通表單送出,要處理,以拼接的形式
// application/x-www-form-urlencoded
// 如果有檔案(圖檔、音視訊····),不要處理,multipart/form-data
if (req.headers['content-type'].startsWith("multipart/form-data")) {
return next();
}
// 3. 資料流的拼接
let data = "";
req.on("data", (chunk) => {
data += chunk;
});
req.on("end", () => {
req.body = querystring.parse(data);
next();
})
}
挂載中間件,在app.js中引入body_parse,并且在所有路由前進配置資料進行中間件
13. Node中,使用中間件處理error
-
- 需求:出現錯誤的時候,通過中間件,将錯誤存儲到資料庫中
- 在models中,建立Error.js,建立錯誤模型
實戰Node:幼教平台幼教資源部分實作 - 在middle_wares檔案夾中,建立error_log.js,作為錯誤中間件處理錯誤。
實戰Node:幼教平台幼教資源部分實作 - 在app.js中引入并挂載錯誤中間件
實戰Node:幼教平台幼教資源部分實作
14. 路由跳轉
與Vue直接在頁面中通過router跳轉不同的是,Node項目中,使用html的a标簽跳轉,直接将路徑放在a标簽的href屬性内即可。
15. 模闆的渲染
在之前的基礎學習中,是使用ejs進行渲染的。在這個項目中,使用的是Nunjucks進行渲染。這兩種伺服器端渲染方法都大同小異。
Nunjucks文檔## 标題
EJS文檔
16. 在src目錄下,有一個config.js配置檔案。
在這個檔案夾下,定義了一些路徑,定義好後,在app.js中引入,就可以在别的檔案中使用了。
17. 模糊路徑比對
在路徑中,使用
路徑/:name
,冒号後面的就是模糊比對
在伺服器接口中,使用
req.params.name
擷取值
18. 圖檔、檔案等資源的上傳,使用formidable
Node.js:借助formidable檔案上傳
19. 內建文本編輯器 wangEditor
20. 分頁
有重新整理
給上一頁下一頁按鈕綁定路由仍然為source_list
在點選後,頁面相當于進行重新整理,此時,後端接口會接收兩個參數, 頁數和每一頁顯示的數量,根據公式查詢結果,并渲染界面傳回前端
無重新整理:內建分頁插件:
twbs-pagination
twbs-pagination文檔 配置擷取總頁數接口以及擷取清單頁面資料的接口,供分頁插件使用
21. 項目的重構
後端
async/await
① 概念
-
- 現在最常用的異步變成方案
- async函數時Generator函數的文法糖
-
具備特點
① 内置執行器
Generator函數的執行必須依靠執行器,而async函數自帶執行器,調用方式和普通函數的調用一樣
② 更好的語義
async和await相較于*和yield更加語義化
③ 更廣的适用性
co子產品約定,yield指令後面隻能是Thunk函數或Promise對象
而async函數的await指令後面則可以是Promise或者原始類型的值(Number、string、boolean,但這時等同于同步操作)
④ 傳回值是promise
async函數傳回值是Promise對象,比Generator函數傳回的Iterator對象友善,可以直接使用then()方法進行調用
② 使用
-
- async是“異步”的簡寫,async function用于聲明一個function是異步的;await,可以認為是async wait的簡寫,用于等待一個異步方法執行完成
- async/await是一個用同步思維解決異步問題的方案(等結果出來之後,代碼才會繼續執行)
- 可以通過多層async function的同步寫法代替傳統的callback嵌套
在項目中如果要是用async/await,需要安裝和配置
transform-runtime
① 步驟:
npm i babel-plugin-transform-runtime -D
② 配置
.babelrc
③ 不安裝則會報錯
regeneratorRuntime is not defined
錯誤
MVC設計模式
将項目轉換為MVC模式,首先要将業務邏輯從router中抽離出來,下面以sowing.js為例
① 建立controller檔案夾,并在controller檔案夾下建立sowing檔案夾,并在sowing檔案夾下建立SowingController.js
② 将sowing.js中的業務邏輯,全部放到SowingController.js中
在sowing.js中
而在SowingController.js中
此時,隻需要在sowing.js中引入SowingController.js,并且在接口處使用SowingController中的方法即可。
所有的接口轉移完成後
sowing.js中
SowingController.js中
端口号配置
各個環境下,nodejs可以通過process.env.PORT去設定端口号
比如
① linux環境下
PORT=1234 node app.js
使用上面指令每次都需要重新設定,如果想設定一次永久生效,使用下面指令
export PORT=1234
node app.js
② windows環境下
set PORT=1234
node app.js
package.json配置檔案
實操
在package.json中設定
在config.js中設定
在app.js中監聽
中間件session抽取——config.js
實操:
在config.js中設定常量
在app.js中直接使用config.js中的資料進行配置即可
內建插件chalk
① 簡介:chalk是一個顔色的插件,可以通過比如:
chalk.blue("hello world")
之類的方法來改變顔色
② 使用
-
- 下載下傳:
npm install chalk
- 引入:
import chalk from 'chalk'
- 顯示:
console.log(chalk.blue("Hello world!"));
封裝資料庫連接配接
① 簡介:全局連接配接資料庫
② 實作:
-
- 在根目錄下建立檔案夾db,在bd檔案夾下建立db.js,db.js中實作連接配接資料庫
'use strict';
import mongoose from 'mongoose';
import config from './../src/config';
mongoose.connect(config.db_url, {useNewUrlParser: true});
mongoose.Promise = global.Promise;
const db = mongoose.connection;
db.once('open' ,()=>{
console.log('連接配接資料庫成功~~~~~~');
});
db.on('error', (error)=>{
console.error('連接配接資料庫時發生錯誤: ' + error);
mongoose.disconnect();
});
db.on('close', function() {
console.log('資料庫斷開,重新連接配接資料庫');
mongoose.connect(config.db_url, {useNewUrlParser: true});
});
export default db;
在app.js中引入