纯前端实现增-删-改-查(模糊查询)和分页[本地存储当成数据库(vue + element)]

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

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

在这里插入图片描述

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>
  • 16
    点赞
  • 88
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,我可以给您一些指导。 首先,增删改查和带条件的分页询是后端开发的基础操作之一,而 Spring 框架提供了很多方便的工具来实现这些操作。下面是一些步骤和代码示例,希望能对您有所帮助。 1. 数据库建表 首先,您需要在数据库中创建相应的表,例如一个名为 user 的用户表,表中包含 id、name、age、gender 等字段。 2. 创建 Entity 类 接下来,您需要创建一个与数据库表对应的实体类,通常称为 Entity 类。该类的属性需要与数据库表中的字段一一对应。例如: ```java @Entity @Table(name = "user") public class User { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @Column(name = "name") private String name; @Column(name = "age") private Integer age; @Column(name = "gender") private String gender; // getter/setter 略 } ``` 3. 创建 Repository 接口 接着,您需要创建一个 Repository 接口,用于操作数据库。Repository 接口通常继承 JpaRepository 或 JpaSpecificationExecutor 接口,以便使用 Spring Data JPA 提供的增删改查分页询方法。例如: ```java @Repository public interface UserRepository extends JpaRepository<User, Long>, JpaSpecificationExecutor<User> { } ``` 4. 创建 Service 类 然后,您需要创建一个 Service 类,用于封装业务逻辑。Service 类通常调用 Repository 中的方法来实现具体的操作。例如: ```java @Service public class UserService { @Autowired private UserRepository userRepository; public List<User> findAll() { return userRepository.findAll(); } public void save(User user) { userRepository.save(user); } public void delete(Long id) { userRepository.deleteById(id); } public User findById(Long id) { return userRepository.findById(id).orElse(null); } public Page<User> findByCondition(String name, Integer age, String gender, Pageable pageable) { Specification<User> specification = (root, criteriaQuery, criteriaBuilder) -> { List<Predicate> predicates = new ArrayList<>(); if (StringUtils.isNotBlank(name)) { predicates.add(criteriaBuilder.like(root.get("name"), "%" + name + "%")); } if (age != null) { predicates.add(criteriaBuilder.equal(root.get("age"), age)); } if (StringUtils.isNotBlank(gender)) { predicates.add(criteriaBuilder.equal(root.get("gender"), gender)); } return criteriaBuilder.and(predicates.toArray(new Predicate[predicates.size()])); }; return userRepository.findAll(specification, pageable); } } ``` 5. 创建 Controller 类 最后,您需要创建一个 Controller 类,用于处理前端请求。Controller 类通常调用 Service 中的方法来实现具体的操作,并将结果以 JSON 格式返回给前端。例如: ```java @RestController @RequestMapping("/api/user") public class UserController { @Autowired private UserService userService; @GetMapping("/") public List<User> findAll() { return userService.findAll(); } @PostMapping("/") public void save(@RequestBody User user) { userService.save(user); } @DeleteMapping("/{id}") public void delete(@PathVariable Long id) { userService.delete(id); } @GetMapping("/{id}") public User findById(@PathVariable Long id) { return userService.findById(id); } @GetMapping("/search") public Page<User> findByCondition(@RequestParam(required = false) String name, @RequestParam(required = false) Integer age, @RequestParam(required = false) String gender, @PageableDefault(size = 10, sort = {"id"}, direction = Sort.Direction.ASC) Pageable pageable) { return userService.findByCondition(name, age, gender, pageable); } } ``` 6. 创建前端页面 在前端页面中,您可以使用 vue 框架来实现用户界面。例如,您可以创建一个 user.vue 组件,包含增删改查分页询等功能。具体实现方式可以参考 vue 官方文档和相关教程。 以上是一个简单的增删改查和带条件的分页询的实现步骤和代码示例。当然,实际项目中可能会更加复杂,需要根据具体情况进行调整。希望能对您有所帮助。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值