Vue.js + Node.js + Express + MySQL 案例: 创建 CRUD 应用之前端

后端地址为:https://blog.csdn.net/renxingwu2008/article/details/123672189

1、创建前端工程
npm init vite@latest hr_client(项目名称)
vue(选择vue)
下一步
2、初始化并运行项目(注意:默认端口为:3000,这里要与后端端口有所区分)
cd hr_client
npm install
npm run dev
3、安装Element plus
npm install element-plus --save
  • 全局引入
import { createApp } from 'vue'
import App from './App.vue'

// 全局引入Element plus
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
// 这里添加 .use(ElementPlus)
createApp(App).use(ElementPlus).mount('#app')
4、安装vue-router
npm install vue-router
  • 全局引用
import { createApp } from 'vue'
import App from './App.vue'

import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
// 全局引用 vue-router
import router from './route'

// 这里添加 .use(router)
createApp(App).use(ElementPlus).use(router).mount('#app')
5、安装axios
npm install axios
6、工程目录src下创建http-common.js
import axios from 'axios'
export default axios.create({
  // 后端端口号调整为:9000
  baseURL: 'http://localhost:9000/api',
  headers: {
    'Content-type': 'application/json'
  }
})
7、创建vue文件
  1. 修改工程目录下的App.vue内容,将其定为导航页;
  2. 将工程目录下的components目录重命名为:views
  3. 同时在其目录下创建HR目录;
  4. HR目录下创建Users目录;
  5. Users目录下创建vue文件:UsersList.vueAddUser.vue文件
8、配置路由
  • 工程src目录下 创建route目录,目录中创建index.js
import { createWebHistory, createRouter } from "vue-router";
const routes =  [
  {
    path: "/",
    alias: "/users",
    name: "users",
    component: () => import("../views/HR/Users/UsersList.vue")
  },
  {
    path: '/add',
    name: 'add',
    component: () => import('../views/HR/Users/AddUser.vue')
  }
];
const router = createRouter({
  history: createWebHistory(),
  routes,
});
export default router;
9、配置服务层

工程src目录下 创建services目录,目录中创建UserDataService.js

import http from '../http-common'
class UserDataService {
  // 获取全部用户
  getAll () {
    return http.get('/users')
  }
  // 根据ID获取指定用户信息
  get (id) {
    return http.get(`/users/${id}`)
  }
  // 创建一条用户记录
  create (data) {
    return http.post('/users', data)
  }
  // 更新一条用户记录
  update (id, data) {
    return http.put(`/users/${id}`, data)
  }
  // 删除指定ID用户记录
  delete (id) {
    return http.delete(`/users/${id}`)
  }
  // 删除所有用户记录(业务上估计用不上)
  deleteAll () {
    return http.delete('/users')
  }
  // 根据用户中文名称查找用户信息
  findByUserCN (userCN) {
    return http.get(`/users?userCN=${userCN}`)
  }
}
export default new UserDataService()
10、编辑vue文件
  1. App.vue
<template>
  <div>
    <div id="nav">
      <el-menu
        class="el-menu-demo"
        background-color="#545c64"
        mode="horizontal"
        text-color="#fff"
        active-text-color="#ffd04b"
      >
        <el-menu-item index="1">简单案例</el-menu-item>
        <el-menu-item index="2"><router-link to="/users">用户列表</router-link></el-menu-item>
        <el-menu-item index="3"><router-link to="/add">添加用户</router-link></el-menu-item>
      </el-menu>
    </div>
    <router-view />
  </div>
</template>
<style>
a {
  text-decoration: none;
}
.router-link-active {
  text-decoration: none;
}
</style>
  1. UserList.vue(注意:修改提交的地方有些问题,抽空修改下)
<template>
  <div>
    <!-- 用户信息列表区域 -->
    <el-table :data="users" scope="scope" style="width: 100%">
      <el-table-column prop="id" label="ID" width="50" v-if="false" />
      <el-table-column prop="userId" label="用户编号" width="100" />
      <el-table-column prop="userCN" label="用户姓名" width="100" />
      <el-table-column prop="sex" label="用户性别" width="100" />
      <el-table-column prop="mobile" label="电话号码" width="180" />
      <el-table-column prop="telNo" label="办公电话" width="180" />
      <el-table-column prop="email" label="用户邮箱" width="300" />
      <el-table-column prop="roomNO" label="房间号" width="180" />
      <el-table-column prop="address" label="家庭地址" />
      <el-table-column label="操作" width="200">
        <template v-slot="scope">
          <el-button type="primary" @click="editUser(scope.row)">修改</el-button>
          <el-button type="danger" @click="delUser(scope.row.id)">删除</el-button>
        </template>
      </el-table-column>
    </el-table>
    <!-- 修改用户信息弹窗区域 -->
    <el-dialog v-model="dialogFormVisible" :show-close="false">
      <div class="head"></div>
      <el-card
      class="box-card"
      :body-style="{ padding: '20px', width: '80%', margin: '0 auto' }">
      <!-- 卡片头部分 -->
      <template #header>
        <div>
          添加用户信息
        </div>
      </template>
      <!-- 表单字段部分 -->
      <el-form label-position="right" label-width="100%">
        <el-divider content-position="left">基本信息</el-divider>
        <el-row>
          <el-col :span="4">
            <div><el-form-item label="用户编号:"></el-form-item></div>
          </el-col>
          <el-col :span="8">
            <div><el-input v-model="userData.userId" disabled></el-input></div>
          </el-col>
          <el-col :span="4">
            <div><el-form-item label="用户账号:"></el-form-item></div>
          </el-col>
          <el-col :span="8">
            <div><el-input v-model="userData.userName"></el-input></div>
          </el-col>
        </el-row>
        <el-row>
          <el-col :span="4">
            <div><el-form-item label="中文名称:"></el-form-item></div>
          </el-col>
          <el-col :span="8">
            <div><el-input v-model="userData.userCN"></el-input></div>
          </el-col>
          <el-col :span="4">
            <div><el-form-item label="用户性别:"></el-form-item></div>
          </el-col>
          <el-col :span="8">
            <div>
              <el-radio-group v-model="userData.sex">
                <el-radio label="男"></el-radio>
                <el-radio label="女"></el-radio>
              </el-radio-group>
            </div>
          </el-col>
        </el-row>
        <el-divider content-position="left">办公信息</el-divider>
        <el-row>
          <el-col :span="4">
            <div><el-form-item label="移动电话:"></el-form-item></div>
          </el-col>
          <el-col :span="8">
            <div><el-input v-model="userData.mobile"></el-input></div>
          </el-col>
          <el-col :span="4">
            <div><el-form-item label="办公电话:"></el-form-item></div>
          </el-col>
          <el-col :span="8">
            <div><el-input v-model="userData.telNo"></el-input></div>
          </el-col>
        </el-row>
        <el-row>
          <el-col :span="4">
            <div><el-form-item label="电子邮箱:"></el-form-item></div>
          </el-col>
          <el-col :span="8">
            <div><el-input v-model="userData.email"></el-input></div>
          </el-col>
          <el-col :span="4">
            <div><el-form-item label="房间号码:"></el-form-item></div>
          </el-col>
          <el-col :span="8">
            <div><el-input v-model="userData.roomNO"></el-input></div>
          </el-col>
        </el-row>
        <el-row>
          <el-col :span="4">
            <div><el-form-item label="是否有效:"></el-form-item></div>
          </el-col>
          <el-col :span="8">
            <div>
              <el-radio-group v-model="userData.isEffective">
                <el-radio label="是"></el-radio>
                <el-radio label="否"></el-radio>
              </el-radio-group></div>
          </el-col>
          <el-col :span="4">
            <div><el-form-item label="有效期至:"></el-form-item></div>
          </el-col>
          <el-col :span="8">
            <div>
              <el-date-picker type="date" v-model="userData.effectTime" placeholder="选择有效截止日期" style="width: 100%"></el-date-picker>
            </div>
          </el-col>
        </el-row>
        <el-divider content-position="left">其他信息</el-divider>
        <el-row>
          <el-col :span="4">
            <div><el-form-item label="家庭住址:"></el-form-item></div>
          </el-col>
          <el-col :span="20">
            <div><el-input v-model="userData.address"></el-input></div>
          </el-col>
        </el-row>
        <el-row>
          <el-col :span="4">
            <div><el-form-item label="概述:"></el-form-item></div>
          </el-col>
          <el-col :span="20">
            <div><el-input v-model="userData.description" type="textarea"></el-input></div>
          </el-col>
        </el-row>
        <br>
        <el-divider content-position="left"><el-button type="primary" @click="updateUser">提交</el-button><el-button @click="dialogFormVisible = false">关闭</el-button></el-divider>
      </el-form>
    </el-card>
    </el-dialog>
  </div>
</template>
<script>
import UserDataService from '../../../services/UserDataService'
import { ElMessage } from 'element-plus'
export default {
  data () {
    return {
      users: [],
      dialogFormVisible: false,
      userData: ''
    }
  },
  methods: {
    retrieveUsers () {
      UserDataService.getAll()
        .then((response) => {
          this.users = response.data
          console.log(response.data)
        })
        .catch((e) => {
          console.log(e)
        })
    },
    delUser (id) {
      console.log(id)
      UserDataService.delete(id)
        .then(
          ElMessage({
            message: '删除成功!',
            type: 'success',
            duration: 1000
          }),
          setTimeout(() => {
            this.$router.push({ name: 'users' })
            this.retrieveUsers()
          }, 1000)
        ).catch(e => {
          console.log(e)
        })
    },
    editUser (data) {
      this.dialogFormVisible = true
      this.userData = data
    },
    updateUser () {
      console.log(this.userData.userCN)
      UserDataService.update(this.userData.id, this.userData)
        .then(
          ElMessage({
            message: '修改成功!',
            type: 'success',
            duration: 1000
          }),
          setTimeout(() => {
            this.$router.push({ name: 'users' })
            this.retrieveUsers()
          }, 1000)
        ).catch(e => {
          console.log(e)
        })
      this.dialogFormVisible = false
    }
  },
  mounted () {
    this.retrieveUsers()
  }
}
</script>
<style scoped>
.head {
  margin-top: -30px;
}
</style>
  1. AddUser.vue
<template>
  <div>
    <el-card
      class="box-card"
      :body-style="{ padding: '20px', width: '80%', margin: '0 auto' }">
      <!-- 卡片头部分 -->
      <template #header>
        <div>
          添加用户信息
        </div>
      </template>
      <!-- 表单字段部分 -->
      <el-form label-position="right" label-width="100%">
        <el-divider content-position="left">基本信息</el-divider>
        <el-row>
          <el-col :span="4">
            <div><el-form-item label="用户编号:"></el-form-item></div>
          </el-col>
          <el-col :span="8">
            <div><el-input v-model="userData.userId"></el-input></div>
          </el-col>
          <el-col :span="4">
            <div><el-form-item label="用户账号:"></el-form-item></div>
          </el-col>
          <el-col :span="8">
            <div><el-input v-model="userData.userName"></el-input></div>
          </el-col>
        </el-row>
        <el-row>
          <el-col :span="4">
            <div><el-form-item label="用户密码:"></el-form-item></div>
          </el-col>
          <el-col :span="8">
            <div><el-input v-model="userData.userPass"></el-input></div>
          </el-col>
          <el-col :span="4">
            <div><el-form-item label="确认密码:"></el-form-item></div>
          </el-col>
          <el-col :span="8">
            <div><el-input v-model="userData.reUserPass"></el-input></div>
          </el-col>
        </el-row>
        <el-row>
          <el-col :span="4">
            <div><el-form-item label="中文名称:"></el-form-item></div>
          </el-col>
          <el-col :span="8">
            <div><el-input v-model="userData.userCN"></el-input></div>
          </el-col>
          <el-col :span="4">
            <div><el-form-item label="用户性别:"></el-form-item></div>
          </el-col>
          <el-col :span="8">
            <div>
              <el-radio-group v-model="userData.sex">
                <el-radio label="男"></el-radio>
                <el-radio label="女"></el-radio>
              </el-radio-group>
            </div>
          </el-col>
        </el-row>
        <el-divider content-position="left">办公信息</el-divider>
        <el-row>
          <el-col :span="4">
            <div><el-form-item label="移动电话:"></el-form-item></div>
          </el-col>
          <el-col :span="8">
            <div><el-input v-model="userData.mobile"></el-input></div>
          </el-col>
          <el-col :span="4">
            <div><el-form-item label="办公电话:"></el-form-item></div>
          </el-col>
          <el-col :span="8">
            <div><el-input v-model="userData.telNo"></el-input></div>
          </el-col>
        </el-row>
        <el-row>
          <el-col :span="4">
            <div><el-form-item label="电子邮箱:"></el-form-item></div>
          </el-col>
          <el-col :span="8">
            <div><el-input v-model="userData.email"></el-input></div>
          </el-col>
          <el-col :span="4">
            <div><el-form-item label="房间号码:"></el-form-item></div>
          </el-col>
          <el-col :span="8">
            <div><el-input v-model="userData.roomNO"></el-input></div>
          </el-col>
        </el-row>
        <el-row>
          <el-col :span="4">
            <div><el-form-item label="是否有效:"></el-form-item></div>
          </el-col>
          <el-col :span="8">
            <div>
              <el-radio-group v-model="userData.isEffective">
                <el-radio label="是"></el-radio>
                <el-radio label="否"></el-radio>
              </el-radio-group></div>
          </el-col>
          <el-col :span="4">
            <div><el-form-item label="有效期至:"></el-form-item></div>
          </el-col>
          <el-col :span="8">
            <div>
              <el-date-picker type="date" v-model="userData.effectTime" placeholder="选择有效截止日期" style="width: 100%"></el-date-picker>
            </div>
          </el-col>
        </el-row>
        <el-divider content-position="left">其他信息</el-divider>
        <el-row>
          <el-col :span="4">
            <div><el-form-item label="家庭住址:"></el-form-item></div>
          </el-col>
          <el-col :span="20">
            <div><el-input v-model="userData.address"></el-input></div>
          </el-col>
        </el-row>
        <el-row>
          <el-col :span="4">
            <div><el-form-item label="概述:"></el-form-item></div>
          </el-col>
          <el-col :span="20">
            <div><el-input v-model="userData.description" type="textarea"></el-input></div>
          </el-col>
        </el-row>
        <el-divider content-position="left"><el-button type="primary" @click="onSubmit">提交</el-button><el-button @click="resetForm">重置</el-button></el-divider>
      </el-form>
    </el-card>
  </div>
</template>
<script>
import UserDataService from '../../../services/UserDataService'
import { ElMessage } from 'element-plus'
export default {
  data () {
    return {
      test: '123',
      userData: {
        userId: '',
        userName: '',
        userPass: '',
        userCN: '',
        sex: '男',
        mobile: '',
        telNo: '',
        email: '',
        roomNO: '',
        address: '',
        effectTime: '2022/01/01',
        description: '',
        isEffective: '是',
        createdAt: '',
        updatedAt: ''
      }
    }
  },
  methods: {
    onSubmit () {
      var userInfo = {
        userId: this.userData.userId,
        userName: this.userData.userName,
        userPass: this.userData.userPass,
        userCN: this.userData.userCN,
        sex: this.userData.sex,
        mobile: this.userData.mobile,
        telNo: this.userData.telNo,
        email: this.userData.email,
        roomNO: this.userData.roomNO,
        address: this.userData.address,
        effectTime: this.userData.effectTime,
        description: this.userData.description,
        isEffective: this.userData.isEffective === '是' ? '1' : '0',
        createdAt: '2022-01-01',
        updatedAt: '2022-01-01'
      }
      UserDataService.create(userInfo)
        .then(res => {
          console.log(res.data)
          ElMessage({
            message: '提交成功!',
            type: 'success',
            duration: 1000
          })
          setTimeout(() => {
            this.$router.push({ name: 'users' })
          }, 1000)
        })
        .catch(e => {
          console.log(e)
        })
    },
    resetForm () {
      this.userData = {}
    }
  }
}
</script>
11、目录结构

在这里插入图片描述

12、运行效果图
  • 用户列表:
    在这里插入图片描述
  • 添加用户:

在这里插入图片描述

  • 修改用户:
    在这里插入图片描述

注意:有些方法尚未实现,表单缺少验证功能,注意修改后端的端口信息server.js

const express = require("express");
const cors = require("cors");
const app = express();
var corsOptions = {
  origin: "http://localhost:3000"
};
app.use(cors(corsOptions));
// 解析内容类型为:application/json 的请求
app.use(express.json());
// 解析内容类型为:application/x-www-form-urlencoded 的请求
app.use(express.urlencoded({ extended: true }));
const db = require("./app/models");
db.sequelize.sync();
/** 
 * 通过models实例创建数据库表时使用
db.sequelize.sync({ force: true }).then(() => {
  console.log("删除并且重新同步数据库!!!");
});
 */
// 简单路由
app.get("/", (req, res) => {
  res.json({ message: "欢迎来到我的应用!!!" });
});
require("./app/routes/user.routes")(app);
// 设置端口, 监听请求
const PORT = process.env.PORT || 9000;
app.listen(PORT, () => {
  console.log(`服务器正在运行,端口为: ${PORT}.`);
});
Logo

前往低代码交流专区

更多推荐