纯前端实现增-删-改-查(模糊查询)和分页[本地存储当成数据库(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>
更多推荐
所有评论(0)