webpack4+express+mongodb+vue實(shí)現(xiàn)增刪改查的示例
在講解之前,我們先來(lái)看看效果如下所示:
1)整個(gè)頁(yè)面的效果如下:

2) 新增數(shù)據(jù)效果如下:

3) 新增成功如下:

4) 編輯數(shù)據(jù)效果如下:

5) 編輯成功效果如下:

6) 刪除數(shù)據(jù)效果如下:

7) 刪除成功效果如下:

8) 查詢效果如下:

如上的效果,下面我們還是和之前一樣,先看看我們整個(gè)項(xiàng)目的架構(gòu)如下所示:
### 目錄結(jié)構(gòu)如下: demo1 # 工程名 | |--- dist # 打包后生成的目錄文件 | |--- node_modules # 所有的依賴包 | |----database # 數(shù)據(jù)庫(kù)相關(guān)的文件目錄 | | |---db.js # mongoose類庫(kù)的數(shù)據(jù)庫(kù)連接操作 | | |---user.js # Schema 創(chuàng)建模型 | | |---addAndDelete.js # 增刪改查操作 | |--- app | | |---index | | | |-- views # 存放所有vue頁(yè)面文件 | | | | |-- list.vue # 列表數(shù)據(jù) | | | | |-- index.vue | | | |-- components # 存放vue公用的組件 | | | |-- js # 存放js文件的 | | | |-- css # 存放css文件 | | | |-- store # store倉(cāng)庫(kù) | | | | |--- actions.js | | | | |--- mutations.js | | | | |--- state.js | | | | |--- mutations-types.js | | | | |--- index.js | | | | | | | | |-- app.js # vue入口配置文件 | | | |-- router.js # 路由配置文件 | |--- views | | |-- index.html # html文件 | |--- webpack.config.js # webpack配置文件 | |--- .gitignore | |--- README.md | |--- package.json | |--- .babelrc # babel轉(zhuǎn)碼文件 | |--- app.js # express入口文件
如上目錄架構(gòu)是我現(xiàn)在整個(gè)項(xiàng)目的架構(gòu)圖,其中database目錄下存放 db.js ,該文件最主要是使用 mongoose 數(shù)據(jù)庫(kù)連接操作,user.js 文件是創(chuàng)建一個(gè)Schema模型,也可以理解為表結(jié)構(gòu),addAndDelete.js 文件內(nèi)部實(shí)現(xiàn)增刪改查操作。
先在本地把數(shù)據(jù)庫(kù)搭建起來(lái)后,再慢慢學(xué)習(xí)哦,我這邊文章實(shí)現(xiàn) vue+mongodb 實(shí)現(xiàn)增刪改查也是基于上面這些文章的基礎(chǔ)之上來(lái)進(jìn)行的,特別是居于這篇 使用Mongoose類庫(kù)實(shí)現(xiàn)簡(jiǎn)單的增刪改查
( http://www.dhdzp.com/article/150381.htm) 來(lái)進(jìn)行的,增刪改查操作及使用Schema 創(chuàng)建模型 都是居于這篇文章的基礎(chǔ)之上再進(jìn)行使用vue來(lái)重構(gòu)下的。本篇文章也是依賴于餓了么vue組件進(jìn)行開(kāi)發(fā)的。
先來(lái)分別講下代碼結(jié)構(gòu)吧:
1)使用express創(chuàng)建服務(wù)器
首先我們?cè)陧?xiàng)目的根目錄新建app.js, 該app.js 主要實(shí)現(xiàn)的功能是 啟動(dòng) 3001端口的服務(wù)器,并且使用 bodyParser進(jìn)行解析數(shù)據(jù),如下代碼:
// 引入express模塊
const express = require('express');
// 創(chuàng)建app對(duì)象
const app = express();
const addAndDelete = require('./database/addAndDelete');
const bodyParser = require("body-parser")
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
// 使用
app.use('/api', addAndDelete);
// 定義服務(wù)器啟動(dòng)端口
app.listen(3001, () => {
console.log('app listening on port 3001');
});
進(jìn)入我們項(xiàng)目的根目錄后,運(yùn)行 node app.js 即可創(chuàng)建一個(gè) http://127.0.0.1:3001 的服務(wù)器頁(yè)面了。
2)數(shù)據(jù)庫(kù)連接
在database/db.js 鏈接 mongodb://localhost:27017/dataDb 數(shù)據(jù)庫(kù)。使用mongoose類庫(kù),如果不理解mongoose類庫(kù)的話,可以返回來(lái)看我這篇文章(http://www.dhdzp.com/article/150381.htm)如下代碼:
var mongoose = require('mongoose');
var DB_URL = 'mongodb://localhost:27017/dataDb';
/* 鏈接 */
mongoose.connect(DB_URL);
/* 鏈接成功 */
mongoose.connection.on('connected', function() {
console.log('Mongoose connection open to ' + DB_URL);
});
// 鏈接異常
mongoose.connection.on('error', function(err) {
console.log('Mongoose connection error:' + err);
});
// 鏈接斷開(kāi)
mongoose.connection.on('disconnected', function() {
console.log('Mongoose connection disconnected');
});
module.exports = mongoose;
3)創(chuàng)建數(shù)據(jù)模型
在database/user.js 中使用 Schema創(chuàng)建一個(gè)模型,也就是說(shuō)上面的 dataDb是數(shù)據(jù)庫(kù)名稱,這邊使用schema創(chuàng)建的模型就是表結(jié)構(gòu)的字段,有如下 name, age, sex 三個(gè)字段,代碼如下所示:
/*
定義一個(gè)user的Schema
*/
const mongoose = require('./db.js');
const Schema = mongoose.Schema;
// 創(chuàng)建一個(gè)模型
const UserSchema = new Schema({
name: { type: String }, // 屬性name,類型為String
age: { type: Number, default: 30 }, // 屬性age,類型為Number,默認(rèn)值為30
sex: { type: String }
});
// 導(dǎo)出model模塊
const User = module.exports = mongoose.model('User', UserSchema);
4)實(shí)現(xiàn)增刪改查路由接口
如下所有的增刪改查的代碼如下(如果代碼看不懂的話,還是返回看這篇文章即可: http://www.dhdzp.com/article/150381.htm):
// 引入express 模塊
const express = require('express');
const router = express.Router();
// 引入user.js
const User = require('./user');
// 新增一條數(shù)據(jù) 接口為add
router.post('/add', (req, res) => {
const user = new User({
name: req.body.name,
age: req.body.age,
sex: req.body.sex
});
user.save((err, docs) => {
if (err) {
res.send({ 'code': 1, 'errorMsg': '新增失敗' });
} else {
res.send({ "code": 0, 'message': '新增成功' });
}
});
});
// 查詢數(shù)據(jù)
router.post('/query', (req, res) => {
const name = req.body.name,
age = req.body.age,
sex = req.body.sex;
const obj = {};
if (name !== '') {
obj['name'] = name;
}
if (age !== '') {
obj['age'] = age;
}
if (sex !== '') {
obj['sex'] = sex;
}
User.find(obj, (err, docs) => {
if (err) {
res.send({ 'code': 1, 'errorMsg': '查詢失敗' });
} else {
res.send(docs);
}
});
});
// 根據(jù) _id 刪除數(shù)據(jù)
router.post('/del', (req, res) => {
const id = req.body.id;
// 根據(jù)自動(dòng)分配的 _id 進(jìn)行刪除
const whereid = { '_id': id };
User.remove(whereid, (err, docs) => {
if (err) {
res.send({ 'code': 1, 'errorMsg': '刪除失敗' });
} else {
res.send(docs);
}
})
});
// 更新數(shù)據(jù)
router.post('/update', (req, res) => {
console.log(req.body)
// 需要更新的數(shù)據(jù)
const id = req.body.id,
name = req.body.name,
age = req.body.age,
sex = req.body.sex;
const updateStr = {
name: name,
age: age,
sex: sex
};
const ids = {
_id: id
};
console.log(ids);
User.findByIdAndUpdate(ids, updateStr, (err, docs) => {
if (err) {
res.send({ 'code': 1, 'errorMsg': '更新失敗' });
} else {
res.send(docs);
}
});
});
module.exports = router;
5)搭建vue頁(yè)面,如何通過(guò)頁(yè)面的接口請(qǐng)求?
在app/index/views/list.vue 基本代碼如下(所有的html代碼是基于餓了么vue組件的,最主要一些form表單組件的用法及表格的插件及彈窗的插件),代碼如下:
<style lang="stylus">
#list-container
width 100%
</style>
<template>
<div id="list-container" style="margin:20px auto">
<div style="width:100%;overflow:hidden;">
<el-form ref="form" label-width="80px">
<div style="float:left;width:20%">
<el-form-item label="姓名">
<el-input v-model="name"></el-input>
</el-form-item>
</div>
<div style="float:left;width:20%">
<el-form-item label="年齡">
<el-input v-model="age"></el-input>
</el-form-item>
</div>
<div style="float:left;width:20%">
<el-form-item label="性別">
<el-select v-model="sex">
<el-option
v-for="item in options2"
:key="item.value"
:label="item.label"
:value="item.value">
</el-option>
</el-select>
</el-form-item>
</div>
<el-button type="primary" style="margin-left:20px;" @click="query(true)">查 詢</el-button>
<el-button type="success" @click="newAdd">新 增</el-button>
</el-form>
</div>
<div style="width:90%; margin: 0 auto; border: 1px solid #ebebeb; border-radius: 3px;overflow:hidden;">
<el-table
:data="tableData"
style="width: 100%">
<el-table-column
prop="name"
label="姓名"
width="180">
</el-table-column>
<el-table-column
prop="age"
label="年齡"
width="180">
</el-table-column>
<el-table-column
prop="sex"
label="性別">
</el-table-column>
<el-table-column
fixed="right"
label="操作"
width="100">
<template slot-scope="scope">
<el-button type="text" size="small" @click="editFunc(scope.row)">編輯</el-button>
<el-button type="text" size="small" @click="delFunc(scope.row)">刪除</el-button>
</template>
</el-table-column>
</el-table>
</div>
<el-dialog
title="新增"
:visible.sync="dialogVisible"
width="30%">
<el-form label-width="40px">
<div style="float:left;width:100%">
<el-form-item label="姓名">
<el-input v-model="add.name"></el-input>
</el-form-item>
</div>
<div style="float:left;width:100%">
<el-form-item label="年齡">
<el-input v-model="add.age"></el-input>
</el-form-item>
</div>
<div style="float:left;width:100%">
<el-form-item label="性別">
<el-select v-model="add.sex">
<el-option
v-for="item in options2"
:key="item.value"
:label="item.label"
:value="item.value">
</el-option>
</el-select>
</el-form-item>
</div>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="dialogVisible = false">取 消</el-button>
<el-button type="primary" @click="addConfirm">確 定</el-button>
</span>
</el-dialog>
<el-dialog
title="編輯"
:visible.sync="dialogVisible2"
width="30%">
<el-form label-width="40px">
<div style="float:left;width:100%">
<el-form-item label="姓名">
<el-input v-model="update.name"></el-input>
</el-form-item>
</div>
<div style="float:left;width:100%">
<el-form-item label="年齡">
<el-input v-model="update.age"></el-input>
</el-form-item>
</div>
<div style="float:left;width:100%">
<el-form-item label="性別">
<el-select v-model="update.sex">
<el-option
v-for="item in options2"
:key="item.value"
:label="item.label"
:value="item.value">
</el-option>
</el-select>
</el-form-item>
</div>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="dialogVisible = false">取 消</el-button>
<el-button type="primary" @click="editConfirm">確 定</el-button>
</span>
</el-dialog>
<el-dialog
title="提示"
:visible.sync="dialogVisible3"
width="30%">
<div>是否確認(rèn)刪除?</div>
<span slot="footer" class="dialog-footer">
<el-button @click="dialogVisible3 = false">取 消</el-button>
<el-button type="primary" @click="delConfirm">確 定</el-button>
</span>
</el-dialog>
</div>
</template>
<script type="text/javascript">
export default {
data() {
return {
formLabelWidth: '120px',
name: '',
age: '',
sex: '',
options2: [
{
value: '1',
label: '男'
}, {
value: '2',
label: '女'
}
],
tableData: [],
// 新增頁(yè)面
add: {
name: '',
age: '',
sex: ''
},
// 修改頁(yè)面
update: {
name: '',
age: '',
sex: ''
},
dialogVisible: false,
dialogVisible2: false,
dialogVisible3: false,
row: null,
_id: ''
}
},
created() {
this.query();
},
methods: {
setData(datas) {
if (datas.length > 0) {
for (let i = 0; i < datas.length; i++) {
if (datas[i].sex * 1 === 1) {
this.$set(datas[i], 'sex', '男');
} else if (datas[i].sex * 1 === 2) {
this.$set(datas[i], 'sex', '女');
}
}
}
return datas;
},
// 查詢數(shù)據(jù)
query(isquery) {
const obj = {
name: this.name,
age: this.age,
sex: this.sex
};
this.$http.post('/api/query', obj).then((res) => {
if (res.ok) {
this.tableData = res.body ? this.setData(res.body) : [];
if (isquery) {
this.$message({
message: '查詢成功',
type: 'success'
});
}
} else {
if (isquery) {
this.$message({
message: '查詢失敗',
type: 'warning'
});
}
this.tableData = [];
}
});
},
newAdd() {
this.dialogVisible = true;
},
editFunc(row) {
this.dialogVisible2 = true;
this._id = row._id;
this.$set(this.$data.update, 'name', row.name);
this.$set(this.$data.update, 'age', row.age);
this.$set(this.$data.update, 'sex', row.sex);
this.row = row;
},
delFunc(row) {
this.dialogVisible3 = true;
console.log(row);
this.row = row;
},
// 編輯頁(yè)面提交
editConfirm() {
const id = this._id,
name = this.update.name,
age = this.update.age,
sex = this.update.sex;
const obj = {
id: id,
name: name,
age: age,
sex: sex
};
this.$http.post('/api/update', obj).then((res) => {
if (res.ok) {
// 刪除成功
this.$message({
message: '更新成功',
type: 'success'
});
// 重新請(qǐng)求下查詢
this.query(false);
} else {
// 刪除成功
this.$message({
message: '更新失敗',
type: 'success'
});
}
this.dialogVisible2 = false;
});
},
// 刪除提交
delConfirm() {
const obj = {
'id': this.row._id
};
this.$http.post('/api/del', obj).then((res) => {
console.log(res.body)
if (res.body.ok) {
// 刪除成功
this.$message({
message: '刪除成功',
type: 'success'
});
// 成功后,觸發(fā)重新查詢下數(shù)據(jù)
this.query();
} else {
// 刪除失敗
this.$message({
message: res.body.errorMsg,
type: 'warning'
});
}
this.dialogVisible3 = false;
});
},
// 新增提交
addConfirm() {
// 新增的時(shí)候,姓名,年齡,性別 不能為空,這里就不判斷了。。。
const obj = {
name: this.add.name,
age: this.add.age,
sex: this.add.sex
};
this.$http.post('/api/add', obj).then((res) => {
console.log(111);
console.log(res);
if (res.body.code === 0) {
this.$message({
message: '新增成功',
type: 'success'
});
// 成功后,觸發(fā)重新查詢下數(shù)據(jù)
this.query();
} else {
this.$message({
message: res.body.errorMsg,
type: 'warning'
});
}
this.dialogVisible = false;
});
}
}
}
</script>
6. 解決跨域問(wèn)題,及接口如何訪問(wèn)的?
首先我們是使用express啟動(dòng)的是 http://127.0.0.1:3001 服務(wù)器的,但是在我們的webpack中使用的是8081端口的,也就是說(shuō)頁(yè)面訪問(wèn)的是http://127.0.0.1:8081/ 這樣訪問(wèn)的話,因此肯定會(huì)存在接口跨域問(wèn)題的,因此我們需要在webpack中使用 devServer.proxy 配置項(xiàng)配置一下,如下代碼配置:
module.exports = {
devServer: {
port: 8081,
// host: '0.0.0.0',
headers: {
'X-foo': '112233'
},
inline: true,
overlay: true,
stats: 'errors-only',
proxy: {
'/api': {
target: 'http://127.0.0.1:3001',
changeOrigin: true // 是否跨域
}
}
},
}
因?yàn)槲襩ist.vue頁(yè)面所有的請(qǐng)求都是類似于這樣請(qǐng)求的 this.$http.post('/api/query', obj); 因此當(dāng)我使用 /api/query請(qǐng)求的話,它會(huì)被代理到 http://127.0.0.1:3001/api/query, 這樣就可以解決跨域的問(wèn)題了,同時(shí)我們?cè)陧?xiàng)目的根目錄中的 將路由應(yīng)用到 app.js 中,有如下這句代碼:
const addAndDelete = require('./database/addAndDelete');
app.use('/api', addAndDelete);
當(dāng)請(qǐng)求http://127.0.0.1:3001/api/query的時(shí)候,會(huì)自動(dòng)使用 addAndDelete.js 中的 /query的接口方法。
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- express使用Mongoose連接MongoDB操作示例【附源碼下載】
- Node+Express+MongoDB實(shí)現(xiàn)登錄注冊(cè)功能實(shí)例
- 零基礎(chǔ)搭建Node.js、Express、Ejs、Mongodb服務(wù)器及應(yīng)用開(kāi)發(fā)入門(mén)
- vue+socket.io+express+mongodb 實(shí)現(xiàn)簡(jiǎn)易多房間在線群聊示例
- express+vue+mongodb+session 實(shí)現(xiàn)注冊(cè)登錄功能
- 如何優(yōu)雅的在一臺(tái)vps(云主機(jī))上面部署vue+mongodb+express項(xiàng)目
- nodejs連接mongodb數(shù)據(jù)庫(kù)實(shí)現(xiàn)增刪改查
- Java連接MongoDB進(jìn)行增刪改查的操作
- mongodb增刪改查詳解_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理
- MongoDB簡(jiǎn)單操作示例【連接、增刪改查等】
- Node.js對(duì)MongoDB進(jìn)行增刪改查操作的實(shí)例代碼
- express+mongoose實(shí)現(xiàn)對(duì)mongodb增刪改查操作詳解
相關(guān)文章
Element-ui?Layout布局(Row和Col組件)的實(shí)現(xiàn)
我們?cè)趯?shí)際開(kāi)發(fā)中遇到一些布局的時(shí)候會(huì)用到Layout布局,本文就詳細(xì)的介紹了Element-ui?Layout布局(Row和Col組件)的實(shí)現(xiàn),具有一定的參考價(jià)值,感興趣的可以了解一下2021-12-12
Vue路由組件的緩存keep-alive和include屬性的具體使用
:瀏覽器頁(yè)面在進(jìn)行切換時(shí),原有的路由組件會(huì)被銷毀,通過(guò)緩存可以保存被切換的路由組件,本文主要介紹了Vue路由組件的緩存keep-alive和include屬性的具體使用,感興趣的可以了解一下2023-11-11
vue中swiper開(kāi)啟loop后,點(diǎn)擊事件不響應(yīng)的解決方案
這篇文章主要介紹了vue中swiper開(kāi)啟loop后,點(diǎn)擊事件不響應(yīng)的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-09-09
vue利用axios來(lái)完成數(shù)據(jù)的交互
這篇文章主要介紹了vue利用axios來(lái)完成數(shù)據(jù)的交互,本文通過(guò)實(shí)例代碼給大家講解數(shù)據(jù)交互方法及安裝方法,需要的朋友可以參考下2018-03-03
解決Vue 項(xiàng)目打包后favicon無(wú)法正常顯示的問(wèn)題
今天小編就為大家分享一篇解決Vue 項(xiàng)目打包后favicon無(wú)法正常顯示的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-09-09
vue3+electron12+dll開(kāi)發(fā)客戶端配置詳解
本文將結(jié)合實(shí)例代碼,介紹vue3+electron12+dll客戶端配置,對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2021-06-06
vue數(shù)據(jù)傳遞--我有特殊的實(shí)現(xiàn)技巧
這篇文章主要介紹了vue數(shù)據(jù)傳遞一些特殊梳理技巧,需要的朋友可以參考下2018-03-03
Vue中的數(shù)據(jù)驅(qū)動(dòng)解釋
這篇文章主要為大家介紹了Vue中的數(shù)據(jù)驅(qū)動(dòng)解釋,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-12-12

