Mockjs入门级操作 && 案例操作(实现增删改查功能) (二)
Mockjs入门级操作 && 案例操作(实现增删改查功能) (二)
提示:上篇文章里讲解了 mockjs 的一些入门操作,及简单案例演示. 这篇文章将结合项目实现列表的增删改查功能.如有不当之处 欢迎指正
文章目录
- Mockjs入门级操作 && 案例操作(实现增删改查功能) (二)
- 前言
- 一、回顾mockjs在vue项目中的基础使用步骤
- 二、增删改查功能实现
-
- 1.增删改查 -- 查
- 2.增删改查 -- 增
-
- 1. mockjs 模拟 新增 接口 ,封装axios的新增接口
- 2. 创建 views/list/modules/listDialog.vue
- 2.获取子组件传参,调用新增接口
- 3. 完善 mockjs 的 新增接口
- 3.增删改查 -- 改
-
- 1. mockjs模拟 编辑 接口 ,封装 axios 的 编辑 接口
- 2.点击编辑 , 将当前行数据传入listDialog
- 3. listDialog 进行数据回显
- 4. 点击编辑用户时,调用编辑接口
- 4.增删改查 -- 删
-
-
- 1.mockjs 模拟 删除 接口 , 封装 axios 的 删除接口
- 2.点击删除时, 调用删除接口
-
- 三. 完整代码 及 功能实现效果展示
-
- 1. mock/list/index
- 2. api/list/index
- 3.views/list/index.vue
-
- 4.
- 5. 功能实现效果展示 :
- 总结
前言
日常开发中,curd是每个项目都有的基础功能.下面实现在独立于后端时进行curd功能的实现
提示:以下是本篇文章正文内容,下面案例可供参考 如有不当之处 欢迎指正
一、回顾mockjs在vue项目中的基础使用步骤
- mock/list/index文件中对接口数据进行模拟;
- api/list/index 文件中封装axios请求
- .vue组件中调用接口,获取模拟数据;
二、增删改查功能实现
以下关于组件的创建不做过多赘述
1.增删改查 – 查
1.创建views/list/index.vue :
- 完成基本的分页列表布局;
2.模拟 查询功能 的接口
- 生成列表的数据
- 生成 查询 功能的接口
ps :此处的 接口地址 需要与 axios 中封装的接口地址一致;
// 列表模拟数据生成//'userList|55': 数组的长度为55const data = Mock.mock({ 'userList|55': [ { id: '@increment', name: '@cname()', address: '@city(true)', date: '@date(yyyy-MM-dd)' } ]})
data数据: 随机生成了长度为55的数组
生成 查询 功能的接口 :
- 此处 返回的格式需要和后端商讨一致.
2.options : 可以接收到 本次请求的 Ajax 选项集
RegExp : 对接口地址进行正则匹配.
// 生成 查询 功能的接口Mock.mock(RegExp('mock/userList'), 'get', (options) => { console.log(options) return { code: 200, success: true, message: '获取用户列表成功', data: data.userList, totalPage: data.userList.length }})
3.封装axios的列表接口
export const getUserListAPI = (params) => { return request({ url: 'mock/userList', // 此处的接口地址与模拟的 mockjs 接口地址一致 method: 'get', params })}
4.views/list/index.vue中调用接口
async getUserList() { const res = await getUserListAPI({ pageSize: this.pageSize, currentPage: this.currentPage }) this.tableData = res.data this.total = res.totalPage console.log(res, 'res') }
因为涉及到分页功能,所以需要传入 pageSize , currentPage 两个参数; 这时候再反过来看 options中获取到的数据,以及接口响应后我们模拟的返回数据
5. 处理分页功能
分页功能的处理 实际上就是对生成的data数据进行处理;
- 从 options.url中解析出 传过来的参数值 (pageSize,currentPage)
- 根据 pageSize(每页条数) currentPage(当前页) 处理 data数据
- 获取数据的起始值
- 获取数据的终止值
- 获取当前的总页数
- 返回新的数组
1) options.url 解析参数值 :
这里实际就是对 url 进行拆分,然后再匹配传入的值
// 处理get请求的url参数 "/api/api/mock/userList?pageSize=10¤tPage=1"const getQuery = (url, name) => { const isFind = url.indexOf(name) !== -1 if (isFind) { const queryArr = url.split('?')[1].split('&') for (let i = 0; i < queryArr.length; i++) { const result = queryArr[i].split('=') if (result[0] === name) { return result[1] } } } return null}
2) 对data数据进行处理
完善mockjs的接口
Mock.mock(RegExp('mock/userList'), 'get', (options) => { // 根据url解析出pageSize的值 const pageSize = getQuery(options.url, 'pageSize') // 根据url解析出currentPage的值 const currentPage = getQuery(options.url, 'currentPage') / * 对返回的数组进行处理 (即实现分页效果) * 1.获取起始值 : pageSize=1 currentPage=10 即 0(索引)计算公式 : (pageSize-1)*currentPage * 2.获取终止值 : pageSize=1 currentPage=10 即 9(索引)计算公式 : pageSize*currentPage (不-1,是因为使用splice进行截取;) * 3.如当前页码超出总页码,则返回 [] ;计算公式 : totalPage=Math.ceil(data.length/currentPage) */ const startIndex = (currentPage - 1) * pageSize const endIndex = pageSize * currentPage const totalPage = Math.ceil(data.userList.length / pageSize) const newDataArr = currentPage > totalPage ? [] : data.userList.slice(startIndex, endIndex) return { code: 200, success: true, message: '获取用户列表成功', data: newDataArr, totalPage: data.userList.length }})
6.完善list.vue页面的分页功能,使pageSize,currentPage 动态化
// 分页 handleSizeChange(val) { this.pageSize = val this.getUserList() }, handleCurrentChange(val) { this.currentPage = val this.getUserList() }, async getUserList() { const { data, totalPage } = await getUserListAPI({ pageSize: this.pageSize, currentPage: this.currentPage }) this.tableData = data this.total = totalPage }
分页功能展示 :
2.增删改查 – 增
1. mockjs 模拟 新增 接口 ,封装axios的新增接口
- mockjs 模拟 新增 接口 :
post请求,请求参数存在请求体里面;
Mock.mock(RegExp('mock/addUser'), 'post', (options) => { console.log(options, 'options') return { code: 200, success: true, message: '用户添加成功' }})``` 2. 封装axios的新增接口:```javascriptexport const addUserAPI = (data) => { return request({ url: 'api/mock/addUser', method: 'post', data })}
2. 创建 views/list/modules/listDialog.vue
- 完成基本的布局.
新增和编辑是共用的这个dialog弹框,所以弹框的title和btnText都是动态化的;
2. views/list/index.vue中引入listDialog ,实现弹框的显示隐藏功能:
// @handleOk="handleOk" --接收子组件传入的表单数据 // @ok="modelFormOk" 子组件修改完成,触发重新渲染列表 <list-dialog ref="dialogFormVisible" @handleOk="handleOk" @ok="modelFormOk"/> // 新增 handleAdd() { this.$refs.dialogFormVisible.add() },
listDialog :
add() { this.dialogFormVisible = true this.btnText = '新增用户' this.ruleForm = {} },//弹窗关闭事件 onClose() { this.dialogFormVisible = false }
- 点击新增用户时,将获取的表单数据传入父组件中
submitForm(formName) { this.$refs[formName].validate(async (valid) => { if (valid) { this.$emit('handleOk', this.ruleForm) } else { return false } })
2.获取子组件传参,调用新增接口
async handleOk(formData) { const res = await addUserAPI(formData) if (res.success) { this.$message({ message: res.message, type: 'success' }) this.$refs.dialogFormVisible.onClose() // 关闭弹窗 this.getUserList() // 重新加载列表 } },
3. 完善 mockjs 的 新增接口
此时已经将获取的表单数据传入了接口中, 这时再来看 post 传参 和 get 传参的不同之处,以及对data数据的处理;
post请求的参数 可以直接在 options.body中获取
因为获取到的数据是字符串形式("{“name”:“张三”,“address”:“成都”,“date”:“2022-03-01”}"),需要使用JSON.parse()进行转换
将当前传入的参数追加进 data列表中.
Mock.mock(RegExp('mock/addUser'), 'post', (options) => { const params = JSON.parse(options.body) data.userList.unshift( Mock.mock({ id: '@increment', name: params.name, address: params.address, date: params.date }) ) return { code: 200, success: true, message: '用户添加成功' }})
新增功能展示 :
3.增删改查 – 改
1. mockjs模拟 编辑 接口 ,封装 axios 的 编辑 接口
1.mockjs模拟 编辑 接口
获取 传入的 id 值,进行匹配,重新赋值;
Mock.mock(RegExp('mock/editUser'), 'post', (options) => { const params = JSON.parse(options.body) for (let i = 0; i < data.userList.length; i++) { if (data.userList[i].id === params.id) { data.userList[i] = params } } return { code: 200, success: true, message: '用户修改成功' }})
2.封装 axios 的 编辑 接口
export const editUserAPI = (data) => { return request({ url: 'api/mock/editUser', method: 'post', data })}
2.点击编辑 , 将当前行数据传入listDialog
handleEdit(record) { this.$refs.dialogFormVisible.edit(record) },
3. listDialog 进行数据回显
edit(record) { this.dialogFormVisible = true this.ruleForm = Object.assign({}, record) this.btnText = '编辑用户' },
此处效果展示 :
4. 点击编辑用户时,调用编辑接口
实际上 ,此处和新增用户触发的是同一个方法
判断当前表单数据是否存在 id 值, 如果存在则是编辑, 不存在则是新增;
存在时 调用编辑接口
修改完成后,通知父组件已经完成修改,重新渲染列表
submitForm(formName) { this.$refs[formName].validate(async (valid) => { if (valid) { if (!this.ruleForm.id) { this.$emit('handleOk', this.ruleForm) } const res = await editUserAPI(this.ruleForm) if (res.success) { this.$message({message: res.message,type: 'success' }) this.$emit('ok') // 完成修改,通知父组件重新渲染列表; this.onClose() } } else { return false } }) },
父组件 重新渲染事件 :
// 编辑 modelFormOk() { this.getUserList() },
4.增删改查 – 删
1.mockjs 模拟 删除 接口 , 封装 axios 的 删除接口
- mockjs 模拟 删除 接口
获取传入的 id 值 ,进行匹配,查找到当前的索引;
通过Array.splice() 方法 删除当前数据
Mock.mock(RegExp('mock/deleteUser'), 'post', (options) => { const params = JSON.parse(options.body) const deleteIndex = data.userList.findIndex((item) => { return item.id === params.id }) data.userList.splice(deleteIndex, 1) return { code: 200, success: true, message: '用户删除成功' }})
- 封装 axios 的 删除接口
export const deleteUserAPI = (data) => { return request({ url: 'api/mock/deleteUser', method: 'post', data })}
2.点击删除时, 调用删除接口
// 删除 async handleDelete(record) { const res = await deleteUserAPI(record) if (res.success) { this.$message({ message: res.message, type: 'success' }) this.getUserList() } },
效果展示 :
三. 完整代码 及 功能实现效果展示
1. mock/list/index
import Mock from 'mockjs'// 处理get请求的url参数const getQuery = (url, name) => { const isFind = url.indexOf(name) !== -1 if (isFind) { const queryArr = url.split('?')[1].split('&') for (let i = 0; i < queryArr.length; i++) { const result = queryArr[i].split('=') if (result[0] === name) { return result[1] } } } return null}const data = Mock.mock({ 'userList|55': [ { id: '@increment', name: '@cname()', address: '@city(true)', date: '@date(yyyy-MM-dd)' } ]})Mock.mock(RegExp('mock/userList'), 'get', (options) => { const pageSize = getQuery(options.url, 'pageSize') // 根据url解析出pageSize的值 const currentPage = getQuery(options.url, 'currentPage') // 根据url解析出currentPage的值 / * 对返回的数组进行处理 (即实现分页效果) * 1.获取起始值 : pageSize=1 currentPage=10 即 0(索引) 计算公式 : (pageSize-1)*currentPage * 2.获取终止值 : pageSize=1 currentPage=10 即 9(索引) 计算公式 : pageSize*currentPage (不-1,是因为使用splice进行截取;) * 3.如当前页码超出总页码,则返回 [] ; totalPage=Math.ceil(data.length/currentPage) */ const startIndex = (currentPage - 1) * pageSize const endIndex = pageSize * currentPage const totalPage = Math.ceil(data.userList.length / pageSize) const newDataArr = currentPage > totalPage ? [] : data.userList.slice(startIndex, endIndex) return { code: 200, success: true, message: '获取用户列表成功', data: newDataArr, totalPage: data.userList.length }})Mock.mock(RegExp('mock/addUser'), 'post', (options) => { const params = JSON.parse(options.body) data.userList.unshift( Mock.mock({ id: '@increment', name: params.name, address: params.address, date: params.date }) ) return { code: 200, success: true, message: '用户添加成功' }})Mock.mock(RegExp('mock/deleteUser'), 'post', (options) => { const params = JSON.parse(options.body) const deleteIndex = data.userList.findIndex((item) => { return item.id === params.id }) data.userList.splice(deleteIndex, 1) return { code: 200, success: true, message: '用户删除成功' }})Mock.mock(RegExp('mock/editUser'), 'post', (options) => { const params = JSON.parse(options.body) for (let i = 0; i < data.userList.length; i++) { if (data.userList[i].id === params.id) { data.userList[i] = params } } return { code: 200, success: true, message: '用户修改成功' }})
2. api/list/index
import request from '@/utils/request.js'export const getUserListAPI = (params) => { return request({ url: 'api/mock/userList', method: 'get', params })}export const addUserAPI = (data) => { return request({ url: 'api/mock/addUser', method: 'post', data })}export const deleteUserAPI = (data) => { return request({ url: 'api/mock/deleteUser', method: 'post', data })}export const editUserAPI = (data) => { return request({ url: 'api/mock/editUser', method: 'post', data })}
3.views/list/index.vue
<template> <div class="user-list-container"> <el-button type="primary" icon="el-icon-plus" @click="handleAdd"> 新增用户 </el-button> <el-table :data="tableData" style="width: 100%" height="450"> <el-table-column type="index" label="序号" width="50"> </el-table-column> <el-table-column prop="date" label="日期"> </el-table-column> <el-table-column prop="name" label="姓名"> </el-table-column> <el-table-column prop="address" label="地址"> </el-table-column> <el-table-column label="操作" width="100"> <template slot-scope="scope"> <el-button @click="handleEdit(scope.row)" type="text" size="small"> 编辑 </el-button> <el-popconfirm title="确定删除此用户吗?" @confirm="handleDelete(scope.row)" confirm-button-text="确定" cancel-button-text="取消" > <el-button type="text" size="small" slot="reference">删除 </el-button> </el-popconfirm> </template> </el-table-column> </el-table> <div class="pagination"> <el-pagination @size-change="handleSizeChange" @current-change="handleCurrentChange" :current-page="currentPage" :page-sizes="[10, 20, 30, 40]" :page-size="pageSize" layout="total, sizes, prev, pager, next, jumper" :total="total" > </el-pagination> </div> <list-dialog ref="dialogFormVisible" @handleOk="handleOk" @ok="modelFormOk" /> </div></template><script>import { getUserListAPI, addUserAPI, deleteUserAPI } from '@/apis/user.js'import ListDialog from './modules/ListDialog.vue'export default { components: { ListDialog }, data() { return { tableData: [], currentPage: 1, pageSize: 10, total: null } }, methods: { handleEdit(record) { this.$refs.dialogFormVisible.edit(record) }, // 新增 handleAdd() { this.$refs.dialogFormVisible.add() }, async handleOk(formData) { const res = await addUserAPI(formData) if (res.success) { this.$message({ message: res.message, type: 'success' }) this.$refs.dialogFormVisible.onClose() } this.getUserList() }, // 编辑 modelFormOk() { this.getUserList() }, // 删除 async handleDelete(record) { const res = await deleteUserAPI(record) if (res.success) { this.$message({ message: res.message, type: 'success' }) this.getUserList() } }, // 分页 handleSizeChange(val) { this.pageSize = val this.getUserList() }, handleCurrentChange(val) { this.currentPage = val this.getUserList() }, async getUserList() { const { data, totalPage } = await getUserListAPI({ pageSize: this.pageSize, currentPage: this.currentPage }) this.tableData = data this.total = totalPage } }, created() { this.getUserList() }}</script><style lang="scss" scoped>.pagination { margin-top: 10px; text-align: right;}</style>
4.
<template> <el-dialog :title="btnText" :visible.sync="dialogFormVisible" width="450px"> <el-form :model="ruleForm" :rules="rules" ref="ruleForm" label-width="100px" class="demo-ruleForm" > <el-form-item label="姓名" prop="name"> <el-input v-model="ruleForm.name" style="width: 200px"></el-input> </el-form-item> <el-form-item label="地址" prop="address"> <el-input v-model="ruleForm.address" style="width: 200px"></el-input> </el-form-item> <el-form-item label="日期" required> <el-col :span="11"> <el-form-item prop="date"> <el-date-pickerv-model="ruleForm.date"placeholder="选择日期"value-format="yyyy-MM-dd" > </el-date-picker> </el-form-item> </el-col> </el-form-item> <el-form-item> <el-button type="primary" @click="submitForm('ruleForm')"> {{ btnText }} </el-button> <el-button @click="onClose">取消</el-button> </el-form-item> </el-form> </el-dialog></template><script>import { editUserAPI } from '@/apis/user'export default { data() { return { dialogFormVisible: false, ruleForm: { name: '', address: '', date: '' }, rules: { name: [ { required: true, message: '请输入姓名', trigger: 'blur' }, { min: 2, max: 5, trigger: 'blur' } ], address: [ { required: true, message: '请输入居住地址', trigger: 'blur' } ], date: [ { required: true, message: '请选择日期', trigger: 'blur' } ] }, btnText: null } }, methods: { submitForm(formName) { this.$refs[formName].validate(async (valid) => { if (valid) { if (!this.ruleForm.id) { this.$emit('handleOk', this.ruleForm) } const res = await editUserAPI(this.ruleForm) if (res.success) { this.$message({message: res.message,type: 'success' }) this.$emit('ok') this.onClose() } } else { return false } }) }, add() { this.dialogFormVisible = true this.btnText = '新增用户' this.ruleForm = {} }, edit(record) { this.dialogFormVisible = true this.ruleForm = Object.assign({}, record) this.btnText = '编辑用户' }, onClose() { this.dialogFormVisible = false } }}</script><style lang="less" scoped></style>
5. 功能实现效果展示 :
总结
提示:以上 使用 mockjs 前端独立实现 curd 功能 的完整代码 ,如有不当欢迎指正
以上的编辑功能可以在写在listDialog组件中 (因为我已经写完了就懒得修改了);