誉天程序员-2301-3-day08

4. 书籍管理实现CURD

这个结构比较复杂,是有一套复杂的机制,注意它们之间的关系和控制实现。

 新增和修改怎么复用对话框

 对话框中的数据,表格中展现的数据,临时记录正在操作的数据统一联动起来

 单条删除怎么传递数据,多条删除怎么传递数据

 修改怎么传递当前修改记录的索引值index

4.1. 删除

4.1.1. 增加插槽

Vue给我们提供了一个很好用的功能template插槽,可以自动为我们传递一些对象,如row行对象,这样我们就无需自己去写代码,直接拿过来用即可。

官网地址:

https://element-plus.gitee.io/zh-CN/component/table.html#table-column-插槽

https://element-plus.gitee.io/zh-CN/component/table.html#自定义列模板

插槽传递当前行数据,自动封装到row中,我们直接使用row对象即可:

csharp 复制代码
<el-table-column label="操作" width="200">
	<template #default="scope">
		...
	</template>
</el-table-column>

4.1.2. 删除按钮

注意:row代表的是业务数据,所以并不包含index,而插槽额外提供了属性 i n d e x 代表索引值。定义的写法有点与众不同,采用了 e s 6 的语法,前面加个 index代表索引值。定义的写法有点与众不同,采用了es6的语法,前面加个 index代表索引值。定义的写法有点与众不同,采用了es6的语法,前面加个,使用时需要注意。

java 复制代码
<el-button type="danger" size="small" @click="handleDel(scope.$index, scope.row)">
	<el-icon class="el-icon--left"><CircleCloseFilled /></el-icon>删除
</el-button>

4.1.3. 删除事件

splice从数组中移除元素

java 复制代码
//根据槽传过来的row当前行数据,获取其数组的索引位置,调用splic方法进行删除
	const handleDel = (index, row)=>{
		//从数组中删除索引起始的位置,删除1条
		tableData.value.splice(index, 1)
	}

4.2. 批量删除

4.2.1. 增加选择列

之前我们已经加了多选列,type="selection",用其可以记录下用户选中的记录

java 复制代码
<el-table-column prop="id" type="selection" width="55" />

4.2.2. 触发的事件

增加选择时触发的selection-change事件

java 复制代码
<el-table :data="tableData" border @selection-change="handleSelectionChange">

4.2.3. 选择事件

多选按钮,ElementPlus框架会自动把选中的行存放到muchSelection数组中。

java 复制代码
const muchSelection = ref([])	//用于记录多选选中的集合
//表格的多选事件,val保存了被选中的行的
const handleSelectionChange = (val)=>{
	muchSelection.value = val
	//console.log(muchSelection.value)
}

4.2.4. 批量删除动态展现

我们还实现了很酷炫的效果,通过v-if判断muchSelection.length数组的长度,实现是否展现批量删除按钮。数组为空就不展现,数组不为空就展现。

java 复制代码
<el-button v-if="muchSelection.length" type="danger" size="small" @click="handleDelList">
			批量删除
		</el-button>

4.2.5. 循环删除

循环调用删除一条实现。

java 复制代码
//批量删除
	const handleDelList = () => {
		//遍历拿到每一行,调用单个删除
		muchSelection.value.forEach(row=>{
			// indexOf获取当前行数据在数组中的索引值
			const index = tableData.value.indexOf(row)
			if(index != -1){
				handleDel(index, row)
			}
		})
	}

4.3. 转向新增

4.3.1. 新增按钮

java 复制代码
<el-button type="primary" size="small" @click="toAdd">
	<el-icon class="el-icon--left"><CirclePlus /></el-icon>
	新增
</el-button>

4.3.2. 按钮方法

...(对象展开运算符)form.data,formInit这两个展开的对象属性会合并到 form.data 对象中,如果有相同属性名则会用 formInit 对象的对应属性值覆盖 form.data 对象的属性值。

formInit覆盖了之前旧的数据,但对象的结构未破坏,因为form.data是新对象也和form数据分开。这就解决了先去修改,再进新增时,数据回显错误的问题。

//转向新增

java 复制代码
const toAdd = ()=>{
	form.data = {
	  ...form.data,
	  ...formInit		//利用init覆盖了现有数据
	}

	dialogVisible.value = true
	dialogType.value = 'add'
}

4.4. form数据

java 复制代码
const formInit = {	//初始化值
  name: '',
  author: '',
  publishing: '',
  printTime: new Date()
}
let form = reactive(formInit)	//对话框表单绑定数据

4.5. 新增

4.5.1. 新增保存

新增修改复用了对话框代码就带来一个副作用,到底当前是新增还是修改呢?那我们再专门设置一个变量来判别。通过这个判别我们就可以修改对话框的标题,到底是新增还是修改了。

java 复制代码
const dialogType = ref('add')

const dialogSave = (index)=>{
	if(dialogType.value === 'add'){
		tableData.push(form.data)
	}else{
		tableData[index] = {
		  ...tableData[index],
		  ...form.data
		}
	}
	dialogVisible.value = false	//关闭对话框
}

4.5.2. 对话框的标题

通过三元表达式进行判别:

java 复制代码
  <el-dialog v-model="dialogFormVisible">
	<template v-slot:title>
		<span style="font-weight: bold;"><el-icon><ElementPlus /></el-icon>
		 {{dialogType.value==='update'?'修改':'新增'}}书籍管理</span>
	</template>

4.6. 修改

4.6.1. 问题

修改较为复杂,会遇到两个问题:

1)因为修改分为两个过程,打开修改的对话框,点击对话框中的确认按钮。index是传递给打开抽屉的方法handleEdit,而抽屉表单确认是方法confirmClick。它们之间断开了,参数就无法传递。而我们在表单确认时,要去知道具体修改的是哪一条,这怎么办呢?

解决办法:加个公用变量curIndex,这样我们在handleEdit时设置,在confirmClick就可以调用了。

2)修改时如果直接使用form.value=row,进行处理。当我们修改表单值时,页面的值也会随之修改。这是响应式对象的缺点,因为它们是一份引用,所以一个变,其它就跟着变。怎么解决呢?

解决方案:利于js提供的Oject.assign将对象内容复制,而不是引用。这样就断开了其中的关系。修改表单时,页面数据就不会同时被修改了。

4.6.2. 修改按钮

传递修改的索引值和当前行数据

java 复制代码
<el-button @click="toEdit(scope.$index)" type="success" size="small"><el-icon><EditPen /></el-icon> 修改</el-button>

4.6.3. 按钮事件

java 复制代码
let curIndex = ref(-1)
const toEdit = (index)=>{
	form.data = {		//回显数据
	  ...form.data,
	  ...tableData[index]
	}
	
	curIndex = index	//保留下来当前的索引值,供修改保存方式使用
	dialogVisible.value = true
	dialogType.value = 'edit'
}

4.6.4. 修改保存

java 复制代码
const dialogSave = (index)=>{
	if(dialogType.value === 'add'){
		tableData.push(form.data)
	}else{
		tableData[index] = {
		  ...tableData[index],
		  ...form.data
		}
	}
	dialogVisible.value = false	//关闭对话框
}	

4.7. 日期格式转化

4.7.1. 问题

复制代码
日期显示为格林威治时间,不符合中文日常习惯。
java 复制代码
//导入日期函数库
import { format } from 'date-fns'
//配置表格列,它会自动回调这个方法,每行数据都回调,vue会传递3个参数给我们
const formatDate = (row, index, cellValue)=>{
	return format(cellValue, 'yyyy-MM-dd')	//调用函数库方法
}

4.8. 查询

4.8.1. 搜索框

java 复制代码
<el-row style="padding:10px;">
	<div>
		<el-button type="primary" size="small" @click="toAdd">
			<el-icon><CirclePlus /></el-icon> 新增
		</el-button>
		<el-button v-if="multipleSelection.length" type="danger" size="small" @click="handlerMuchDel">删除多条</el-button>
	</div>
	<div style="padding-left:10px;">
		<el-input size="small" v-model="searchBookName" width="100" placeholder="按书名检索"  clearable>
			<template #append><el-icon><Search /></el-icon></template>
		</el-input>
	</div>
	<div style="padding-left:10px;">
		<el-input size="small" v-model="searchAuthor" placeholder="按作者检索" clearable>
			<template #append><el-icon><Search /></el-icon></template>
		</el-input>
	</div>
</el-row>

4.8.2. 换数据绑定

将tableData换成filteredData:

java 复制代码
<el-table :data="filteredData"...

4.8.3. 数据过滤

java 复制代码
import {ref,computed} from 'vue'
...
const searchBookName = ref('')	//按书名搜索
	const searchAuthor = ref('')	//按书名搜索
	import {computed} from 'vue'	//动态计算,搜索框输入内容变化会自动触发

	let filterData = computed(()=>{
		return tableData.filter((r)=>{
			//并列条件
			return r.name.includes(searchBookName.value) && r.author.includes(searchAuthor.value)
			//或者条件
			// return r.name.includes(searchBookName.value) || r.author.includes(searchAuthor.value)
		})
	})
相关推荐
腾讯TNTWeb前端团队6 小时前
helux v5 发布了,像pinia一样优雅地管理你的react状态吧
前端·javascript·react.js
范文杰10 小时前
AI 时代如何更高效开发前端组件?21st.dev 给了一种答案
前端·ai编程
拉不动的猪10 小时前
刷刷题50(常见的js数据通信与渲染问题)
前端·javascript·面试
拉不动的猪10 小时前
JS多线程Webworks中的几种实战场景演示
前端·javascript·面试
FreeCultureBoy11 小时前
macOS 命令行 原生挂载 webdav 方法
前端
uhakadotcom11 小时前
Astro 框架:快速构建内容驱动型网站的利器
前端·javascript·面试
uhakadotcom11 小时前
了解Nest.js和Next.js:如何选择合适的框架
前端·javascript·面试
uhakadotcom11 小时前
React与Next.js:基础知识及应用场景
前端·面试·github
uhakadotcom12 小时前
Remix 框架:性能与易用性的完美结合
前端·javascript·面试
uhakadotcom12 小时前
Node.js 包管理器:npm vs pnpm
前端·javascript·面试