Vue系列——通过moke进行数据模拟

目录

使用mock模拟数据

01、在项目中安装mock

02、新建文件夹并在其创建建index.js

03、 将mock文件夹的index.js文件在main.js中导入

 index.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,
    }
})
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Southern Wind

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值