ElemenPlus:Virtualized Table 虚拟化表格

概要

在我们的项目当中,无法避免会存在,列表显示数据量大的情况,如果在el-table中显示大量数据的话,就会导致浏览器卡死,所以可以使用本次提到的 el-table-v2虚拟化表格来解决数据量多的情况下列表卡顿的问题

一、安装elementPlus

npm i element-plus -s

二、el-table-v2的基本使用

elementPlus官网:跳转地址

1.官网示例

<template>
  <el-table-v2
    :columns="columns"
    :data="data"
    :width="700"
    :height="400"
    fixed
  />
</template>

<script lang="ts" setup>
const generateColumns = (length = 10, prefix = 'column-', props?: any) =>
  Array.from({ length }).map((_, columnIndex) => ({
    ...props,
    key: `${prefix}${columnIndex}`,
    dataKey: `${prefix}${columnIndex}`,
    title: `Column ${columnIndex}`,
    width: 150,
  }))

const generateData = (
  columns: ReturnType<typeof generateColumns>,
  length = 200,
  prefix = 'row-'
) =>
  Array.from({ length }).map((_, rowIndex) => {
    return columns.reduce(
      (rowData, column, columnIndex) => {
        rowData[column.dataKey] = `Row ${rowIndex} - Col ${columnIndex}`
        return rowData
      },
      {
        id: `${prefix}${rowIndex}`,
        parentId: null,
      }
    )
  })

const columns = generateColumns(10)
const data = generateData(columns, 1000)
</script>

三、二次封装

子组件 :Virtualized_Table文件目录下的index.vue文件
<template>
  <div class="tableV2 TableBox"    >
    <el-auto-resizer> 
      <template #default="{ height, width }"> 
         <el-checkbox v-if="false" @change="handelAllShow" v-model="checked2">展开全部</el-checkbox>
            <el-table-v2
              :columns="columns"
              v-loading="Tablloading"
              :data="Tabledata||[]"
              :default-expanded-row-keys="expandedRowKeys"
              :expanded-row-keys="expandedRowKeys"
              :estimated-row-height="50"
              :expand-column-key="columns[0].key"
              fixed
              :width="width"
              :height="
              Comprops.PropVirtTableS.TableHeigth ||
              400"
            >
              <template #row="props">
                <Row v-bind="props" />
              </template>
            </el-table-v2>
      </template>
    </el-auto-resizer>
    </div>
    
</template>

<script lang="tsx" setup>
import PublicAPI from "@/axios/public";
import {ref,reactive,defineProps,getCurrentInstance,watch} from 'vue'
//接收父组件传递过来的数据
const Comprops = defineProps(['PropVirtTableS'])
const proxy = getCurrentInstance()
//定义接收父组件传递过来的数据中 表头显示的对象
const TableHeaderTitle = reactive(Comprops.PropVirtTableS.keyS)
//定义接收父组件传递过来的数据中 列表显示的数据
const TableData = reactive(Comprops.PropVirtTableS.tables)
//展开全部
let checked2 =  ref(false) 
//存放展开全部的对象id
let expandedRowKeys = reactive([])


//处理接收到的表头的显示数据 并且根据父组件传递过来的数据,针对传递的类型,来判断是否显示其他的组件,比如下拉,输入框等等,此处只是简单的判断了,如果显示输入框,那么这一列都会是输入框,如果需要个别的显示,那么还需要加上其他条件。
function generateColumns(data:object){
  let propsData = []
      for (const key in data) {
        let list = {}
            list = {
              key:key,
              dataKey: data[key].children ?  '' : key,
              title: data[key].title,
              //width: data[key].width ? data[key].width : 'auto',  这种表头如果多了,超出不显示,列表不会出现横向滚动条
              width:150,//这种超出会出现滚动条
            }
            if(key === 'operate'){
                list.cellRenderer = ({ cellData, rowData }) => {
                  // 假设 key 是在外部定义且可访问的
                    return data[key].children.map(item => { 
                      let linkElement 
                      if (item.type === 'delete') {
                        linkElement = <el-link onClick={() => {handelRowDelete(item,rowData)}} type="danger">删除</el-link>
                      }else if (item.type === 'edit') {
                        linkElement = <el-link type="primary">编辑</el-link>
                      }
                      return  linkElement
                    })
                }
            }else if(data[key].type ) {
              list.cellRenderer = ({ cellData, rowData }) => {  
                    let linkElement 
                        //显示输入框
                    if (data[key].type === 'input') {
                      linkElement = <ElInput  modelValue={rowData[key]} onUpdate:modelValue = {(e)=>{rowData[key] = e} }  value={rowData[key]}  placeholder="Please input" />
                    }
                       //显示下拉
                    else if (data[key].type === 'select') {
                       linkElement = (
                           <ElSelectV2 multiple={true} options={data[key].children} disabled={ 1 === '1' }  modelValue={rowData[key]} onUpdate:modelValue = {(e)=>{rowData[key] = e} }></ElSelectV2>
                         )
                     }
                        //显示计数器
                    else if (data[key].type === 'inputnumber') {
                      linkElement = (
                          <ElInputNumber  controls-position="right"   modelValue={rowData[key]} onUpdate:modelValue = {(e)=>{rowData[key] = e} }/>
                        )
                    }
                    return  linkElement
                }
            }
            propsData.push(list)
      }
    return propsData
}

//处理列表显示的数据
const generateData = (
  columns: ReturnType<typeof generateColumns>,
  length = TableData.length,
) =>
  Array.from({ length }).map((_, rowIndex) => {
    return columns.reduce(
      (rowData, column, columnIndex) => {
        if(column.dataKey){
            //判断是否包含children :如果包含列表就会显示折叠展开嵌套数据
          if(TableData[rowIndex].children){
            rowData[column.dataKey].children = TableData[rowIndex].children
          }else {
            rowData[column.dataKey] = TableData[rowIndex][column.dataKey]
          }
        }
        return rowData
      },
      {
        id: rowIndex,
      }
    )
  })

//列表的表头显示数据
const columns = generateColumns(TableHeaderTitle)

//列表显示的数据
let data =  reactive(
//自定义添加children测试能否显示附加列表
generateData(columns, TableData.length).map((data) => {
    data.children = [
      {
        id: `${data.id}-detail-content`,
        detail: 11111,
      },
    ]
    return data
  })

//嵌套的tab表头
const columnsRowChildren = reactive(generateColumns({
  application_module: {
      title: "物流供应商编号",
      width:'200px'
    },
    business_code: {
      title: "计费规则名称",
      type:'input',
      width:'200px'
    },
    operation_node: {
      title: "计费仓库",
      width:'200px'
    },
    operator_id: {
      title: "物流供应商",
      width:'200px'
    },
    operator_name: {
      title: "物流公司",
      width:'200px'
    },
    es_id: {
      title: "状态",
      width:'200px'
    },
    operate:
      {
        title:'操作',
        width:'400px',
        children: [
          {
            title: "编辑",
            isshow: `buts.includes('system-users-role')`,
            type: "edit",
          },
          {
            title: "删除",
            isshow: `buts.includes('system-users-delete')`,
            type: "delete",
          },
        ]
      }
}))


//嵌套的tab数据 后期可以根据后端返回的数据来替换
const dataChildren = reactive([
    {
      application_module:'Acc200',
      business_code:'御寒羽绒服1',
      type:'上衣',
      operation_node:'0.3456',
      operator_id:'0.3456',
      operator_name:'M-黑色',
      es_id:'1',
    },
    {
      application_module:'Acc200',
      business_code:'御寒羽绒服1',
      type:'上衣',
      operation_node:'0.3456',
      operator_id:'0.3456',
      operator_name:'M-黑色',
      es_id:'1',
    },
    {
      application_module:'Acc200',
      business_code:'御寒羽绒服1',
      type:'上衣',
      operation_node:'0.3456',
      operator_id:'0.3456',
      operator_name:'M-黑色',
      es_id:'1',
    },
])


//展开全部
function handelAllShow(value:boolean){
    if(value) expandedRowKeys = data.map(item => item.id)
    else expandedRowKeys = []
}

//判断返回渲染
const Row = ({ cells, rowData }) => {
    //如果rowDate.detail存在就会显示嵌套的列表
  if (rowData.detail) return  <el-table-v2 class="nestElTableV2" data={dataChildren} columns={columnsRowChildren}  width={900} height={200}></el-table-v2>
  return cells
}

Row.inheritAttrs = false

//更新数据 页面列表数据不会刷新问题
watch(
  () => Comprops.PropVirtTableS.tables,
  (newValue) => {
    data.splice(0, data.length);
    data.push(...generateData(columns, newValue.length));
  }
 )


</script>

<style>
.el-table-v2__row-depth-0 {
  height: 50px;
}

.el-table-v2__cell-text {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* 展开的 子列表 */
.el-table-v2__row-depth-1{
  width: 100%;
  display: flex;
  justify-content: center;
}

</style>

2:导出组件

//src -> components -> public ->  Virtualized_Table -> index.vue  文件路径


import  VirtualizedTable  from "@/components/public/Virtualized_Table/index.vue"; 

export  {
  VirtualizedTable,
}

3.父组件传递的数据对象结构

父组件引用子组件
<template>
    <VirtualizedTable v-if="PropVirtTableS.tables"  :PropVirtTableS="PropVirtTableS" ></VirtualizedTable>
</template>

<script lang="ts" setup>
import {reactive} from 'vue'
import {VirtualizedTable} from "@/components";

//定义数据结构
 let PropVirtTableS = reactive({
  //自己定义的列表头显示数据 注意:application_module KEY值需要跟显示数据的KEY对应,否则此列数据显示不出来.
  keyS: proxy.$PublicAPI.SetTableCotentWidth({
    application_module: {
      title: "物流供应商编号",
      width:'200px'
    },
    business_code: {
      title: "计费规则名称",
      width:'200px'
    },
    operation_node: {
      title: "计费仓库",
      width:'200px'
    },
    operator_id: {
      title: "物流供应商",
      width:'200px'
    },
    operator_name: {
      title: "物流公司",
      width:'200px'
    },
    es_id: {
      title: "状态",
      width:'200px'
    },
    operate:
      {
        title:'操作',
        width:'400px',
        children: [
          {
            title: "编辑",
            isshow: `buts.includes('system-users-role')`,
            type: "edit",
          },
          {
            title: "删除",
            isshow: `buts.includes('system-users-delete')`,
            type: "delete",
          },
        ]
      }
    
  })
});


请求后端数据,将数据传递给组件
function GetTabList(params: object) {
  // 调用列表数据
    logapi.GetLogList(params).then((res) => {
        PropVirtTableS.tables = res.data.list;
      })
}








 </script>

效果图:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值