Vue系列——通过moke进行数据模拟
使用moke模拟数据进行简单的增删以及分页的实现效果
目录
03、 将mock文件夹的index.js文件在main.js中导入
使用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,
}
})
更多推荐
所有评论(0)