对于使用纯前端方式实现增删改查和分页这个小案例,还没开始做之前觉得颇有些难度,特别是在查询这方面,还没开始做时思想陷入了死胡同:查询的值要怎么才能正确匹配出来,万一有多个值要如何才能全部拿出来,还有本地存储的数据该存储写什么等等…等做完了之后,才发现,其实也没想象中的那么难。所以说,只是动脑子是没什么用的最重要的是要动手去做~~~

前面会先分析一波实现思路,最后会将代码全部贴出来,以供参考
看一下效果图(这里用的是一个简单的买家列表)

在这里插入图片描述

1. 向localStorage添加数据
// 增加
addNew() {
  this.list.unshift(this.form);
  this.list.sort((a, b) => {
    return new Date(b.time).getTime() - new Date(a.time).getTime();
  }); //降序
  window.localStorage.setItem("list", JSON.stringify(this.list));
  this.form = {};//初始化新增表单
  this.dialogFormVisible = false;//隐藏新增弹框
  this.showList();//数据渲染
}
// 数据渲染
showList() {
  if (JSON.parse(window.localStorage.getItem("list"))) {
    this.list = JSON.parse(window.localStorage.getItem("list"));
    this.tableData = [...this.list];//渲染表格数据
    this.total = this.list.length;//数据总条数
    this.changePage(this.list);//进入页面返回到第一页
  }
}

在添加进本地之前,首先得对数据进行一波处理,即:按时间排序;这里用到的是sort方法,相对来说还是比较简单的,对于sort方法在这里我就不详细说明了(网上有很多,不懂的可以去查)。

2.分页显示实现
// 当前页
handleCurrentChange(val) {
  this.currentPage = val;//当前页
  if (this.searchData.length) {
    this.changePage(this.searchData);//如果查询数据存在,则渲染查询数据
  } else {
    this.changePage(this.list);//不存在则渲染全部数据
  }
},
// 分页显示
changePage(obj) {
  const n = (this.currentPage - 1) * this.pageSize; //需要跳过的条数
  this.tableData = obj.slice(n, n + this.pageSize); 
}

分页功能的实现还是有些难度的,主要是需要考虑改变页码时怎么渲染出对应的数据,其中最为精髓的就是:const n = (this.currentPage - 1) * this.pageSize;当前页码减去1,再乘上每页显示条数,获得需要跳过的条数(即值索引)。之后通过数组slice方法将当前页数据渲染到页面。slice():截取数组的一部分,但不改变原数组。

3.删除功能实现
// 删除
handleDelete(row) {
  this.$confirm("此操作将永久删除该记录, 是否继续?", "提示", {
    confirmButtonText: "确定",
    cancelButtonText: "取消",
    type: "warning"
  })
    .then(() => {
      this.list.splice(this.list.indexOf(row), 1);
      window.localStorage.setItem("list", JSON.stringify(this.list));
      this.currentPage = 1;//回到第一页
      this.showList();
      this.$message({
        type: "success",
        message: "删除成功!"
      });
    })
    .catch(() => {
      this.$message({
        type: "info",
        message: "已取消删除"
      });
    });
}

通过handleDelete函数传入的当前项,找到在list中所对应的索引,通过数组splice方法将其删除,最后在把list重新存入本地即可。

4.编辑功能实现
// 编辑
handleEdit(row) {
  this.editFormVisiable = true;//显示编辑弹框
  this.rowItem = row;
  this.editForm = { ...row };
},
// 确认编辑
submitEdit() {
  this.editFormVisiable = false;//隐藏编辑框
  this.list[this.list.indexOf(this.rowItem)] = this.editForm;
  this.list.sort((a, b) => {
    return new Date(b.time).getTime() - new Date(a.time).getTime();
  }); //降序
  window.localStorage.setItem("list", JSON.stringify(this.list));
  this.showList();
  this.$message({
    message: "恭喜你,修改成功",
    type: "success"
  });
}

这里的把row赋值给rowItem以及使用展开运算符深拷贝row赋值给editForm是因为如果不是深拷贝,在编辑时(即还没确认编辑)编辑弹框中值的改变会直接影响到页面渲染的数据,赋值给rowItem是因为在确认编辑中,需要通过它来找到当前项在list中所对应的索引。

5.查询功能实现
// 查询
onSubmit() {
  this.currentPage = 1;//回到第一页
  this.searchData = []; //初始化搜索数据
  this.searchForm = { ...this.formInline };
  if (this.searchForm.user) {//如果搜索对象中user存在
    this.searchData = this.list.filter(item =>
      item.user.match(this.searchForm.user)
    );
    this.total = this.searchData.length;
    this.changePage(this.searchData);
    if (this.searchForm.status) {//如果搜索对象中status存在
      this.searchStatus(this.searchData);
      if (this.searchForm.time && this.searchForm.time.length) {//如果搜索对象中time存在
        this.searchTime(this.searchData);
      }
    } else if (this.searchForm.time && this.searchForm.time.length) {//如果搜索对象中time存在
      this.searchTime(this.searchData);
    }
  } else if (this.searchForm.status) {//如果搜索对象中status存在
    this.searchStatus(this.list);
    if (this.searchForm.time && this.searchForm.time.length) {//如果搜索对象中time存在
      this.searchTime(this.searchData);
    }
  } else if (this.searchForm.time && this.searchForm.time.length) {//如果搜索对象中time存在
    this.searchTime(this.list);
  } else {//如果搜索对象为空
    this.showList();
  }
  this.formInline = {};
},
// 查询状态
searchStatus(obj) {
  this.searchData = obj.filter(item =>
    item.status.match(this.searchForm.status)
  );
  this.total = this.searchData.length;//搜索结果数据总条数
  this.changePage(this.searchData);//传入渲染
},
// 查询时间
searchTime(obj) {
  let beforeTime = new Date(this.searchForm.time[0]).getTime();//查询时间范围下限
  let afterTime = new Date(this.searchForm.time[1]).getTime();//查询时间范围上限
  this.searchData = obj.filter(
    item =>
      beforeTime <= new Date(item.time).getTime() &&
      new Date(item.time).getTime() <= afterTime
  );
  this.total = this.searchData.length;//搜索数据总条数
  this.changePage(this.searchData);//传入渲染
}

刚开始做到这里的是时候感觉还是有些愣,这个查询好像有点难做啊,在网上直接搜索前端做模糊搜索又感觉太复杂了。偶然间我记得好像有个match方法,于是就百度了下,match() 方法可在字符串内检索指定的值,或找到一个或多个正则表达式的匹配。于是,果断测试了下,果然可行,效果异常显著,很符合再这使用。之后再配合数组的filter方法,很完美的实现了模糊查询功能。(尽管这个判断语句有些长,目前我是没有想到更好的方法了,只能尽量减少代码的冗余,将状态和时间封装成函数。不过能够实现我也挺开心了)。

看到这里,基本的功能也是完全实现了。话不多说,上代码

1.template
<template>
  <div id="app">
    <el-card class="box-card">
      <!-- 查询内容 -->
      <div slot="header" class="clearfix">
        <el-form size="small" :inline="true" :model="formInline" class="demo-form-inline">
          <!-- 收货人 -->
          <el-form-item label="收货人">
            <el-input v-model="formInline.user" placeholder="收货人"></el-input>
          </el-form-item>
          <!-- 订单状态 -->
          <el-form-item label="订单状态">
            <el-select v-model="formInline.status" placeholder="订单状态">
              <el-option label="未受理" value="未受理"></el-option>
              <el-option label="已受理" value="已受理"></el-option>
              <el-option label="已送达" value="已送达"></el-option>
            </el-select>
          </el-form-item>
          <!-- 时间范围 -->
          <el-form-item>
            <el-date-picker
              v-model="formInline.time"
              type="datetimerange"
              :picker-options="pickerOptions"
              range-separator=""
              start-placeholder="开始日期"
              end-placeholder="结束日期"
              align="right"
            ></el-date-picker>
          </el-form-item>
          <!-- 查询 -->
          <el-form-item>
            <el-button type="primary" @click="onSubmit">查询</el-button>
          </el-form-item>
          <!-- 新增 -->
          <el-form-item>
            <el-button type="primary" size="small" @click="dialogFormVisible = true">添加新记录</el-button>
            <el-dialog :visible.sync="dialogFormVisible">
              <el-form size="small" style="width:450px" label-width="100px" :model="form">
                <!-- 收货人 -->
                <el-form-item label="收货人">
                  <el-input
                    style="width:280px;margin-left:-80px"
                    v-model="form.user"
                    placeholder="收货人"
                  ></el-input>
                </el-form-item>
                <!-- 订单状态 -->
                <el-form-item label="订单状态">
                  <el-select
                    style="width:280px;margin-left:-80px"
                    v-model="form.status"
                    placeholder="订单状态"
                  >
                    <el-option label="未发货" value="未受理"></el-option>
                    <el-option label="已受理" value="已受理"></el-option>
                    <el-option label="已送达" value="已送达"></el-option>
                  </el-select>
                </el-form-item>
                <!-- 下单时间 -->
                <el-form-item label="下单时间">
                  <el-date-picker
                    style="width:280px;margin-left:-80px"
                    v-model="form.time"
                    type="datetime"
                    value-format="yyyy-MM-dd HH:mm:ss"
                    placeholder="选择日期时间"
                  ></el-date-picker>
                </el-form-item>
              </el-form>
              <div slot="footer" class="dialog-footer">
                <el-button size="small" @click="dialogFormVisible = false">取 消</el-button>
                <el-button size="small" type="primary" @click="addNew">确 定</el-button>
              </div>
            </el-dialog>
          </el-form-item>
        </el-form>
      </div>
      <!-- 表格 -->
      <div>
        <el-table :data="tableData" height="250" border style="width: 100%">
          <el-table-column prop="time" label="日期" width="180"></el-table-column>
          <el-table-column prop="user" label="收货人" width="180"></el-table-column>
          <el-table-column prop="status" label="订单状态"></el-table-column>
          <el-table-column>
            <template slot-scope="scope">
              <el-button size="mini" @click="handleEdit(scope.row)">编辑</el-button>
              <el-dialog :visible.sync="editFormVisiable">
                <el-form size="small" style="width:500px" label-width="100px" :model="editForm">
                  <!-- 收货人 -->
                  <el-form-item label="收货人">
                    <el-input style="width:300px;" v-model="editForm.user" placeholder="收货人"></el-input>
                  </el-form-item>
                  <!-- 订单状态 -->
                  <el-form-item label="订单状态">
                    <el-select style="width:300px;" v-model="editForm.status" placeholder="订单状态">
                      <el-option label="未发货" value="未受理"></el-option>
                      <el-option label="已受理" value="已受理"></el-option>
                      <el-option label="已送达" value="已送达"></el-option>
                    </el-select>
                  </el-form-item>
                  <!-- 下单时间 -->
                  <el-form-item label="下单时间">
                    <el-date-picker
                      style="width:300px"
                      v-model="editForm.time"
                      value-format="yyyy-MM-dd HH:mm:ss"
                      type="datetime"
                      placeholder="选择日期时间"
                    ></el-date-picker>
                  </el-form-item>
                </el-form>
                <div slot="footer" class="dialog-footer">
                  <el-button size="small" @click="editFormVisiable = false">取 消</el-button>
                  <el-button size="small" :plain="true" type="primary" @click="submitEdit">确 定</el-button>
                </div>
              </el-dialog>
              <el-button size="mini" type="danger" @click="handleDelete(scope.row)">删除</el-button>
            </template>
          </el-table-column>
        </el-table>
      </div>
      <!-- 分页 -->
      <el-pagination
        @current-change="handleCurrentChange"
        :current-page="currentPage"
        :page-sizes="[3, 5, 7, 10,20]"
        :page-size="pageSize"
        layout="total, prev, pager, next, jumper"
        :total="total"
      ></el-pagination>
    </el-card>
  </div>
</template>
2.script
<script>
export default {
  data() {
    return {
      currentPage: 1, //当前页
      pageSize: 3, //每页条数
      total: 0, //总条数
      // 日期时间
      pickerOptions: {
        shortcuts: [
          {
            text: "最近一周",
            onClick(picker) {
              const end = new Date();
              const start = new Date();
              start.setTime(start.getTime() - 3600 * 1000 * 24 * 7);
              picker.$emit("pick", [start, end]);
            }
          },
          {
            text: "最近一个月",
            onClick(picker) {
              const end = new Date();
              const start = new Date();
              start.setTime(start.getTime() - 3600 * 1000 * 24 * 30);
              picker.$emit("pick", [start, end]);
            }
          },
          {
            text: "最近三个月",
            onClick(picker) {
              const end = new Date();
              const start = new Date();
              start.setTime(start.getTime() - 3600 * 1000 * 24 * 90);
              picker.$emit("pick", [start, end]);
            }
          }
        ]
      },
      // 渲染表格数据
      tableData: [],
      list: [], //存入本地记录
      // 新增表单
      form: {
        user: "",
        status: [],
        time: ""
      },
      dialogFormVisible: false, //新增弹框
      editFormVisiable: false, //编辑弹框
      // 编辑表单
      editForm: {
        user: "",
        status: [],
        time: ""
      },
      rowItem: {}, // 编辑每项内容
      // 初始查询表单
      formInline: {
        user: "",
        status: [],
        time: []
      },
      // 查询表单
      searchForm: {
        user: "",
        status: [],
        time: []
      },
      searchData: [] //查询到的数据
    };
  },
  methods: {
    // 渲染数据
    showList() {
      if (JSON.parse(window.localStorage.getItem("list"))) {
        this.list = JSON.parse(window.localStorage.getItem("list"));
        this.tableData = [...this.list];//渲染数组
        this.total = this.list.length;//数据总条数
        this.changePage(this.list);//进入页面返回到第一页
      }
    },
    // 当前页
    handleCurrentChange(val) {
      this.currentPage = val;//当前页
      //如果查询数据存在,则渲染查询数据
      if (this.searchData.length) {
        this.changePage(this.searchData);
      } else {
        this.changePage(this.list);//不存在则渲染全部数据
      }
    },
    // 分页显示
    changePage(obj) {
      const n = (this.currentPage - 1) * this.pageSize; //需要跳过的条数
      this.tableData = obj.slice(n, n + this.pageSize);
    },
    // 增加
    addNew() {
      this.list.unshift(this.form);
      this.list.sort((a, b) => {
        return new Date(b.time).getTime() - new Date(a.time).getTime();
      }); //降序
      window.localStorage.setItem("list", JSON.stringify(this.list));
      this.form = {};
      this.dialogFormVisible = false;
      this.showList();
    },
    // 删除
    handleDelete(row) {
      this.$confirm("此操作将永久删除该记录, 是否继续?", "提示", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning"
      })
        .then(() => {
          this.list.splice(this.list.indexOf(row), 1);
          window.localStorage.setItem("list", JSON.stringify(this.list));
          this.currentPage = 1;
          this.showList();
          this.$message({
            type: "success",
            message: "删除成功!"
          });
        })
        .catch(() => {
          this.$message({
            type: "info",
            message: "已取消删除"
          });
        });
    },
    // 编辑
    handleEdit(row) {
      this.editFormVisiable = true;
      this.rowItem = row;
      this.editForm = { ...row };
    },
    // 确认编辑
    submitEdit() {
      this.editFormVisiable = false;
      this.list[this.list.indexOf(this.rowItem)] = this.editForm;
      this.list.sort((a, b) => {
        return new Date(b.time).getTime() - new Date(a.time).getTime();
      }); //降序
      window.localStorage.setItem("list", JSON.stringify(this.list));
      this.showList();
      this.$message({
        message: "恭喜你,修改成功",
        type: "success"
      });
    },
    // 查询
    onSubmit() {
      this.currentPage = 1;//回到第一页
      this.searchData = []; //初始化搜索数据
      this.searchForm = { ...this.formInline };
      if (this.searchForm.user) {//如果搜索对象中user存在
        this.searchData = this.list.filter(item =>
          item.user.match(this.searchForm.user)
        );
        this.total = this.searchData.length;
        this.changePage(this.searchData);
        if (this.searchForm.status) {//如果搜索对象中status存在
          this.searchStatus(this.searchData);
          if (this.searchForm.time && this.searchForm.time.length) {//如果搜索对象中time存在
            this.searchTime(this.searchData);
          }
        } else if (this.searchForm.time && this.searchForm.time.length) {//如果搜索对象中time存在
          this.searchTime(this.searchData);
        }
      } else if (this.searchForm.status) {//如果搜索对象中status存在
        this.searchStatus(this.list);
        if (this.searchForm.time && this.searchForm.time.length) {//如果搜索对象中time存在
          this.searchTime(this.searchData);
        }
      } else if (this.searchForm.time && this.searchForm.time.length) {//如果搜索对象中time存在
        this.searchTime(this.list);
      } else {//如果搜索对象为空
        this.showList();
      }
      this.formInline = {};
    },
    // 查询状态
    searchStatus(obj) {
      this.searchData = obj.filter(item =>
        item.status.match(this.searchForm.status)
      );
      this.total = this.searchData.length;//搜索结果数据总条数
      this.changePage(this.searchData);//传入渲染
    },
    // 查询时间
    searchTime(obj) {
      let beforeTime = new Date(this.searchForm.time[0]).getTime();//查询时间范围下限
      let afterTime = new Date(this.searchForm.time[1]).getTime();//查询时间范围上限
      this.searchData = obj.filter(
        item =>
          beforeTime <= new Date(item.time).getTime() &&
          new Date(item.time).getTime() <= afterTime
      );
      this.total = this.searchData.length;//搜索数据总条数
      this.changePage(this.searchData);//传入渲染
    }
  },
  created() {
    this.showList();
  }
};
</script>
3.style
<style lang="less" scoped>
#app {
  .box-card {
    width: 800px;
    margin: 40px auto;
  }
  /deep/ .el-dialog {
    width: 40%;
  }
}
</style>
GitHub 加速计划 / eleme / element
54.06 K
14.63 K
下载
A Vue.js 2.0 UI Toolkit for Web
最近提交(Master分支:3 个月前 )
c345bb45 7 个月前
a07f3a59 * Update transition.md * Update table.md * Update transition.md * Update table.md * Update transition.md * Update table.md * Update table.md * Update transition.md * Update popover.md 7 个月前
Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐