使用mock模拟数据
通过脚手架创建基本项目 脚手架详情请参考脚手架这篇安装教学
01、在项目中安装mock
两种安装 命令如下:
npm install mockjs vue add axios
安装完成后可在node_modules中查看是否安装成了mockjs
02、新建文件夹并在其创建建index.js
03、 将mock文件夹的index.js文件在main.js中导入
04、对index.js添加mock语法
(此处用来测试)详细语法请从官网中获取 Mock.js
// 使用 Mock var Mock = require('mockjs') var data = Mock.mock({ // 属性 list 的值是一个数组,其中含有 1 到 10 个元素 'list|1-10': [{ // 属性 id 是一个自增数,起始值为 1,每次增 1 'id|+1': 1 }] }) // 输出结果 console.log(JSON.stringify(data, null, 4))
测试完毕后下载elementui插件,从vue ui中下载
接下来可以运用element-ui来实现分页数据的请求,添加以及删除等功能
一、删除vue中的原有样式
在index.js中添加四种数据
// 使用 Mock var Mock = require('mockjs') var data = Mock.mock({ // 属性 list 的值是一个数组,其中含有 1 到 10 个元素 'list|20-60': [{ // 属性 id 是一个自增数,起始值为 1,每次增 1 "id": '@increment()', "title": "@ctitle", "content": "@cparagraph", "add_time": "@date(yyyy-MM-dd hh:mm:ss)" }] }) // 输出结果 console.log(JSON.stringify(data))
这里打印要先把他转换成字符串格式,并且如果只加了data那么效果如下:
特别不容易查看数据,所以需要对其进行排版。像以下这种:
// 使用 Mock var Mock = require('mockjs') var data = Mock.mock({ // 属性 list 的值是一个数组,其中含有 1 到 10 个元素 'list|20-60': [{ // 属性 id 是一个自增数,起始值为 1,每次增 1 "id": '@increment()', "title": "@ctitle", "content": "@cparagraph", "add_time": "@date(yyyy-MM-dd hh:mm:ss)" }] }) // 输出结果 console.log(JSON.stringify(data,null,4))
效果如下图 所示:
console.log(JSON.stringify(data,null,4)) Mock.mock('/api/get/user','get',(options)=>{ console.log(options); return { status: 200, message: '获取新闻列表数据成功', test:data.list } })
App.vue
mounted(){ this.getData() }, methods: { getData(){ this.$axios.get('/api/get/user').then(res=>{ console.log(res); }) } },
接下来可以设置App.vue中的样式了
可从官网中提取所需的样式:element-ui官网
,并加以修改即可
在div #app里添加如下代码
<h3 style="text-align: center">数据展示</h3> <!-- 添加 --> <el-row :gutter="24"> <el-col :span="8"> <el-input v-model="title" placeholder="请输入标题"></el-input ></el-col> <el-col :span="8" ><el-input v-model="content" placeholder="请输入内容"></el-input ></el-col> <el-col :span="8" ><el-button type="primary" @click="handelAdd">添加</el-button></el-col > </el-row>
通过 row 和 col 组件,并通过 col 组件的 span 属性我们就可以自由地组合布局。
Row 组件 提供 gutter 属性来指定每一栏之间的间隔,默认间隔为 0。
效果如下:
接下来就是选择表格
<el-table :data="tableData" stripe style="width: 100%"> <el-table-column prop="date" label="日期" width="180"> </el-table-column> <el-table-column prop="name" label="姓名" width="180"> </el-table-column> <el-table-column prop="address" label="地址"> </el-table-column> </el-table> export default { name: "app", data() { return { // tableData: [], title: "", content: "", pagenum: 1, pagesize: 10, total: 0, tableData: [ { date: "2016-05-02", name: "王小虎", address: "上海市普陀区金沙江路 1518 弄", }, { date: "2016-05-04", name: "王小虎", address: "上海市普陀区金沙江路 1517 弄", }, { date: "2016-05-01", name: "王小虎", address: "上海市普陀区金沙江路 1519 弄", }, { date: "2016-05-03", name: "王小虎", address: "上海市普陀区金沙江路 1516 弄", }, ], }; }, mounted() { this.getData(); }, methods: { getData() { this.$axios.get("/api/get/user").then((res) => { console.log(res); }); }, }, };
添加删除按钮
<el-table-column label="操作"> <template v-slot="scope" > <el-button size="mini" type="danger" @click="handleDelete(scope.$index, scope.row)" >删除</el-button > </template> </el-table-column> handleDelete(index, row) { console.log(index, row); },
然后修改头部名称
代码如下:
<template> <div id="app"> <h3 style="text-align: center">数据展示</h3> <!-- 添加 --> <el-row :gutter="24"> <el-col :span="8"><el-input v-model="title" placeholder="请输入标题"></el-input></el-col> <el-col :span="8"><el-input v-model="content" placeholder="请输入内容"></el-input></el-col> <el-col :span="8"> <el-button type="primary">添加</el-button> </el-col> </el-row> <template> <el-table :data="tableData" stripe style="width: 100%"> <el-table-column prop="date" label="标题" width="180"> </el-table-column> <el-table-column prop="name" label="内容" width="180"> </el-table-column> <el-table-column prop="address" label="时间"> </el-table-column> <el-table-column label="操作"> <template v-slot="scope"> <el-button size="mini" type="danger" @click="handleDelete(scope.$index, scope.row)" >删除</el-button > </template> </el-table-column> </el-table> </template> </div> </template> <script> export default { name: "app", data() { return { // tableData: [], title: "", content: "", pagenum: 1, pagesize: 10, total: 0, tableData: [ { date: "2016-05-02", name: "王小虎", address: "上海市普陀区金沙江路 1518 弄", }, { date: "2016-05-04", name: "王小虎", address: "上海市普陀区金沙江路 1517 弄", }, { date: "2016-05-01", name: "王小虎", address: "上海市普陀区金沙江路 1519 弄", }, { date: "2016-05-03", name: "王小虎", address: "上海市普陀区金沙江路 1516 弄", }, ], }; }, mounted() { this.getData(); }, methods: { getData() { this.$axios.get("/api/get/user").then((res) => { console.log(res); }); }, handleDelete(index, row) { console.log(index, row); }, }, }; </script> <style> </style>
效果如下:
在index.js中 绑定total
Mock.mock('/api/get/user','get',(options)=>{ console.log(options); return { status: 200, message: '获取新闻列表数据成功', test:data.list, total:data.list.length } })
在app.vue中删除数据项并获取数据
getData() { this.$axios.get("/api/get/user").then((res) => { console.log(res); // 渲染到页面中 this.tableData = res.data.test console.log(this.tableData); }); },
效果如下:
重新设置宽度
<el-table :data="tableData" stripe style="width: 100%"> <el-table-column prop="title" label="标题" width="160"> </el-table-column> <el-table-column prop="content" label="内容" > </el-table-column> <el-table-column prop="add_time" label="时间" width="180"> </el-table-column> <el-table-column label="操作" width="180"> <template v-slot="scope"> <el-button size="mini" type="danger" @click="handleDelete(scope.$index, scope.row)" >删除</el-button > </template> </el-table-column> </el-table>
效果如下:
接下来做分页
<el-pagination style="text-align: center" @size-change="handleSizeChange" @current-change="handleCurrentChange" :current-page="currentPage4" :page-sizes="[100, 200, 300, 400]" :page-size="100" layout="total, sizes, prev, pager, next, jumper" :total="400"> </el-pagination> methods: { handleSizeChange(val) { console.log(`每页 ${val} 条`); }, handleCurrentChange(val) { console.log(`当前页: ${val}`); } },
因为分页默认向左边对齐,所以要在标签上添加一个style样式设置为文本居中
所有的页面渲染就已经完成了
接下来进行删除和添加效果
index.js中的对删除进行操作
首先先把分页样式给注释掉,不然控制台会引起错误
// 用正则表达式来写 Mock.mock(/\/api\/delete\/user/,'post',(options)=>{ console.log(options); return{ status: 200, message: '删除成功', list:data.list, } })
app.vue部分
// 删除 async handleDelete(id) { // console.log(index, row); // 传一个参数id post就直接传 // 解构写法 // const {data,res} = await('/api/get/user',{ id }) const result = await axios.post('/api/delete/user',{ id }) console.log(result); this.getData() // 如果是get请求 /* const {data,res} = await('/api/get/user',{ params:{ // id:id id } }) */ }, /* handleSizeChange(val) { console.log(`每页 ${val} 条`); }, handleCurrentChange(val) { console.log(`当前页: ${val}`); }, */
将删除按钮进行修改:
<template v-slot="scope"> <el-button size="mini" type="danger" @click="handleDelete(scope.row.id)" >删除</el-button > </template>
使用async要把axios引入
index.js中获取options里的body
Mock.mock(/\/api\/delete\/user/,'post',(options)=>{ console.log(options); // 要转成对象的形式 // const body = options.body const body = JSON.parse(options.body) console.log(body); // 过滤数据 return{ status: 200, message: '删除成功', list:data.list, } })
使用findindex进行复杂数据类型的查找
const index = data.list.findIndex(item=>item.id === body.id); data.list.splice(index,1)
效果如下:
当然也可以添加一个弹窗
如何添加?
把里面的代码放到app.vue的方法中
this.$confirm('此操作将永久删除该文件, 是否继续?', '提示', { confirmButtonText: '确定', cancelButtonText: '取消', type: 'warning' }).then(() => { this.$message({ type: 'success', message: '删除成功!' }); }).catch(() => { this.$message({ type: 'info', message: '已取消删除' }); });
并且在删除成功里渲染数据
this.$confirm('此操作将永久删除该文件, 是否继续?', '提示', { confirmButtonText: '确定', cancelButtonText: '取消', type: 'warning' }).then(() => { this.$message({ type: 'success', message: '删除成功!' }); // 把this.getData放到此处 this.getData(); }).catch(() => { this.$message({ type: 'info', message: '已取消删除' }); });
效果如下:
添加操作
app.vue
async handelAdd() { if (!this.title || !this.content) { alert('请您务必填写标题以及内容信息!'); return; } // 可以使用重复的result,其作用域不同 const result = await axios.post("/api/add/user", { // 传入的参数为标签中的标题栏以及内容栏 title: this.title, content: this.content, }); // 重新加载一遍数据 console.log(result); this.getData(); // 输入完毕后清空内容 this.title='' this.content='' },
加上一个判断条件(如果为空值时,则调出弹窗提醒用户未完善信息)
if (!this.title || !this.content) { alert('请您务必填写标题以及内容信息!'); return; }
index.js部分
Mock.mock(/\/api\/add\/user/,'post',(options)=>{ console.log(options); const body = JSON.parse(options.body) data.list.unshift(Mock.mock({ // 这里切记不要添加随机数 ,要把随机的数据给去除换成body.title和body.content "id": '@increment()', "title": body.title, "content": body.content, "add_time": "@date(yyyy-MM-dd hh:mm:ss)" })) return{ status: 200, message: '添加成功', list:data.list, } })
效果如下:
分页部分
分页控件
<el-pagination @size-change="handleSizeChange" @current-change="handleCurrentChange" :current-page="pageindex" :page-sizes="[1, 3, 5, 7]" :page-size="pagesize" layout="total, sizes, prev, pager, next, jumper" :total="total" > </el-pagination>
分页的方法:
handleSizeChange(val) { console.log(`每页 ${val} 条`); this.pagesize = val; this.getList(); }, handleCurrentChange(val) { console.log(`当前页: ${val}`); this.pageindex = val; this.getList(); },
index.js部分:
这个就不要了
直接在下面写个新的
// 含有分页的数据列表,有需要接受的参数要使用正则匹配 // /api/get/news?pageindex=1&pagesize=10 Mock.mock(/\/api\/get\/user/, 'get', (options) => { console.log(options) // 获取传递的参数pageindex const pageindex = getQuery(options.url,'pageindex') // 获取传递的参数pagesize const pagesize = getQuery(options.url,'pagesize') // 截取数据的起始位置 const start = (pageindex-1)*pagesize // 截取数据的终点位置 const end = pageindex*pagesize // 计算总页数 const totalPage = Math.ceil(data.list.length/pagesize) // 数据的起始位置:(pageindex-1)*pagesize 数据的结束位置:pageindex*pagesize const list = pageindex>totalPage?[]:data.list.slice(start,end) return { status: 200, message: '获取新闻列表成功', list: list, total: data.list.length } })
参数名可以自己取
最后在生命周期内 先运行一下即可:
create() { this.getData(); },
实现效果如下:
本章中间更变数据后有细微错误,下面代码是为完整代码
vue.app部分:
<template> <div id="app"> <h3 style="text-align: center">数据展示</h3> <!-- 添加 --> <el-row :gutter="24" style="margin: 0"> <el-col :span="8" ><el-input v-model="title" placeholder="请输入标题"></el-input ></el-col> <el-col :span="8" ><el-input v-model="content" placeholder="请输入内容"></el-input ></el-col> <el-col :span="8"> <el-button type="primary" @click="handelAdd">添加</el-button> </el-col> </el-row> <template> <el-table :data="tableData" stripe style="width: 100%"> <el-table-column prop="title" label="标题" width="160"> </el-table-column> <el-table-column prop="content" label="内容"> </el-table-column> <el-table-column prop="add_time" label="时间" width="180"> </el-table-column> <el-table-column label="操作" width="180"> <template v-slot="scope"> <el-button size="mini" type="danger" @click="handleDelete(scope.row.id)" >删除</el-button > </template> </el-table-column> </el-table> <el-pagination style="text-align: center" @size-change="handleSizeChange" @current-change="handleCurrentChange" :current-page="pageindex" :page-sizes="[1, 3, 5, 7]" :page-size="pagesize" layout="total, sizes, prev, pager, next, jumper" :total="total" > </el-pagination> </template> </div> </template> <script> import axios from "axios"; export default { name: "app", data() { return { tableData: [], title: "", content: "", pageindex: 1, pagesize: 10, total: 0, }; }, mounted() { this.getData(); }, create() { this.getData(); }, methods: { getData() { // 写分页 this.$axios .get("/api/get/user", { params: { pageindex: this.pageindex, pagesize: this.pagesize, }, }) .then((res) => { console.log(res); this.tableData = res.data.list; // console.log(this.tableData); this.total = res.data.total; }); }, // 删除 async handleDelete(id) { this.$confirm("此操作将永久删除该文件, 是否继续?", "提示", { confirmButtonText: "确定", cancelButtonText: "取消", type: "warning", }) .then(() => { this.$message({ type: "success", message: "删除成功!", }); this.getData(); }) .catch(() => { this.$message({ type: "info", message: "已取消删除", }); }); // console.log(index, row); // 传一个参数id post就直接传 // 解构写法 // const {data,res} = await('/api/get/user',{ id }) const result = await axios.post("/api/delete/user", { id }); console.log(result); // 如果是get请求 /* const {data,res} = await('/api/get/user',{ params:{ // id:id id } }) */ }, // 添加 async handelAdd() { if (!this.title || !this.content) { alert("请您务必填写标题以及内容信息!"); return; } // 可以使用重复的result,其作用域不同 const result = await axios.post("/api/add/user", { // 传入的参数为标签中的标题栏以及内容栏 title: this.title, content: this.content, }); // 重新加载一遍数据 console.log(result); this.getData(); // 输入完毕后清空内容 this.title = ""; this.content = ""; }, handleSizeChange(val) { console.log(`每页 ${val} 条`); this.pagesize = val; this.getData(); console.log(this.pagesize); }, handleCurrentChange(val) { console.log(`当前页: ${val}`); this.pageindex = val; this.getData(); }, }, }; </script> <style> </style>
moke/index.js部分
// 使用 Mock import Mock from 'mockjs' const data = Mock.mock({ // 属性 list 的值是一个数组,其中含有 1 到 10 个元素 'list|20-60': [{ // 属性 id 是一个自增数,起始值为 1,每次增 1 "id": '@increment()', "title": "@ctitle", "content": "@cparagraph", "add_time": "@date(yyyy-MM-dd hh:mm:ss)" }] }) const getQuery = (url,name)=>{ const index = url.indexOf('?') console.log(index); if(index !== -1) { const queryStrArr = url.substr(index+1).split('&') for(var i=0;i<queryStrArr.length;i++) { const itemArr = queryStrArr[i].split('=') console.log(itemArr) if(itemArr[0] === name) { return itemArr[1] } } } } /* // 输出结果 // console.log(JSON.stringify(data,null,4)) Mock.mock(/\/api\/get\/user/,'get',(options)=>{ console.log(options); return { status: 200, message: '获取新闻列表数据成功', list:data.list, total:data.list.length } }) */ // 含有分页的数据列表,有需要接受的参数要使用正则匹配 // /api/get/news?pageindex=1&pagesize=10 Mock.mock(/\/api\/get\/user/, 'get', (options) => { console.log(options) // 获取传递的参数pageindex const pageindex = getQuery(options.url,'pageindex') // 获取传递的参数pagesize const pagesize = getQuery(options.url,'pagesize') // 截取数据的起始位置 const start = (pageindex-1)*pagesize // 截取数据的终点位置 const end = pageindex*pagesize // 计算总页数 const totalPage = Math.ceil(data.list.length/pagesize) // 数据的起始位置:(pageindex-1)*pagesize 数据的结束位置:pageindex*pagesize const list = pageindex>totalPage?[]:data.list.slice(start,end) return { status: 200, message: '获取新闻列表成功', list: list, total: data.list.length } }) // 删除通过post请求 Mock.mock('/api/delete/user','post',(options)=>{ console.log(options); // 要转成对象的形式 // const body = options.body const body = JSON.parse(options.body) console.log(body) // 如果每一项的id与body的id相等时,则删除本身一行数据 const index = data.list.findIndex(item=>item.id === body.id); data.list.splice(index,1) // 过滤数据 return{ status: 200, message: '删除成功', list:data.list, } }) // 添加 Mock.mock('/api/add/user','post',(options)=>{ console.log(options); const body = JSON.parse(options.body) data.list.unshift(Mock.mock({ // 属性 id 是一个自增数,起始值为 1,每次增 1 "id": '@increment(1)', "title": body.title, "content": body.content, "add_time": "@date(yyyy-MM-dd hh:mm:ss)" })) return{ status: 200, message: '添加成功', list:data.list, } })