天天看點

實戰Node:幼教平台幼教資源部分實作

實作幼教平台的幼教資源部分功能,主要熟悉Node中前後端互動以及和資料庫進行互動

​​幼教平台完整項目代碼​​

這個項目陸陸續續看了有兩三遍,終于完整的整理完了,Node的項目主要還是做後端伺服器的提供接口的,前端界面還是主要用Vue、react來做,Vue可以參考​​實戰Vue:基于Vue的移動端購物商城​​

前端界面展示

實戰Node:幼教平台幼教資源部分實作
實戰Node:幼教平台幼教資源部分實作
實戰Node:幼教平台幼教資源部分實作
實戰Node:幼教平台幼教資源部分實作
實戰Node:幼教平台幼教資源部分實作

項目目錄結構

實戰Node:幼教平台幼教資源部分實作

(一)項目初始化(不借助express-genertor)

建立文檔school

實戰Node:幼教平台幼教資源部分實作

在school文檔下建立app.js入口檔案

實戰Node:幼教平台幼教資源部分實作

進行npm初始化

實戰Node:幼教平台幼教資源部分實作

使用express搭建伺服器

① 安裝express ​

​npm install express --save​

​ ② 啟動伺服器

實戰Node:幼教平台幼教資源部分實作

③ 比對基礎路徑

實戰Node:幼教平台幼教資源部分實作

④ 完成設定

實戰Node:幼教平台幼教資源部分實作

配置babel,實作高階文法轉化

① 配置轉化環境:根目錄建立​

​.babelrc​

​,并在裡面添加如下代碼

實戰Node:幼教平台幼教資源部分實作

安裝并設定為開發依賴​

​npm install babel-preset-env --save-dev​

實戰Node:幼教平台幼教資源部分實作

② 安裝babel-register轉化工具​

​npm i babel-register --save-dev​

實戰Node:幼教平台幼教資源部分實作

設定不再使用app.js向外暴露,建立src檔案夾,将app.js放在src目錄下。建立main.js。

實戰Node:幼教平台幼教資源部分實作

main.js中,首先引入文法轉換工具,然後引入app.js。就可以将app.js中的高階文法轉換為低階文法。

babel高階文法轉化示範

① 安裝

​npm install -g babel-cli​

​ 全局安裝

​npm install babel-cli --save-dev​

​ 項目中安裝

② 通過​

​babel 檔案名​

​進行示範

實戰Node:幼教平台幼教資源部分實作

③ 通過​

​babel src -d dist​

​将src中檔案轉換為低階文法版本

實戰Node:幼教平台幼教資源部分實作
實戰Node:幼教平台幼教資源部分實作
實戰Node:幼教平台幼教資源部分實作

設定package.json中,實作開發和生産分離

實戰Node:幼教平台幼教資源部分實作

設定完成後,就可以使用​

​npm run dev​

​指令進行項目運作,并且可以使用es6文法了,同時使用​

​npm run build​

​指令進行打包将高階文法轉化為低階文法,使用​

​npm run start​

​指令運作低階文法版本

(二)項目分析

幼教平台是一個全棧項目,應該分為三部分

實戰Node:幼教平台幼教資源部分實作

在實際開發過程中,一般先打通後端接口,前端隻需要進行請求即可。

前端主要做幼教資源部分,一通百通,其他界面都類似:

實戰Node:幼教平台幼教資源部分實作

背景管理系統

實戰Node:幼教平台幼教資源部分實作

(三)項目開發

1. 配置依賴資源

建立public、views檔案夾,引入靜态資源

① 建立public檔案夾,存放公共資源

實戰Node:幼教平台幼教資源部分實作

② 建立views檔案夾,存放所有界面

實戰Node:幼教平台幼教資源部分實作

③ 因為要區分前後端,是以public和views中,各自建立back、web檔案夾

實戰Node:幼教平台幼教資源部分實作

內建靜态資源檔案

将靜态界面以及資源内容放到對應檔案夾中

實戰Node:幼教平台幼教資源部分實作

配置全局路徑

① src目錄下建立config.js,并在裡面設定路徑代碼

實戰Node:幼教平台幼教資源部分實作

② 在app.js中引入并配置全局資源

實戰Node:幼教平台幼教資源部分實作

配置新的模闆引擎(使用Nunjucks)

① 安裝Nunjucks​

​npm install nunjucks --save​

實戰Node:幼教平台幼教資源部分實作

② 在app.js中進行配置

實戰Node:幼教平台幼教資源部分實作

配置全局路由

① 建立routes檔案夾,存放各種路由

實戰Node:幼教平台幼教資源部分實作

② routes檔案夾下,建立index.js。該檔案用于配置首頁路由

實戰Node:幼教平台幼教資源部分實作

③ 配置index.js。因為最後在文法轉換的時候,src檔案夾下的檔案進行轉換,是以在index.js中,使用common.js或者es6文法均可。

實戰Node:幼教平台幼教資源部分實作
實戰Node:幼教平台幼教資源部分實作

④ 在app.js中,引入路由并進行路由挂載

實戰Node:幼教平台幼教資源部分實作

⑤ 此時就可以通過​​

​​

​​通路後端界面

實戰Node:幼教平台幼教資源部分實作

⑥ 同理,可以在index.js中配置前端路由

實戰Node:幼教平台幼教資源部分實作

配置nodemon:自動重新開機項目工程

① 安裝​

​npm install -g nodemon​

實戰Node:幼教平台幼教資源部分實作

② 更改package.json中的開發指令

實戰Node:幼教平台幼教資源部分實作
實戰Node:幼教平台幼教資源部分實作

伺服器啟動後

實戰Node:幼教平台幼教資源部分實作

此時更改代碼後,就可以自動更新了

2. 路由重定向

伺服器接收指令後,使用​

​res.redirect(url)​

​進行路由重定向

實戰Node:幼教平台幼教資源部分實作

在這裡,将​

​'/'’​

​重定向為​

​'/web'​

​,也就是通路​​

​​

​​後,會直接重定向到​​

​​

​​

3. 配置公共代碼模闆

後端界面可以将頭部以及側邊欄進行抽離,别的界面在使用的時候,直接使用Nunjucks進行內建就可以

實戰Node:幼教平台幼教資源部分實作

設定完基礎模闆後,在index.html中進行繼承即可

實戰Node:幼教平台幼教資源部分實作

4. 配置簡單的404界面

  1. 書寫簡單404界面
    實戰Node:幼教平台幼教資源部分實作
  2. 在app.js所有中間件最後配置404錯誤界面
    實戰Node:幼教平台幼教資源部分實作
  3. 此時通路沒有的資源就會出現錯誤提示
    實戰Node:幼教平台幼教資源部分實作

5. 配置前台界面

  1. 配置幼教資源以及具體文章路由
    實戰Node:幼教平台幼教資源部分實作
  2. 在界面上,将a标簽跳轉連結,改為路由的形式
    實戰Node:幼教平台幼教資源部分實作

6. 幼教資源中輪播圖的實作

在routes中,建立sowing.js,用來配置輪播圖接口路由,并配置基礎路由代碼

實戰Node:幼教平台幼教資源部分實作

路由設計

① 圖示:實作以下界面資料動态化

實戰Node:幼教平台幼教資源部分實作

② 新增一張輪播圖

ⅰ請求方法:POST

ⅱ請求路徑:/sowing/add

ⅲ 請求參數

  1. image_url 圖檔路徑
  2. image_link 跳轉連結
  3. image_title 圖檔标題
  4. s_time 上架時間
  5. e_time 下架時間
  6. l_edit 最後編輯
  7. c_time 添加時間

③ 擷取所有輪播圖

ⅰ請求方法:GET

ⅱ請求路徑:/sowing/api/list

④ 通過ID擷取一條輪播圖

ⅰ請求方法:GET

ⅱ請求路徑:/sowing/api/singer/:sowingId

ⅲ 注意:通過url拼接的方法,擷取輪播圖ID

⑤ 根據ID修改輪播圖

ⅰ請求方法:POST

ⅱ請求路徑:/sowing/api/edit

ⅲ 請求參數

  1. ID 輪播圖ID
  2. image_url 新圖檔路徑
  3. image_link 新跳轉連結
  4. image_title 新圖檔标題
  5. s_time 新上架時間
  6. e_time 新下架時間
  7. l_edit 新最後編輯
  8. c_time 新添加時間

⑥ 根據ID删除輪播圖

ⅰ請求方法:GET

ⅱ請求路徑:/sowing/api/remove/:sowingId

ⅲ 注意:通過url拼接擷取輪播圖ID

背景管理輪播圖實作

可以直接使用req.body擷取資料的原因是配置了POST請求中間件。

① 新增一張輪播圖

配置接口API

實戰Node:幼教平台幼教資源部分實作

配置添加輪播圖頁面路由

實戰Node:幼教平台幼教資源部分實作
實戰Node:幼教平台幼教資源部分實作

② 擷取所有輪播圖

配置接口API

實戰Node:幼教平台幼教資源部分實作

加載輪播圖清單路由配置

這裡采用的是伺服器端渲染的方法,是以首先查詢了所有的資料,并将資料作為參數傳遞給sowing_list界面,并在界面中調用模闆文法進行渲染

實戰Node:幼教平台幼教資源部分實作
實戰Node:幼教平台幼教資源部分實作

③ 通過ID擷取一張輪播圖/font>

  1. 配置接口API
    實戰Node:幼教平台幼教資源部分實作

④ 根據ID修改輪播圖

配置接口API

實戰Node:幼教平台幼教資源部分實作

修改輪播圖路由配置

實戰Node:幼教平台幼教資源部分實作

在輪播圖清單中,點選删除按鈕後,可以通過兩種方式在編輯界面擷取資料:① 直接将所有資料從清單界面擷取,傳遞到編輯界面。② 向編輯界面傳遞一個圖檔id,編輯界面通過id調用接口,擷取一張輪播圖的資料。這裡采用第二種方式。

實戰Node:幼教平台幼教資源部分實作

在輪播圖編輯界面中,首先需要通過路徑截取id,擷取一張輪播圖資料,并注入界面。

實戰Node:幼教平台幼教資源部分實作

圖檔縮略圖的地方,需要監聽檔案變化,當檔案變化的時候,監聽事件并讀取檔案,當檔案讀取完畢,将縮略圖路徑指派為新的圖檔路徑

實戰Node:幼教平台幼教資源部分實作

當使用者修改完資料送出後,發起新的送出表單請求

實戰Node:幼教平台幼教資源部分實作

⑤ 根據ID删除輪播圖

  1. 配置接口API
    實戰Node:幼教平台幼教資源部分實作
  2. 修改删除路由配置
    實戰Node:幼教平台幼教資源部分實作

前端展示界面實作

① 後端在傳回路由的時候,直接将所有的輪播圖資料查詢出來,并且傳回

實戰Node:幼教平台幼教資源部分實作

② 前端直接使用模闆文法進行渲染即可

實戰Node:幼教平台幼教資源部分實作

7. 使用者中心版塊

使用者模型

實戰Node:幼教平台幼教資源部分實作

接口處理

① 添加管理者接口,在後面/user會被屏蔽,不會進行使用者名密碼的判斷

實戰Node:幼教平台幼教資源部分實作

② 使用者和密碼登入接口

在驗證使用者存在後,如果密碼比對成功,會将user._id使用者的id資訊存儲在req.session.token中,即在session中存儲用戶端的資訊。同時,再傳回的結果中,将使用者ID存儲在token中,友善前端存儲在localStorage中

實戰Node:幼教平台幼教資源部分實作

在前端界面,也将md5加密後的使用者名密碼傳遞到伺服器進行處理

實戰Node:幼教平台幼教資源部分實作

③ 登出

實戰Node:幼教平台幼教資源部分實作

④ 擷取使用者資訊——部分

實戰Node:幼教平台幼教資源部分實作

使用者資訊修改

實戰Node:幼教平台幼教資源部分實作

⑤ 擷取使用者資訊——全部

實戰Node:幼教平台幼教資源部分實作

前端個人中心界面展示

實戰Node:幼教平台幼教資源部分實作

⑥ 根據ID(token)修改一條資料資訊

實戰Node:幼教平台幼教資源部分實作

⑦ 根據ID(token)修改密碼

實戰Node:幼教平台幼教資源部分實作
實戰Node:幼教平台幼教資源部分實作

路由配置

實戰Node:幼教平台幼教資源部分實作

權限控制

在伺服器端,使用session存儲使用者資料,并将session儲存到MongoDB資料庫。同時,使用中間件進行判斷。

​​Node.js:使用session存儲使用者資訊​​ ① 在middle_wares檔案夾下,建立login_pass.js檔案,同時設定中間件

實戰Node:幼教平台幼教資源部分實作

② 在app.js中,進行引入并挂載中間件

實戰Node:幼教平台幼教資源部分實作

③ 在所有的輪播圖接口前面,加上/back

實戰Node:幼教平台幼教資源部分實作

④ 這樣在通路後端接口或頁面的時候,就必須先登入才能通路了。

8. 後端幼教資源管理

使用者模型

實戰Node:幼教平台幼教資源部分實作

接口處理

① 圖檔上傳到upload檔案夾

實戰Node:幼教平台幼教資源部分實作

② 向資料庫中插入一條新記錄

實戰Node:幼教平台幼教資源部分實作

③ 根據ID修改文章

實戰Node:幼教平台幼教資源部分實作

④ 根據ID删除文章

實戰Node:幼教平台幼教資源部分實作

路由配置

實戰Node:幼教平台幼教資源部分實作

9. 前端幼教資源展示

  1. 接口設定

    ① 擷取總頁數

    實戰Node:幼教平台幼教資源部分實作
    ② 擷取清單頁資料
    實戰Node:幼教平台幼教資源部分實作
    ③ 前台擷取資源清單
    實戰Node:幼教平台幼教資源部分實作
    ④ 前台擷取詳情頁資料
    實戰Node:幼教平台幼教資源部分實作
    ⑤ 前端詳情頁頁面閱讀量處理
    實戰Node:幼教平台幼教資源部分實作
  2. 界面動态請求接口加載資料渲染界面
    實戰Node:幼教平台幼教資源部分實作

10. 使用Mongoose與MongoDB互動,存儲資料

使用​

​npm i mongoose --save​

​安裝mongoose

實戰Node:幼教平台幼教資源部分實作

模組化:Schema(模式對象),Schema對象定義限制了資料庫中的文檔結構

① 在根目錄下,建立models檔案夾,存放所有模型

實戰Node:幼教平台幼教資源部分實作

② 在models下建立Sowing.js,規定輪播圖模式,模式的作用就是mongoose在與資料庫進行互動,進行增删改查的時候,進行借鑒使用的

實戰Node:幼教平台幼教資源部分實作

③ 在Sowing.js中,進行導入mongoose并連接配接資料庫,并監聽連接配接成功或失敗

實戰Node:幼教平台幼教資源部分實作

④ 建立模式Schema,并建立一個Model向外暴露。Mongoose 的一切始于 Schema。每個 schema 都會映射到一個 MongoDB collection ,并定義這個collection裡的文檔的構成。

實戰Node:幼教平台幼教資源部分實作

在sowing.js輪播圖路由中,引入Sowing模式,并進行相關操作,配置接口。

11. Node中POST請求

​​Node.js:POST請求、檔案上傳​​

12. Node中,使用中間件處理POST請求

在根目錄下建立middle_wares檔案夾存儲中間件。

實戰Node:幼教平台幼教資源部分實作

過濾get請求

實戰Node:幼教平台幼教資源部分實作

如果是普通表單(application/x-www-form-urlencoded)送出,要處理,以拼接的形式;如果有檔案(圖檔、音視訊····multipart/form-data),不要處理

實戰Node:幼教平台幼教資源部分實作

其他情況,需要進行處理。

① 資料流拼接

② 使用querystring解析和格式化字元串。

實戰Node:幼教平台幼教資源部分實作

完整的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,并且在所有路由前進配置資料進行中間件

實戰Node:幼教平台幼教資源部分實作

13. Node中,使用中間件處理error

  1. 需求:出現錯誤的時候,通過中間件,将錯誤存儲到資料庫中
  2. 在models中,建立Error.js,建立錯誤模型
    實戰Node:幼教平台幼教資源部分實作
  3. 在middle_wares檔案夾中,建立error_log.js,作為錯誤中間件處理錯誤。
    實戰Node:幼教平台幼教資源部分實作
  4. 在app.js中引入并挂載錯誤中間件
    實戰Node:幼教平台幼教資源部分實作

14. 路由跳轉

與Vue直接在頁面中通過router跳轉不同的是,Node項目中,使用html的a标簽跳轉,直接将路徑放在a标簽的href屬性内即可。

實戰Node:幼教平台幼教資源部分實作

15. 模闆的渲染

在之前的基礎學習中,是使用ejs進行渲染的。在這個項目中,使用的是Nunjucks進行渲染。這兩種伺服器端渲染方法都大同小異。

​​Nunjucks文檔## 标題​​

​​EJS文檔​​

16. 在src目錄下,有一個config.js配置檔案。

在這個檔案夾下,定義了一些路徑,定義好後,在app.js中引入,就可以在别的檔案中使用了。

實戰Node:幼教平台幼教資源部分實作
實戰Node:幼教平台幼教資源部分實作

17. 模糊路徑比對

在路徑中,使用​

​路徑/:name​

​,冒号後面的就是模糊比對

在伺服器接口中,使用​

​req.params.name​

​擷取值

實戰Node:幼教平台幼教資源部分實作

18. 圖檔、檔案等資源的上傳,使用formidable

​​Node.js:借助formidable檔案上傳​​

19. 內建文本編輯器 ​​wangEditor​​

20. 分頁

有重新整理

給上一頁下一頁按鈕綁定路由仍然為source_list

實戰Node:幼教平台幼教資源部分實作

在點選後,頁面相當于進行重新整理,此時,後端接口會接收兩個參數, 頁數和每一頁顯示的數量,根據公式查詢結果,并渲染界面傳回前端

實戰Node:幼教平台幼教資源部分實作

無重新整理:內建分頁插件:​

​twbs-pagination​

​​​twbs-pagination文檔​​ 配置擷取總頁數接口以及擷取清單頁面資料的接口,供分頁插件使用

實戰Node:幼教平台幼教資源部分實作
實戰Node:幼教平台幼教資源部分實作

21. 項目的重構

後端

async/await

① 概念

  1. 現在最常用的異步變成方案
  2. async函數時Generator函數的文法糖
  3. 具備特點

    ① 内置執行器

    Generator函數的執行必須依靠執行器,而async函數自帶執行器,調用方式和普通函數的調用一樣

    ② 更好的語義

    async和await相較于*和yield更加語義化

    ③ 更廣的适用性

    co子產品約定,yield指令後面隻能是Thunk函數或Promise對象

    而async函數的await指令後面則可以是Promise或者原始類型的值(Number、string、boolean,但這時等同于同步操作)

    ④ 傳回值是promise

    async函數傳回值是Promise對象,比Generator函數傳回的Iterator對象友善,可以直接使用then()方法進行調用

② 使用

  1. async是“異步”的簡寫,async function用于聲明一個function是異步的;await,可以認為是async wait的簡寫,用于等待一個異步方法執行完成
  2. async/await是一個用同步思維解決異步問題的方案(等結果出來之後,代碼才會繼續執行)
  3. 可以通過多層async function的同步寫法代替傳統的callback嵌套

在項目中如果要是用async/await,需要安裝和配置​

​transform-runtime​

​ ① 步驟:​

​npm i babel-plugin-transform-runtime -D​

​ ② 配置​

​.babelrc​

實戰Node:幼教平台幼教資源部分實作

③ 不安裝則會報錯​

​regeneratorRuntime is not defined​

​錯誤

MVC設計模式

将項目轉換為MVC模式,首先要将業務邏輯從router中抽離出來,下面以sowing.js為例

① 建立controller檔案夾,并在controller檔案夾下建立sowing檔案夾,并在sowing檔案夾下建立SowingController.js

實戰Node:幼教平台幼教資源部分實作

② 将sowing.js中的業務邏輯,全部放到SowingController.js中

在sowing.js中

實戰Node:幼教平台幼教資源部分實作

而在SowingController.js中

實戰Node:幼教平台幼教資源部分實作

此時,隻需要在sowing.js中引入SowingController.js,并且在接口處使用SowingController中的方法即可。

實戰Node:幼教平台幼教資源部分實作

所有的接口轉移完成後

sowing.js中

實戰Node:幼教平台幼教資源部分實作

SowingController.js中

實戰Node:幼教平台幼教資源部分實作

端口号配置

各個環境下,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中設定

實戰Node:幼教平台幼教資源部分實作

在config.js中設定

實戰Node:幼教平台幼教資源部分實作

在app.js中監聽

實戰Node:幼教平台幼教資源部分實作

中間件session抽取——config.js

實操:

在config.js中設定常量

實戰Node:幼教平台幼教資源部分實作

在app.js中直接使用config.js中的資料進行配置即可

實戰Node:幼教平台幼教資源部分實作

內建插件chalk

① 簡介:chalk是一個顔色的插件,可以通過比如:​

​chalk.blue("hello world")​

​之類的方法來改變顔色

② 使用

  1. 下載下傳:​

    ​npm install chalk​

  2. 引入:​

    ​import chalk from 'chalk'​

  3. 顯示:​

    ​console.log(chalk.blue("Hello world!"));​

封裝資料庫連接配接

① 簡介:全局連接配接資料庫

② 實作:

  1. 在根目錄下建立檔案夾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中引入

實戰Node:幼教平台幼教資源部分實作

前端