这里我使用 Ant-Design-Vue 组件库, 使用 vue2 , 我们在使用 a-table 组件的时候,会经常碰到表格中需要有子级展开的需求,而 组件中的 defaultExpandedRowKeys 不是响应式的,也就是说我们第一次进来,会加载一次,后面我们动态改变 defaultExpandedRowKeys 以后,展开项不会动态改变,这里我们的思路分两部分,第一部分是动态判断哪些子表是需要展开的,第二部分是利用 key 的属性, 动态更改 key , 让 table 刷新。
- 首先来看实现的样子是什么样子的:
我们需要实现一个这样的表格, 这是一个弹窗其实, 他有两种打开方式, 一种是不传入数据,就是我们表格里面的各个字段都是空的,如下:
另外一种就是传入数据的,就和第一张图一样, 每一行的子表是根据当前父级的某个数据字段状态来判定是否展开,上代码~
<template>
<div>
<a-table
:data-source="dataSource"
:columns="columns"
:rowKey="
(record, index) => {
return index
}
"
:key="changeKey"
:expandIconAsCell="false"
:expandIconColumnIndex="5"
:defaultExpandedRowKeys="defaultExpandedData"
:pagination="false"
:scroll="dataSource.length > 7 ? { y: 300 } : {}"
>
<template slot="expandIcon" slot-scope="props">
<span style="cursor: pointer">
<div
:ref="props.record.order"
v-if="props.expanded"
style="display: inline-block; margin-right: 10px"
@click="(e) => clickHandler(props, e)"
>
<a-icon type="down-circle" />
</div>
<div v-else style="display: inline-block; margin-right: 10px" @click="(e) => clickHandler(props, e)">
<a-icon type="up-circle" />
</div>
</span>
</template>
<span slot="expandedRowRender" slot-scope="textA" style="margin: 0">
<a-table
style="width: 730px; margin-left: 50px"
:data-source="textA?.childrenData ?? []"
:columns="childrenColumns"
:rowKey="
(record, index) => {
return index
}
"
:bordered="true"
:pagination="false"
:scroll="textA?.childrenData?.length > 4 ? { y: 250 } : {}"
>
<span slot="leastRender" slot-scope="text,record">
<a-input-number :min="0" :max="100" :value="text" style="width:60px" @change="(value)=>inputChange(value,record,textA)"/> %
</span>
</a-table>
</span>
<span slot="action" slot-scope="text, record">
<a-icon
style="margin-right: 10px"
@click="editorHandler(0, record)"
v-if="record.order !== 1"
type="minus"
class="btn_box"
/>
<a-icon
@click="editorHandler(1, record)"
v-if="record.order === dataSource.length"
type="plus"
class="btn_box"
/>
</span>
</a-table>
</div>
</template>
<script>
/* eslint-disable */
import { Ellipsis } from '@/components'
const columns = [
{ title: '序号', dataIndex: 'order', align: 'center', width:'100px' },
{ title: '线路', dataIndex: 'genderName', align: 'center', scopedSlots: { customRender: 'selectRender' }, width:'200px' },
{ title: '时刻表', dataIndex: 'timeList', align: 'center', scopedSlots: { customRender: 'timeList' },width:'200px' },
{ title: '首站线路可用电桩数', dataIndex: 'departure', align: 'center', scopedSlots: { customRender: 'departure' },width:'150px' },
{ title: '末站线路可用电桩数', dataIndex: 'terminal', align: 'center', scopedSlots: { customRender: 'terminal' },width:'150px' },
{ title: '', dataIndex: '', align: 'center', scopedSlots: { customRender: 'action' },width:'100px' },
]
const childrenColumns = [
{
title: '车型',
dataIndex: 'busTypeName',
align: 'center',
width: '150px'
},
{
title: '续航里程(公里)',
dataIndex: 'busMileage',
align: 'center',
width: '120px'
},
{
title: '充电时长(分)',
dataIndex: 'chargeDuration',
align: 'center',
width: '120px'
},
{
title: '最少剩余电量',
dataIndex: 'soc',
align: 'center',
width: '100px',
scopedSlots: { customRender: 'leastRender' }
}
]
export default {
components:{
Ellipsis
},
props: {
dataSource:{
type: Array,
default: () => []
},
handleSelect:{
type: Function,
default: () => {}
},
hanlderNumCounts:{
type: Function,
default: () => {}
},
handleSelectTime:{
type: Function,
default: () => {}
},
editorHandler:{
type: Function,
default: () => {}
},
inputChange:{
type: Function,
default: () => {}
},
assessData:{
type: Array,
default: () => []
},
defaultExpandedData: {
type: Array,
default: () => []
}
},
data(){
return {
columns,
changeKey:1,
childrenColumns
}
},
watch:{
defaultExpandedData:{
handler(){
this.changeKey++
},
deep: true,
immediate: true
}
},
methods:{
// 展开收起
clickHandler(props, e) {
props.onExpand(props.record?.childrenData, e)
}
}
}
</script>
这里我把这个表格封装成了一个子组件, 由父组件来进行调用, 这里有几个关键点 首先是这个几个属性:
:expandIconAsCell="false" // 关闭按钮放置在第一列,设置这个之后才可以设置展开按钮显示在哪一列
:expandIconColumnIndex="5" // 展开按钮所在位置 我这里按钮放在最后一行 加减号千前面
:defaultExpandedRowKeys="defaultExpandedData" // 默认展开行 是数组 每一项是表格中哪一行下的子级展开[0,2,4]
其次是 key
, 就是我上面代码给 a-table
表格中 使用的key
, changeKey
是自己定义的一个数值, 当我们父组件传入的 defaultExpandedData
默认选中项改变以后(使用watch
侦听), 则让key++
这样 table
就会从新渲染了,达到了改变选中项的效果
- 下面来看父组件的使用
<template>
<step1
:dataSource="dataSource"
:handleSelect="handleSelectChange1"
:editorHandler="editorHandler"
:defaultExpandedData="defaultExpandedData"
:assessData="assessData"
:inputChange="inputChange1"
:hanlderNumCounts="hanlderNumCounts"
:handleSelectTime="handleSelectTime"
/>
</template>
<script>
export default {
data(){
return {
defaultExpandedData: [],
dataSource: [
{
order: 1,
...generalA
},
{
order: 2,
...generalA
}
],
}
},
watch: {
// 动态加载两个表格的子表展开状态, 子表中通过 自定义的 key 来完成动态展开(展开状态只会在加载的时候初始化,期响应式修改展开状态不会重新渲染)
dataSource: {
handler() {
this.defaultExpandedData = this.dataSource?.filter((item) => item?.genderName).map((item) => item.order - 1)
},
deep: true,
immediate: true
},
}
}
</script>
父组件当中关键点是那个 watch
, 这个没难度了就, 侦听我们 data
数据源, 发生改变以后,通过咱们数据当中自己定义的一些字段,取判定是否需要展开这一项,得到需要展开的数组的下标,这里我的 order
是序号,所以 -1 了。
还有另外一种实现方式,就是把 key 加到父组件上, 大同小异。
还有一种方式就是,改变 defaultExpandedRowKeys
原数组,而不是覆盖的方式去触发,之前我使用过一次,但是实行起来比较麻烦,每一次响应式,都要去进行 push
、splice
、findeIndex
或者 sort
等。这里给大家提供一下这个思路, 就不贴代码了~
代办报建
本公司承接江浙沪报建代办施工许可证。
联系人:张经理,18321657689(微信同号)。
11条评论
鉴定完毕!http://bbs.kdhlpt.com/article/1247790.html
小弟默默的路过贵宝地~~~http://xcaeid.hjgbigdata.com
楼主英明!http://59p.982010.com
楼上的这是啥态度呢?http://r8ki0b.60bq.com
楼上的心情不错啊!http://hqu3.dfwulian.com
楼主的帖子越来越有深度了!http://tpoxy.fdstx.com
楼主今年多大了?http://www.3553km.com
有机会找楼主好好聊聊!http://www.3553km.com
好东西,赞一个!http://51pk.txf5.com
经典,收藏了!http://www.guangcexing.net/voddetail/peCVMVhRYaW.html
我就搞不明白了,看帖回帖能死人么,居然只有我这么认真的在回帖!https://www.telegramxp.com/
发表评论