本系列文章是為學習Vue的專案練習筆記,盡量詳細記錄一下一個完整專案的開發程序,面向初學者,本人也是初學者,搬磚技識訓不成熟,專案在技術上前端為主,包含一些后端代碼,從基礎的資料庫(Sqlite)、到后端服務Node.js(Express),再到Web端的Vue,包含服務端、管理后臺、商城網站、小程式/App,分為下面多個篇檔案,
??系列目錄:
- 圖書商城Vue+Element+Node+TS專案練習??
- 圖書商城①管理后臺Vue2+ElementUI??
- 圖書商城②后端服務Node+Express+Sqlite??
- 未完成:商城網站Vue3+TS、商城APP端Vue3+TS+uniapp
00、后端服務Node/Express/Sqlite
后端服務實作的比較簡單,僅僅只是為了滿足前端的最小需要,實作了登錄、檔案上傳下載、一些資料的增刪改查等基礎功能,正式后端服務中的權限、安全、性能并沒有考慮,主要是也不太熟悉,用Node做一個簡單的后端服務還是比較容易的,前端開發還是有必要了解一下,不僅要和前端同行卷,更要往外卷,卷起來!—— 跟自己卷就行了!(不得不)持續學習,(被迫)不斷進步!
??技術路線:
- Node.js,開發運行環境
v16.17.1
- express,Web組件
v4.18
- sqlite3,資料庫
??相關組件:
express.static
:靜態資源托管,express提供的,無需額外安裝,multer
:檔案上傳
??源代碼地址:Github / KWebNote,Gitee / KWebNote,后臺服務端代碼在目錄??server下,
01、資料庫Database
1.1、用什么資料庫?Sqlite
Node支持多種資料,官網Database integration,本專案采用的是Sqlite資料庫,Sqlite是一款輕量的關系型資料庫,無需安裝、無需配置、無需單獨啟動,SQLite是一種嵌入式資料庫,它的資料庫就是一個db庫檔案,極度輕量,該有的功能都有,可嵌入到多種語言中使用,當然也支持JS,引入Sqlite的JS庫“sqlite3
”即可進行資料庫增刪改查操作了,
???專案中的Sqlite資料庫檔案就一個db檔案“book_db.db ”單檔案20KB,
GUI管理工具推薦下載 SQLiteStudio,非常好用,免費開源,功能齊全,支持Windows、IOS、Linux,
1.2、資料庫結構設計
基于專案需求,設計了5個表,表結構相對比較簡單,設計比較也比較隨意,
???書籍資訊表“books”
編碼 | 名稱 | 描述/備注 |
---|---|---|
id | 編號ID | 主鍵,自增長 |
name | 書籍名稱 | |
catgory | 圖書分類編號 | 來自字典資料,字典型別dictype.code =bookType ,關聯字典資料dicdata.code |
tag | 促銷標簽 | 來自字典資料,字典型別dictype.code =bookTag ,關聯字典資料dicdata.code |
author | 作者 | |
price | 價格 | |
imgs | 圖片 | 圖片集合字串,逗號分割,最多8張 |
comments | 評論數 | 評論內容就模擬隨機產生了 |
introduction | 詳情介紹 | 富文本內容,長度最大8000,支持上傳圖片 |
status | 狀態 | 列舉值:正常、下架 |
createtime | 創建時間 | 時間戳 |
lasttime | 修改時間 | 時間戳 |
???訂單表“order”
編碼 | 名稱 | 描述/備注 |
---|---|---|
id | 編號ID | 主鍵,自增長 |
uid | 用戶id | 下單的用戶 |
money | 訂單金額 | |
products | 商品 | 購買的圖書商品串列,書名、數量、價格的Json字串 |
status | 狀態 | 列舉值:unpay(未支付)、canceled(已取消)、done(已完成) |
createtime | 創建時間 | 時間戳 |
INSERT INTO [order] (createtime,status,products,money,uid)
VALUES (1675319639624,'unpay','[{"name":"論語","price":155,"total":1},{"name":"論語2","price":15,"total":2}]',113,1);
資料:
id | uid | money | products | status | createtime |
---|---|---|---|---|---|
1 | 1 | 113 | [{"name":"論語","price":155,"total":1},{"name":"論語2","price":15,"total":2}] | unpay | 1675319639624 |
2 | 1 | 1334 | [{"name":"論語","price":155,"total":1},{"name":"論語2","price":15,"total":2}] | canceled | 1675319639624 |
3 | 2 | 333 | [{"name":"論語","price":155,"total":1},{"name":"論語2","price":15,"total":2}] | done | 1675319639624 |
???用戶表“user_info”
編碼 | 名稱 | 描述/備注 |
---|---|---|
id | 編號ID | 主鍵,自增長 |
name | 用戶名 | |
pwd | 密碼 | 明文存盤,沒有加密,實際專案中不會這么干 |
資料:
id | pwd | name |
---|---|---|
1 | 123 | admin |
2 | 123456 | ading |
3 | test | test |
???字典型別“dictype”
編碼 | 名稱 | 描述/備注 |
---|---|---|
id | ID | 主鍵,自增長 |
code | 型別編碼 | 不可重復,如booktype (圖書分類) |
name | 名稱 | |
tree | 是否樹形結構 | 1=樹形結構,0=非樹形結構,主要是區分資料的結構 |
資料:
id | code | name | tree |
---|---|---|---|
1 | bookTag | 商品標簽 | 0 |
2 | bookType | 書籍分類 | 1 |
???字典資料“dicdata”
編碼 | 名稱 | 描述/備注 |
---|---|---|
id | 編號ID | 主鍵,自增長 |
name | 名稱 | |
code | 型別code | 同dictype.code ,用于區分不同字典資料 |
pid | 父ID | 一級(根)的值為0,以此來判等根節點并組裝為樹 |
資料:
id | name | code | sort | pid |
---|---|---|---|---|
1 | 促銷 | bookTag | 1 | 0 |
2 | 熱賣 | bookTag | 2 | 0 |
3 | 新上市 | bookTag | 3 | 0 |
4 | 買它! | bookTag | 4 | 0 |
5 | 科技 | bookType | 1 | 0 |
6 | 計算機/網路 | bookType | 1 | 5 |
7 | 人文歷史 | bookType | 2 | 0 |
8 | 醫學12333 | bookType | 2 | 5 |
25 | 小說 | bookType | 1 | 7 |
26 | 歷史 | bookType | 2 | 7 |
02、創建專案
創建一個“server”目錄,就創建完畢了,后端服務做的比較簡陋,檔案結構也比較清晰,
- ??
api
目錄:服務端的api介面,使用Express的路由來構建,base.js
:基礎公共api,如登錄、首頁資料book.js
:書籍管理apifile.js
:檔案上傳apiorder.js
:訂單模塊apisystem.js
:系統管理模塊api,如字典管理
- ??
db
目錄:book_db.db
:sqlite資料庫檔案,就一個db檔案,非常輕量,db.js
:sqlite資料庫訪問的封裝,
- ??
file
目錄:上傳的檔案存盤在這里的, index.js
:入口JS檔案,組裝??api目錄下的API介面、注冊HTTP服務,
服務端運行也同樣簡單,用node啟動入口JS檔案index.js
即可,
node index.js
03、sqlite3資料庫api
安裝sqlite3
的Node組件:cnpm install sqlite3 -S
,在??server
目錄下運行,
資料庫的操作介面很簡單,指定sqlite的db檔案,申明一個sqlite3實體物件,就可干活了,主要就是執行sql(新增insert、修改update、洗掉delete)、查詢(select)資料!
let sqlite3 = require('sqlite3').verbose();
let db = new sqlite3.Database('file-name.db'); //指定sqlite的db檔案
//查詢,引數row為查詢的結果結合
db.all("select * from 表名",function(err,row){
console.log(row);
})
//執行sql:新增、修改、洗掉
const sql = "delete from dicdata where id=?";
const params = [req.body.id];
db.run(sql, params, function (error) { })
可以做一個簡單的封裝,統一回傳的資料結構,
db.queryData
:查詢資料db.executeSql
:執行sql:增、刪、修改
//加載sqlite并創建資料庫實體
let sqlite3 = require('sqlite3').verbose();
let db = new sqlite3.Database('./db/book_db.db');
// 回應資料結構
function ResponsData(error) {
this.status = error ? 'Error' : 'OK';
this.message = error ? error : null;
}
//例外處理
db.printError = function (error) {
if (error) console.error(error);
}
//查詢資料
db.queryData = https://www.cnblogs.com/anding/archive/2023/06/29/function (sql, params, callback) {
if (!params) params = {};
db.all(sql, params, function (error, rows) {
db.printError(error);
let resData = new ResponsData(error);
callback(resData, rows);
})
}
//執行sql:增、刪、修改
db.executeSql = function (sql, params, callback) {
db.run(sql, params, function (error) {
db.printError(error);
let resData = new ResponsData(error);
callback(resData);
})
}
module.exports = db;
??引數化:使用引數化單獨管理sql中的變數引數,更安全,這是防止SQL注入的基礎手段,
- 使用問號“?”作為引數的占位符,引數按照順序組裝為陣列,
insert into books values(NULL,?,?,?,?,?,?,?,?,?,?,?)
- 模糊查詢時,在引數中構造模糊查詢運算式:
wheresql = " where name like ?"; params.push("%" + req.body.name + "%");
更多SQL使用詳見Github / KWebNote,
04、Express開發后臺API
4.1、Express入門
express 是Node.js 的組件_(express /?k?spres/ 快速、快遞)_,一個快速、開放、極簡的 Web 開發框架, 提供一系列強大特性幫助你創建各種Web應用,使用非常簡便、靈活,用于搭建WEB服務,所以我們就用Express來搭建后端API服務,
- 1、安裝express:
cnpm install express -S
,在??server
目錄下運行, - 2、創建實體,添加介面、監聽埠,
- 3、運行,在命令列中用node命令運行該JS檔案,啟動Express服務:
node server.js
,
//加載組件
let express = require('express');
//創建一個服務端服務實體server
let server = new express();
//定義一個get介面
server.get('/hello', (req, res) => {
res.send('Hello World!')
})
//定義一個post介面
server.get('/send', (req, res) => {
console.log(req.body); //post發送的資料
})
//***** 配置監聽埠 *****/
server.listen(801, err => {
if (!err)
console.log('服務器啟動成功,地址:http://localhost:801')
})
啟動:node server.js
測驗:http://localhost:801/hello
4.2、Express路由/API介面
后端的API介面的封裝比較簡單了,監聽路由API地址,接收請求、處理(操作資料庫),然后回傳回應結果,為了更好管理后端的API,使用Express的路由express.Router()
來組織不同模塊的API介面,各個模塊的API可以單獨管理,然后統一組裝,
比如book.js
,圖書管理api:
//引入express
let express = require('express');
//獲取Express的路由
let router = express.Router();
//引入db庫
const db = require('../db/db.js');
//設定路由:獲取單個book資料,get方式
router.get('/book/id', (req, res) => {
//sql陳述句
let sql = "select id,name,author,introduction,imgs,status,catgory,price,tag,comments,createtime,lasttime from books where id =?";
//呼叫db封裝的查詢api,回傳資料
db.queryData(sql, [req.query.id], (resData, rows) => {
resData.data = https://www.cnblogs.com/anding/archive/2023/06/29/rows[0];
res.send(resData);
});
})
//設定路由:新增、修改,post方式
router.post('/book/save', (req, res) => {
let sql = '';
// 引數,在sql中用?占位(按照順序)
let params = [req.body.name, req.body.author, req.body.introduction, req.body.imgs, req.body.status, req.body.catgory, req.body.price, req.body.tag, req.body.comments, req.body.createtime ?? Date.now(), Date.now()];
//update 修改資料
if (req.body.id) {
sql = "update books set name=?,author=?,introduction=?,imgs=?,status=?,catgory=?,price=?,tag=?,comments=?,createtime=?,lasttime=? where id=?";
params.push(req.body.id);
}
else //insert 新增資料 (name,author,introduction,img,status)
sql = "insert into books values(NULL,?,?,?,?,?,?,?,?,?,?,?)";
db.executeSql(sql, params, resData =https://www.cnblogs.com/anding/archive/2023/06/29/> {
if (resData.status =='OK')
resData.message = '保存成功';
res.send(resData);
});
})
// 匯出路由router
module.exports = router;
在入口檔案index.js
中參考安裝book.js
的路由,
//加載組件
let express = require('express');
//創建一個服務端服務實體server
let server = new express();
// 書籍模塊api
const book = require('./api/book.js');
const path='/api';
server.use(path, book);
完整API介面詳見Github / KWebNote,
4.3、檔案的上傳
常用的圖片、Excel等附件的上傳,檔案本質上也是資料,同其他API介面一樣,通過POST方式提交檔案資料,HTML的FORM表單提交支持多種型別,其中multipart/form-data
混合型別就是專用于提交二進制檔案的,
??HTML中
<form>
表單enctype
:編碼型別(encode type),規定了form表單在發送到服務器時候編碼方式,
- application/x-www-form-urlencoded:編碼所有字符(默認),傳輸字符內容,
- multipart/form-data :混合型別, 表單中有檔案上傳時使用,
- text/plain:純文體,空格轉換為 “+” 加號,不對特殊字符編碼,
在Express中上傳檔案,使用中間件multer
,是專門用來處理復合表單multipart/form-data
資料,用來處理后端的檔案上傳,
- 安裝
multer
插件:cnpm i -S multer
,,在??server
目錄下運行, - 配置檔案上傳介面“/upload”:
let express = require('express');
let router = express.Router();
let multer = require('multer');
// 申明multer實體,并組態檔保存路徑、檔案名
let upload = multer({
storage: multer.diskStorage({
//檔案存盤位置
destination: function (req, file, callback) {
callback(null, './file/')
},
//檔案命名
filename: function (req, file, callback) {
callback(null, Date.now() + '-' + file.originalname);
}
})
});
// 組態檔上傳介面
router.post('/upload', upload.single('file'), function (req, res, next) {
if (!req.file) {
res.json({ status: 'Error', message: '檔案上傳錯誤:檔案不存在' });
return;
}
let file = req.file;
//回傳回應訊息:檔案的相對URL地址
res.json({
status: 'OK',
name: file.filename,
url: '/file/' + file.filename,
});
});
測驗一下,注意欄位名稱應為“file”,與后端保持一致,
05、托管靜態資源/部署網站
5.1、靜態資源托管
前面上傳了檔案,那客戶端如何訪問靜態檔案呢?官方檔案:利用 Express 托管靜態檔案,
在Node中使用express
自帶的靜態資源管理插件,即可托管靜態檔案,如圖片、網頁檔案等,因此不僅可以實作檔案下載,還支持部署靜態網站,
// 使用內置的“express.static”實作靜態檔案代理,引數為資源地址,
//圖片靜態資源,第一個引數為url路由,“./file”為存放檔案的檔案夾
server.use('/file', express.static('./file'));
這就完了?是的,很簡單!訪問一下試試:
http://localhost:3000/file/f1.jpg
http://localhost:3000/file/1676274037570-gif007.gif
5.2、部署網站/前端路由重定向
前面通過express.static
可以托管靜態資源,也就意味著可以部署前端網站,可以把編譯好的管理后臺“book_admin”通過Node來部署試試,
//部署管理后臺網站
server.use('/bookadmin', express.static('./book_admin'));
登錄可用,頁面訪問正常!
重繪一下,糟了,出錯了,無法訪問此頁面~
?這是什么原因呢?
- Node后端只配置了路由地址“
/bookadmin
”,沒有配置“/bookadmin/home
”的路由,后端就沒人回應, - “
/home
”是前端路由,前端路由vue-router
使用的是history
模式,如果用hash
模式就沒問題,
?怎么解決?
- 方法1:前端路由改用
hash
模式,/bookadmin#home
,hash值#home
后端不會管,前端處理, - 方法2:后端處理,重定向到單頁應用的頁面即可,具體方式也有多個:
- 方式1:參考組件“connect-history-api-fallback”解決,
- 方式2:強制重定向到主頁面
index.html
,代碼如下:
//管理后臺"book_admin"的部署
//靜態資源
server.use('/bookadmin', express.static('./book_admin'));
const fs = require('fs')
const rpath = require('path')
//前端路由的重定向
server.get('/bookadmin/*', function(req, res) {
const html = fs.readFileSync(rpath.resolve(__dirname, '../server/book_admin/index.html'), 'utf-8')
res.send(html)
})
重啟node服務解決
D:\Project_Files\kwongGit\KWebNote\server>node index.js
服務器啟動成功,地址:http://localhost:3000
參考資料:
- Express 中文網
- NodeJS中使用SQLite3
- 還有一個更快的sqlite庫:better-sqlite3
??著作權申明:著作權所有@安木夕,本文內容僅供學習,歡迎指正、交流,轉載請注明出處!原文編輯地址-語雀
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/556349.html
標籤:其他
上一篇:XHbuilder 需要的 ipa 簽名,超詳細的教程,你不看吃虧的是自己!
下一篇:返回列表