0
Follow
0
View

The Element ui uses expand-change of el-table to load the data js asynchronously

lucky_xu123 注册会员
2023-02-28 07:02

Can you use the code I provided to explain?

<template>
  <div class="sys-container-box">
    <div class="committee-container">
      <div class="committee-head">
        <h3 v-page-title="$route">h3>
        <div>
          <el-button type="primary" size="small" @click="handleDictionary('', 'add')">
            新增字典项
          el-button>
        div>
      div>
      <div class="layout-search-wrap">
        <el-form ref="search" :model="searchForm" label-width="" size="small" inline>
          <el-form-item label="字典名称" prop="dictName">
            <el-input
              v-model="searchForm.dictName"
              @keyup.enter.native="searchData"
              placeholder="按 字典名称 检索"
            >el-input>
          el-form-item>
          <el-form-item label="字典类型" prop="dictType">
            <el-select
              v-model="searchForm.dictType"
              @keyup.enter.native="searchData"
              filterable
              placeholder="选择 字典类型"
            >
              <template v-for="item in typeData">
                <el-option
                  :key="item.dictTypeId"
                  :label="item.dictValue"
                  :value="item.id"
                >el-option>
              template>
            el-select>
          el-form-item>
          <el-form-item label="创建时间" prop="createTime">
            <el-date-picker
              v-model="searchForm.createTime"
              type="daterange"
              range-separator="至 "
              start-placeholder="开始日期"
              end-placeholder="结束日期"
              format="yyyy-MM-dd"
              value-format="yyyy-MM-dd"
              :picker-options="endDateOption"
            >
            el-date-picker>
          el-form-item>
          <el-form-item>
            <el-button type="primary" plain @click="searchData">查询el-button>
            <el-button plain @click="resetSearch">重置el-button>
          el-form-item>
        el-form>
      div>
      <div class="layout-table-wrap">
        <div class="layout-table-body">
          <el-table
            @expand-change="expandChange"
            :expand-row-keys="expandKeys"
            row-key="id"
            :data="tableData"
            stripe
            :default-expand-all="expandAll"
            ref="table"
          >
            <el-table-column type="expand">
              <template slot-scope="">
                <el-table
                  v-loading="!this.isShow"
                  size="mini"
                  row-key="id"
                  :header-cell-style="{
                    background: '#ebf4fe',
                    height: '50px'
                  }"
                  :row-style="{ background: '#ebf4fe' }"
                  class="table-style"
                  :data="tags"
                  style="width: 60%;font-size: 10px;margin-left :auto"
                >
                  <template v-for="column in childTableColumn">
                    <el-table-column
                      :prop="column.prop"
                      :key="column.prop"
                      :label="column.label"
                      :width="column.width || ''"
                      :align="column.align || 'center'"
                      min-width="90"
                    >
                    el-table-column>
                  template>
                  <el-table-column fixed="right" label="操作" width="250" align="center">
                    <template slot-scope="scope">
                      <el-button
                        type="success"
                        plain
                        size="mini"
                        @click="handleTree(scope.row, 'edit')"
                      >
                        编辑
                      el-button>
                      <el-button
                        type="danger"
                        plain
                        size="mini"
                        @click="delChildDictionary(scope.row)"
                      >
                        删除
                      el-button>
                    template>
                  el-table-column>
                el-table>
              template>
            el-table-column>
            <template v-for="column in tableColumn">
              <el-table-column
                :prop="column.prop"
                :key="column.prop"
                :label="column.label"
                :width="column.width || ''"
                :align="column.align || 'center'"
                min-width="110"
              >
                <template slot-scope="scope">
                  <template v-if="column.prop === 'sort'">
                    <el-tag size="mini">
                      {{ scope.row.sort }}
                    el-tag>
                  template>
                  <template v-else>{{ scope.row[column.prop] || '-' }}template>
                template>
              el-table-column>
            template>
            <el-table-column fixed="right" label="操作" width="250" align="center">
              <template slot-scope="scope">
                <el-button
                  type="success"
                  plain
                  size="mini"
                  @click="handleDictionary(scope.row, 'edit')"
                >
                  编辑
                el-button>
                <el-button type="primary" plain size="mini" @click="handleTree(scope.row, 'add')"
                  >添加子项
                <el-button type="danger" plain size="mini" @click="delDictionary(scope.row)">
                  删除
                el-button>
              template>
            el-table-column>
          el-table>
        div>
        <div class="layout-table-foot">
          <pagination
            :page="searchForm.pageNo"
            :size="searchForm.pageSize"
            :total="tableTotal"
            @page-change="pageChange"
            @size-change="sizeChange"
          >pagination>
        div>
      div>
    div>
    <form-dialog
      :visible="visible"
      :id="rowId"
      :type="type"
      @close="dialogClose"
      @submit="dialogSubmit"
    />
    <tree-dialog
      :visible="visibleTree"
      :id="TreeId"
      :type="typeTree"
      @close="dialogClose"
      @submit="dialogTreeSubmit"
    />
  div>
template>

<script>
import {
  dictionaryManagementSearch_committee,
  dictionaryManagementTable_committee,
  childDictionaryManagementTable_committee
} from '_committee/config/table-form.js'
import {
  dictDataComboBoxCommittee,
  listDictDataComboBoxCommittee,
  delDictDataComboBoxCommittee,
  delChildDictDataComboBoxCommittee,
  listChildDictDataComboBoxCommittee
} from '_committee/config/api'
import { elConfirm } from '@/utils/elComponent.js'
import { isShowBtn } from '_committee/config/utils.js'

export default {
  name: 'CommitteeBusinessOperation',
  components: {
    Pagination: () => import('@/components/pagination/index.vue'),
    FormDialog: () => import('./form-dialog.vue'),
    TreeDialog: () => import('./tree-dialog.vue')
  },
  data() {
    return {
      tableData: [],
      tags: [],
      isShow: false,
      expandKeys: [],
      dictTypeId: '',
      typeData: [],
      tableTotal: 0,
      searchForm: dictionaryManagementSearch_committee(),
      tableColumn: dictionaryManagementTable_committee,
      childTableColumn: childDictionaryManagementTable_committee,
      visible: false,
      visibleTree: false,
      type: '',
      typeTree: '',
      rowId: '',
      TreeId: '',
      endDateOption: {
        disabledDate: time => {
          return time.getTime() > new Date().getTime()
        }
      }
    }
  },
  computed: {
    expandAll() {
      return this.from === 'moudle'
    },
    userInfo() {
      return this.$store.getters.getActiveRole
    }
  },
  mounted() {
    this.loadData()
  },
  methods: {
    setShowBtn(row, type = 'edit') {
      return isShowBtn(this.userInfo, row, type)
    },
    loadTypeData() {
      // 加载类型下拉
      dictDataComboBoxCommittee()
        .then(res => {
          this.pageLoading = false
          if (res.status === '0000') {
            this.typeData = res.data
          }
        })
        .catch(() => {
          this.pageLoading = false
        })
    },
    //  获取表格数据
    loadData() {
      let options = this.searchForm
      options.companyOrgId = this.userInfo.companyOrgId
      options.siteOrgId = this.userInfo.siteOrgId
      listDictDataComboBoxCommittee(options)
        .then(res => {
          this.pageLoading = false
          if (res.status === '0000') {
            this.tableData = res.data.records
            this.tableTotal = res.data.total
            this.dictTypeId = res.data.records
          }
          this.loadTypeData()
        })
        .catch(() => {})
    },
    // 加载子项列表
    loadTreeData() {
      let options = {}
      options.companyOrgId = this.userInfo.companyOrgId
      options.siteOrgId = this.userInfo.siteOrgId
      options.dictTypeId = this.TreeId
      listChildDictDataComboBoxCommittee(options)
        .then(res => {
          this.pageLoading = false
          if (res.status === '0000') {
            this.tags = res.data.records
            console.log(this.tags)
          }
        })
        .catch(() => {})
    },
    // 展开行
    expandChange(row) {
      if (!this.isShow) {
        //根据判定是否已经加载了数据
        setTimeout(() => {
          let options = {}
          options.companyOrgId = this.userInfo.companyOrgId
          options.siteOrgId = this.userInfo.siteOrgId
          options.dictTypeId = this.TreeId
          listChildDictDataComboBoxCommittee(options)
            .then(res => {
              this.pageLoading = false
              if (res.status === '0000') {
                let dateList = res.data.records.map(function(item) {
                  return item['dictTypeId']
                })

                dateList = dateList.filter(val => val == row.id)
                console.log(row.id)
                console.log(dateList)
                this.tags = res.data.records
                console.log(this.tags)
                this.isShow = true //加载成功之后更新标识

                this.expands.push(row.id)
                console.log(this.expands)
                console.log(this.isShow)
              }
            })
            .catch(() => {})

          this.$message({
            showClose: true,
            message: '数据加载成功'
          })
        }, 1000)
      }
      // 拿id
      // console.log(row.id)
      // this.TreeId = row.id
      // console.log(this.tags)
      // console.log(expandedRows[0].id)
      // let that = this
      // that.$nextTick(function() {
      //   this.loadTreeData()
      // })
      // this.loadTreeData()
      // if (expandedRows.length == 1) {
      //   this.expandKeys.shift()
      //   this.expandKeys = []
      //   return
      // }
      // console.log(expandedRows)
      // console.log(this.TreeId)
      // if (this.expands.includes(row.id)) {
      //   this.expands = this.expands.filter(val => val !== row.id)
      // } else {
      //   this.expands.push(row.id)
      // }
      // console.log(expandedRows)
      // console.log(this.tags)
      // console.log(this.expandKeys)
      // if (!expandedRows.length) {
      //   this.expandKeys.shift()
      //   this.expandKeys = []
      //   return
      // }
      // // //将展开行的id push到expandKeys数组里面
      // this.expandKeys = []
      // expandedRows.forEach(item => {
      //   this.expandKeys.shift()
      //   this.expandKeys.push(item.id)
      // })
      // // //判断是否关闭当前行
      // if (expandedRows.indexOf(row) == -1) {
      //   this.expandKeys.shift()
      //   row.expandedRows = []
      //   return
      // }
      // this.loadTreeData()
    },
    //  检索数据
    searchData() {
      this.searchForm.pageNo = 1
      this.loadData()
    },
    //  重置搜索表单
    resetSearch() {
      this.searchForm = dictionaryManagementSearch_committee()
      this.$nextTick(() => this.searchData())
    },
    // 新增/编辑
    handleDictionary(row, type) {
      this.visible = true
      this.type = type
      if (row) {
        this.rowId = row.id
      }
    },
    // 子项新增/编辑
    handleTree(row, typeTree) {
      this.visibleTree = true
      this.typeTree = typeTree
      if (row) {
        this.TreeId = row.id
      }
    },
    //  删除
    delDictionary(row) {
      console.log(row)
      elConfirm({
        title: '删除确认',
        content: `确定删除 ${row.dictName} 吗?`,
        callback: res => {
          if (res === 'success') {
            const options = {
              id: row.id
            }
            delDictDataComboBoxCommittee(options).then(res => {
              if (res.status === '0000') {
                this.$message.success('删除成功')
              } else {
                this.$message.error(`${res.msg} (${res.status})`)
              }
              this.loadData()
            })
          } else {
            this.$message.error('取消删除')
          }
        }
      })
    },
    // 删除子项
    delChildDictionary(row) {
      console.log(row)
      elConfirm({
        title: '删除确认',
        content: `确定删除 ${row.id} 吗?`,
        callback: res => {
          if (res === 'success') {
            const options = {
              id: row.id
            }
            delChildDictDataComboBoxCommittee(options).then(res => {
              if (res.status === '0000') {
                this.$message.success('删除成功')
              } else {
                this.$message.error(`${res.msg} (${res.status})`)
              }
              this.loadTreeData()
            })
          } else {
            this.$message.error('取消删除')
          }
        }
      })
    },
    //  切换分页显示条数
    sizeChange(size) {
      this.searchForm.pageNo = 1
      this.searchForm.pageSize = size
      this.loadData()
    },
    //  翻页
    pageChange(page) {
      this.searchForm.pageNo = page
      this.loadData()
    },
    dialogClose() {
      this.visible = false
      this.visibleTree = false
    },
    dialogSubmit() {
      this.visible = false
      this.loadData()
    },
    dialogTreeSubmit() {
      this.visibleTree = false
      this.loadTreeData()
    }
  }
}
script>

<style scoped lang="scss">
el-table ::v-deep .el-table tr {
  background-color: yellow;
}
style>



chenw456 注册会员
2023-02-28 07:02
  • Take a look at this blog post, maybe you will understand. element el-table, type=expand row, expand-change= event get dynamic data, dom render refresh problem(do not display for the first time, Second display)
cuisite123 注册会员
2023-02-28 07:02

This answer quotes ChatGPT

Question 1: How do I load data asynchronously the first time I expand an item?

You can request data asynchronously in the expand-change event, then save the data into the child item, and set the data to be displayed when the child item expands in the expanded property.

Example:


<template>
  <el-table :data="tableData" @expand-change="handleExpandChange">
    <el-table-column prop="id" label="ID">el-table-column>
    <el-table-column prop="name" label="Name">el-table-column>
    <el-table-column type="expand">
      <template slot-scope="props">
        <div v-if="props.row.childrenLoading">Loading...div>
        <ul v-else>
          <li v-for="child in props.row.children" :key="child.id">{{ child.name }}li>
        ul>
      template>
    el-table-column>
  el-table>
template>

<script>
export default {
  data() {
    return {
      tableData: []
    }
  },
  methods: {
    handleExpandChange(row, expanded) {
      if (expanded && row.children == null) {
        row.childrenLoading = true;
        // 异步请求子项数据
        axios.get(`/api/children?id=${row.id}`)
          .then(response => {
            row.children = response.data;
            row.childrenLoading = false;
          })
          .catch(error => {
            row.childrenLoading = false;
            console.error(error);
          });
      }
    }
  }
}
script>


In the expand-change event, first determine whether to expand the item and then determine whether the child item already exists. If the child item does not exist, set the childrenLoading attribute to true, indicating that data is being loaded. Then asynchronously request data and save the data to the child item. Finally, set the childrenLoading property to false.

In the template, determine the state of the subitem by v-if and v-else. If you are Loading data, loading... Otherwise, the subitem data is displayed.

Question 2: How do I make parent and child items request different interfaces?

You can asynchronously request parent and child item data in the expand-change event, then save the data to the parent and child items, and finally display the parent and child item data respectively in the template.

Example:

<template>
  <el-table :data="tableData" @expand-change="handleExpandChange">
    <el-table-column prop="id" label="ID">el-table-column>
    <el-table-column prop="name" label="Name">el-table-column>
    <el-table-column type="expand">
      <template slot-scope="props">
        <div v-if="props.row.childrenLoading">Loading...div>
        <ul v-else>
          <li v-for="child in props.row.children" :key="child.id">{{ child.name }}li>
        ul>
      template>
    el-table-column>
  el-table>
template>

<script>
export default {
  data() {
    return {
      tableData: []
    }
  },
  methods: {
    handleExpandChange(row, expanded) {
      if (expanded && row.children == null) {
        row.childrenLoading = true;
        // 异步请求父项数据
        axios.get(`/api/parent?id=${row.id}`)
          .then(parentResponse => {
            row.parent = parentResponse.data;
            // 再次异步请求子项数据
            axios.get(`/api/children?dictTypeId=${row.parent.dictTypeId}`)
              .then(childrenResponse => {
                row.children = childrenResponse.data;
                row.childrenLoading = false;
              })
              .catch(error => {
                row.childrenLoading = false;
                console.error(error);
              });
          })
          .catch(error => {
            row.childrenLoading = false;
            console.error(error);
          });
      }
    }
  }
}
script>



In the then callback function of the parent data request, first store the parent data into the row.parent property, then asynchronously request the child data again with dictTypeId= row.parent-dicttypeid, This allows you to get the child item data that matches the parent item id. Finally, the child item data is saved in the row.children property. If the request fails, set the childrenLoading property to false and print an error log.