在线客服

a-table 默认展开行动态加载

adminadmin 报建百科 2024-04-24 121 11
a-table 默认展开行动态加载

这里我使用 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 表格中 使用的keychangeKey 是自己定义的一个数值, 当我们父组件传入的 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 原数组,而不是覆盖的方式去触发,之前我使用过一次,但是实行起来比较麻烦,每一次响应式,都要去进行 pushsplicefindeIndex 或者 sort等。这里给大家提供一下这个思路, 就不贴代码了~

本网站是一个以CSS、JavaScript、Vue、HTML为核心的前端开发技术网站。我们致力于为广大前端开发者提供专业、全面、实用的前端开发知识和技术支持。 在本网站中,您可以学习到最新的前端开发技术,了解前端开发的最新趋势和最佳实践。我们提供丰富的教程和案例,让您可以快速掌握前端开发的核心技术和流程。 本网站还提供一系列实用的工具和插件,帮助您更加高效地进行前端开发工作。我们提供的工具和插件都经过精心设计和优化,可以帮助您节省时间和精力,提升开发效率。 除此之外,本网站还拥有一个活跃的社区,您可以在社区中与其他前端开发者交流技术、分享经验、解决问题。我们相信,社区的力量可以帮助您更好地成长和进步。 在本网站中,您可以找到您需要的一切前端开发资源,让您成为一名更加优秀的前端开发者。欢迎您加入我们的大家庭,一起探索前端开发的无限可能!
代办报建

本公司承接江浙沪报建代办施工许可证。
联系人:张经理,18321657689(微信同号)。

喜欢0发布评论

11条评论

  • 游客 发表于 5个月前

    鉴定完毕!http://bbs.kdhlpt.com/article/1247790.html

  • 游客 发表于 4个月前

    楼主今年多大了?http://www.3553km.com

  • 游客 发表于 4个月前

    有机会找楼主好好聊聊!http://www.3553km.com

  • 游客 发表于 4个月前

    经典,收藏了!http://www.guangcexing.net/voddetail/peCVMVhRYaW.html

  • 电报下载 发表于 4周前

    我就搞不明白了,看帖回帖能死人么,居然只有我这么认真的在回帖!https://www.telegramxp.com/

发表评论

  • 昵称(必填)
  • 邮箱
  • 网址