在講解之前,我們先來看看效果如下所示:
1)整個頁面的效果如下:
2) 新增資料效果如下:
3) 新增成功如下:
4) 編輯資料效果如下:
5) 編輯成功效果如下:
6) 刪除資料效果如下:
7) 刪除成功效果如下:
8) 查詢效果如下:
如上的效果,下面我們還是和之前一樣,先看看我們整個專案的架構如下所示:
### 目錄結構如下: demo1 # 工程名 | |--- dist # 打包後生成的目錄檔案 | |--- node_modules # 所有的依賴包 | |----database # 資料庫相關的檔案目錄 | | |---db.js # mongoose類庫的資料庫連線操作 | | |---user.js # Schema 建立模型 | | |---addAndDelete.js # 增刪改查操作 | |--- app | | |---index | | | |-- views # 存放所有vue頁面檔案 | | | | |-- list.vue # 列表資料 | | | | |-- index.vue | | | |-- components # 存放vue公用的元件 | | | |-- js # 存放js檔案的 | | | |-- css # 存放css檔案 | | | |-- store # store倉庫 | | | | |--- 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轉碼檔案 | |--- app.js # express入口檔案
如上目錄架構是我現在整個專案的架構圖,其中database目錄下存放 db.js ,該檔案最主要是使用 mongoose 資料庫連線操作,user.js 檔案是建立一個Schema模型,也可以理解為表結構,addAndDelete.js 檔案內部實現增刪改查操作。
如果對mongodb資料庫相關的知識點不是很熟悉的話,可以先看下我之前寫的一些關於mongodb文章(https://www.cnblogs.com/tugenhua0707/category/1240772.html), 先在本地把資料庫搭建起來後,再慢慢學習哦,我這邊文章實現 vue+mongodb 實現增刪改查也是基於上面這些文章的基礎之上來進行的,特別是居於這篇 使用Mongoose類庫實現簡單的增刪改查
(https://www.cnblogs.com/tugenhua0707/p/9256605.html) 來進行的,增刪改查操作及使用Schema 建立模型 都是居於這篇文章的基礎之上再進行使用vue來重構下的。本篇文章也是依賴於餓了麼vue元件進行開發的。
先來分別講下程式碼結構吧:
1)使用express建立伺服器
首先我們在專案的根目錄新建app.js, 該app.js 主要實現的功能是 啟動 3001埠的伺服器,並且使用 bodyParser進行解析資料,如下程式碼:
// 引入express模組 const express = require('express'); // 建立app物件 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); // 定義伺服器啟動埠 app.listen(3001, () => { console.log('app listening on port 3001'); });
進入我們專案的根目錄後,執行 node app.js 即可建立一個 http://127.0.0.1:3001 的伺服器頁面了。
2)資料庫連線
在database/db.js 連結 mongodb://localhost:27017/dataDb 資料庫。使用mongoose類庫,如果不理解mongoose類庫的話,可以返回來看我這篇文章(https://www.cnblogs.com/tugenhua0707/p/9256605.html)如下程式碼:
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); }); // 連結斷開 mongoose.connection.on('disconnected', function() { console.log('Mongoose connection disconnected'); }); module.exports = mongoose;
3)建立資料模型
在database/user.js 中使用 Schema建立一個模型,也就是說上面的 dataDb是資料庫名稱,這邊使用schema建立的模型就是表結構的欄位,有如下 name, age, sex 三個欄位,程式碼如下所示:
/* 定義一個user的Schema */ const mongoose = require('./db.js'); const Schema = mongoose.Schema; // 建立一個模型 const UserSchema = new Schema({ name: { type: String }, // 屬性name,型別為String age: { type: Number, default: 30 }, // 屬性age,型別為Number,預設值為30 sex: { type: String } }); // 匯出model模組 const User = module.exports = mongoose.model('User', UserSchema);
4)實現增刪改查路由介面
如下所有的增刪改查的程式碼如下(如果程式碼看不懂的話,還是返回看這篇文章即可:https://www.cnblogs.com/tugenhua0707/p/9256605.html):
// 引入express 模組 const express = require('express'); const router = express.Router(); // 引入user.js const User = require('./user'); // 新增一條資料 介面為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': '新增成功' }); } }); }); // 查詢資料 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); } }); }); // 根據 _id 刪除資料 router.post('/del', (req, res) => { const id = req.body.id; // 根據自動分配的 _id 進行刪除 const whereid = { '_id': id }; User.remove(whereid, (err, docs) => { if (err) { res.send({ 'code': 1, 'errorMsg': '刪除失敗' }); } else { res.send(docs); } }) }); // 更新資料 router.post('/update', (req, res) => { console.log(req.body) // 需要更新的資料 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頁面,如何通過頁面的介面請求?
在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>是否確認刪除?</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: [], // 新增頁面 add: { name: '', age: '', sex: '' }, // 修改頁面 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; }, // 查詢資料 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; }, // 編輯頁面提交 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' }); // 重新請求下查詢 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' }); // 成功後,觸發重新查詢下資料 this.query(); } else { // 刪除失敗 this.$message({ message: res.body.errorMsg, type: 'warning' }); } this.dialogVisible3 = false; }); }, // 新增提交 addConfirm() { // 新增的時候,姓名,年齡,性別 不能為空,這裡就不判斷了。。。 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' }); // 成功後,觸發重新查詢下資料 this.query(); } else { this.$message({ message: res.body.errorMsg, type: 'warning' }); } this.dialogVisible = false; }); } } } </script>
6. 解決跨域問題,及介面如何訪問的?
首先我們是使用express啟動的是 http://127.0.0.1:3001 伺服器的,但是在我們的webpack中使用的是8081埠的,也就是說頁面訪問的是http://127.0.0.1:8081/ 這樣訪問的話,因此肯定會存在介面跨域問題的,因此我們需要在webpack中使用 devServer.proxy 配置項配置一下,如下程式碼配置:
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 // 是否跨域 } } }, }
因為我list.vue頁面所有的請求都是類似於這樣請求的 this.$http.post('/api/query', obj); 因此當我使用 /api/query請求的話,它會被代理到 http://127.0.0.1:3001/api/query, 這樣就可以解決跨域的問題了,同時我們在專案的根目錄中的 將路由應用到 app.js 中,有如下這句程式碼:
const addAndDelete = require('./database/addAndDelete');
app.use('/api', addAndDelete);
當請求http://127.0.0.1:3001/api/query的時候,會自動使用 addAndDelete.js 中的 /query的介面方法。