提示:上篇文章里讲解了 mockjs 的一些入门操作,及简单案例演示. 这篇文章将结合项目实现列表的增删改查功能.如有不当之处 欢迎指正
日常开发中,curd是每个项目都有的基础功能.下面实现在独立于后端时进行curd功能的实现
提示:以下是本篇文章正文内容,下面案例可供参考 如有不当之处 欢迎指正
以下关于组件的创建不做过多赘述
ps :此处的 接口地址 需要与 axios 中封装的接口地址一致;
// 列表模拟数据生成
//'userList|55': 数组的长度为55
const data = Mock.mock({
'userList|55': [
{
id: '@increment',
name: '@cname()',
address: '@city(true)',
date: '@date(yyyy-MM-dd)'
}
]
})
生成 查询 功能的接口 :
- 此处 返回的格式需要和后端商讨一致.
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
}
})
export const getUserListAPI = (params) => {
return request({
url: 'mock/userList', // 此处的接口地址与模拟的 mockjs 接口地址一致
method: 'get',
params
})
}
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中获取到的数据,以及接口响应后我们模拟的返回数据
分页功能的处理 实际上就是对生成的data数据进行处理;
这里实际就是对 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
}
完善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
}
})
// 分页
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
}
post请求,请求参数存在请求体里面;
Mock.mock(RegExp('mock/addUser'), 'post', (options) => {
console.log(options, 'options')
return {
code: 200,
success: true,
message: '用户添加成功'
}
})```
2. 封装axios的新增接口:
```javascript
export const addUserAPI = (data) => {
return request({
url: 'api/mock/addUser',
method: 'post',
data
})
}
新增和编辑是共用的这个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
}
})
async handleOk(formData) {
const res = await addUserAPI(formData)
if (res.success) {
this.$message({
message: res.message,
type: 'success'
})
this.$refs.dialogFormVisible.onClose() // 关闭弹窗
this.getUserList() // 重新加载列表
}
},
此时已经将获取的表单数据传入了接口中, 这时再来看 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: '用户添加成功'
}
})
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
})
}
handleEdit(record) {
this.$refs.dialogFormVisible.edit(record)
},
edit(record) {
this.dialogFormVisible = true
this.ruleForm = Object.assign({}, record)
this.btnText = '编辑用户'
},
实际上 ,此处和新增用户触发的是同一个方法
判断当前表单数据是否存在 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()
},
获取传入的 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: '用户删除成功'
}
})
export const deleteUserAPI = (data) => {
return request({
url: 'api/mock/deleteUser',
method: 'post',
data
})
}
// 删除
async handleDelete(record) {
const res = await deleteUserAPI(record)
if (res.success) {
this.$message({
message: res.message,
type: 'success'
})
this.getUserList()
}
},
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: '用户修改成功'
}
})
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
})
}
<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>
<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-picker
v-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>
提示:以上 使用 mockjs 前端独立实现 curd 功能 的完整代码 ,如有不当欢迎指正
以上的编辑功能可以在写在listDialog组件中 (因为我已经写完了就懒得修改了);