webpack4+express+mongodb+vue 实现增删改查

在讲解以前,咱们先来看看效果以下所示:javascript

1)整个页面的效果以下:css

2) 新增数据效果以下:html

3) 新增成功以下:vue

4) 编辑数据效果以下:java

 

5) 编辑成功效果以下:node

 

6) 删除数据效果以下:webpack

 

7) 删除成功效果以下:git

 

8) 查询效果以下:github

 

如上的效果,下面咱们仍是和以前同样,先看看咱们整个项目的架构以下所示:web

### 目录结构以下: 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类库实现简单的增删改查
(http://www.javashuo.com/article/p-elyqbekj-h.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类库的话,能够返回来看我这篇文章(http://www.javashuo.com/article/p-elyqbekj-h.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)实现增删改查路由接口

以下全部的增删改查的代码以下(若是代码看不懂的话,仍是返回看这篇文章便可:http://www.javashuo.com/article/p-elyqbekj-h.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的接口方法。

查看github代码

相关文章
相关标签/搜索