element的table 表格 expand-change事件遇到的bug,记录下

文章讲述了在业务场景中,如何解决表格嵌套时的点击问题,即用户需要点击两次才能展开子表格。作者发现原因是由于最外层表格的数据是响应式,导致第一次点击未展开,解决办法是将row的响应式数据转换为非响应式。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

业务场景是,一个table表格中嵌套table,当点击展开时,需要点击2次才能真正展开列表,我是通过设置外层table的一个属性isExpand的属性值来判断当前行的点击是展开还是折叠状态,废话不多说,直接上图片

首先获取table表格数据时,添加了一项,用来表示行的展开与折叠

在这里插入图片描述

下面图片中框住的部分很重要,这个就是造成第一次点击展开,其实已经发送请求,但子table并未展开,需要再点一次才能出来,这块,我猜想是因为最外层的表格数据是响应式数据,传递的参数row也是响应式的,因此改了row.isExpand,造成了页面刷新,所以第一次点击没有展开,第二次才展开,图中圈中的部分,把row的响应式数据变成非响应式数据就可以了,点击展开立即就可以展开子table

在这里插入图片描述
贴下我的代码

111111

<div class="my-table">
              <MyTable ref="myTableRef" v-loading="loading" :columns="tableColumn" :table-data="tableData" :options="options"
               @command="handleCommand"
                @pagination-change="(page, pageSize) => _getTableData(page, pageSize)"
                主要就是看下👇这一行,展开事件的调用方法
                @expand-change="(row, obj)=>_getbaseStationTableData(row,obj)">
                <!-- slot,子级table -->
                <template #expand="{ row }: any" >
                <MyTable v-loading="baseStationLoading" :columns="baseStationTableColumn" :table-data="baseStationTableData" :options="{...baseStationOptions,empty:true}"
                    >
                    <!-- 插槽表头 -->
                    <template #deliveryHeader="{ column }: any">
                      <el-icon color="#b6b6b6" style="font-size:16px;cursor: pointer;">
                        <Plus  @click="onBaseStationAdd" />
                      </el-icon>
                    </template>
                    <!-- 插槽操作项 -->
                    <template #opera="{ row }: any">
                      <el-icon color="#b6b6b6" style="font-size:16px;cursor: pointer;">
                        <Minus @click="onBaseStationDel(row)" />
                      </el-icon>
                    </template>
                    <!-- 插槽无数据项 -->
                    <template #empty> 暂无数据</template>
                  </MyTable>
                </template>
              </MyTable>

22222

const _getTableData = async (pageNum = 1, pageSize = 10) => {
  loading.value = true
  try {
    const res = await httpGet(`${devApiUrl}/lcap/v1/building?parkId=${props.parkId}&current=${pageNum}&size=${pageSize}`)
    if (res && res.code && res.code == '00000') {
      tableData.value = (res.data && res.data.rows) || []
      // 添加一项数据,判断该行是否是展开的状态,重点就下面👇这一行代码
      tableData.value = (res.data && res.data.rows && res.data.rows.length) && tableData.value.map((item) => ({ ...item, isExpand:false }))
      options.value.paginationConfig.total = (res.data && res.data.total) || 0
      loading.value = false
    } else {
      loading.value = false
      console.log('获取建筑信息失败')
    }
  } catch (error) {
    console.log(error)
    loading.value = false
  }
}

333333

 const _getbaseStationTableData = async (row, obj) => {
    // 需要把row的响应式数据变成非响应式数据,这个很重要,这样的话,就不会出现需要点击两次才能真正展开子级table
    row = toRaw(row)
    // 如果之前展开过,不需要再次请求数据,直接return
    // 这里分为两种情况,
    // 第1种是:他点击的折叠,那么更加不需要再次请求数据
    // 第2种情况是,他是第2次点击展开,那么也不需要请求远层数据
    if(row.isExpand){
      return
    }
    // 代码至此,说明是第一次点击展开,那么需要请求远层数据,并且设置展开状态
    row.isExpand = !row.isExpand
    //// 后面的可以不看,重点就是代码前面的
    baseStationLoading.value = true
    try {
      const res = await httpGet(`/api/lcap/v1/building/${row.id}/zones`)
      if (res && res.code && res.code == '00000') {
        baseStationTableData.value = (res.data && res.data) || []
        baseStationLoading.value = false
      } else {
        baseStationLoading.value = false
        console.log('获取基站列表失败')
      }
    } catch (error) {
      console.log(error)
      baseStationLoading.value = false
    }
  }
### Vue 中 `el-table` 组件 `expand-change` 事件的使用 在 Vue 应用程序中,Element UI 提供了丰富的组件来简化前端开发工作。对于表格组件 (`el-table`) 而言,其支持多种交互方式之一就是通过展开行(`expand`)功能实现更复杂的数据展示逻辑。 当涉及到异步加载子项数据时,可以利用 `expand-change` 事件监听用户的操作行为,在每次用户点击展开/收起某一行的时候触发相应的处理函数[^1]。 #### 处理流程说明 每当发生扩展变化时,会传递两个参数给回调函数:一个是当前被改变状态的那一行记录对象;另一个则是整个已展开行组成的数组列表。基于此机制,可以在接收到这些信息之后发起网络请求获取额外的信息并更新到界面上显示出来。 #### 实现代码示例 下面是一个简单的例子展示了如何结合 `axios` 来完成这一过程: ```javascript <template> <div id="app"> <!-- 定义 table 并绑定 expand-change --> <el-table :data="tableData" @expand-change="handleExpandChange"> <el-table-column type="expand"> <template slot-scope="props"> <p v-for="(item, index) in props.row.children">{{ item.name }}</p> </template> </el-table-column> <el-table-column label="日期" prop="date"></el-table-column> <el-table-column label="姓名" prop="name"></el-table-column> </el-table> </div> </template> <script> import axios from 'axios'; export default { data() { return { tableData: [ // 初始数据集... ] }; }, methods: { handleExpandChange(row, expandedRows) { const loadingIndex = this.tableData.indexOf(row); if (!row._loading && !row.children) { row._loading = true; setTimeout(() => { // 模拟异步请求延迟 axios.get('/api/getChildren', { params: { parentId: row.id } }) .then(response => { this.$set(this.tableData[loadingIndex], 'children', response.data); row._loading = false; }); }, 500); // 延迟时间设置为半秒 } } } }; </script> ``` 在这个案例里,首先定义了一个基础表格结构,并绑定了 `@expand-change` 方法用于响应用户的动作。接着,在 JavaScript 部分实现了具体的业务逻辑——即根据传入的 `row` 参数判断是否已经存在对应的子级数据,如果没有则执行一次模拟的 API 请求去拉取新资料填充至视图当中。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值