vue基于el-table自定义table组件

本文档介绍了一个自定义的Table组件,该组件支持数据绑定、列的自定义展示、编辑功能以及操作列。组件提供了获取表格实例、当前页面数据、加载数据等方法,便于在父组件中调用。示例展示了如何在父组件中使用该组件,并通过事件监听处理行点击事件。

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

自定义table组件

  <template>
    <div>
      <el-table ref="_myTb" :data="tableData" style="width: 100%">
        <template v-for="(item, index) in fieldList">
          <el-table-column v-if="typeInference(item)" v-bind="item" :key="columnKey(item, index)">
            <template slot="header" slot-scope="scope">
              <slot :name="slotName(item, 'headerScope')" :scope="scope">
                <template v-if="item.editable">
                  {{ scope.column.label }}
                  <i class="el-icon-edit-outline"></i>
                </template>
                <template v-else-if="openRtSet && item.operable">
                  {{ scope.column.label }}
                </template>
                <template v-else>{{ scope.column.label }}</template>
              </slot>
            </template>
            <template slot-scope="scope">
              <template v-if="item.editable">
                <div v-if="editor(scope.row, scope.column, scope.$index)">
                  <slot :name="slotName(item)" :scope="{
                    row: scope.row,
                    column: scope.column,
                    $index: scope.$index
                  }">
                    <el-input v-model.trim="scope.row[item.prop]"></el-input>
                  </slot>
                </div>
                <div v-else>
                  <i v-if="editorChangeIcon(scope.row, scope.column.property)"
                    class="el-icon-caret-left editorIcon"></i>
                  <template v-if="typeof item.formatter === 'function'">
                    <div v-html="
                      item.formatter(
                        scope.row,
                        scope.column,
                        scope.cellValue,
                        scope.index
                      )
                    "></div>
                  </template>
                  <template v-else>{{ scope.row[item.prop] }}</template>
                </div>
              </template>
              <template v-else-if="item.scope">
                <slot :name="slotName(item, 'scope')" :scope="scope"></slot>
              </template>
              <template v-else-if="item.render">
                <ex-slot :render="item.render" :params="scope" />
              </template>
            </template>
          </el-table-column>
          <el-table-column v-else-if="typeInference(item, 'normal')" v-bind="item" :key="index">
            <template slot="header" slot-scope="scope">
              <slot :name="slotName(item, 'headerScope')" :scope="scope">
                <template v-if="openRtSet && item.operable">
                  {{ scope.column.label }}
                </template>
                <template v-else>{{ scope.column.label }}</template>
              </slot>
            </template>
          </el-table-column>
        </template>
      </el-table>
    </div>
  </template>

  <script>
    export default {
      props: {
        tableInfo: {
          type: Object,
          default () {
            return {}
          }
        }
      },
      data() {
        return {
          openRtSet: false,
          fieldList: [],
          tableData: [],
        }
      },
      computed: {
        columnKey() {
          return function (item, index) {
            if (item.prop) return item.prop
            return item.type ? item.type : index
          }
        },
        typeInference() {
          return function (item, type) {
            if (item.hidden) return false
            return type ? true : item.editable || item.scope || item.render
          }
        },
        slotName() {
          return function (item, type) {
            // 默认使用 prop 作为 slot name,特殊情况没有 prop 时,使用具体类型的值
            const name = item.prop ? item.prop : item[type]
            return type === "headerScope" ? `${name}Header` : name
          }
        },
      },
      created() {
        let tableInfo = this.tableInfo
        // 只显示show为true的列
        const list = [...tableInfo.fieldList]
        this.fieldList = list.filter(item => {
          // boss要求所有页面操作列宽度默认 200
          if (item.type === "action") {
            item.width = item.actWidth ? item.actWidth : 200
          }
          if (typeof item.show === "boolean") return item.show
          return true
        })
      },
      methods: {
        // 获取当前表格实例,用于调用表格提供的方法
        getTbInstance() {
          return this.$refs._myTb
        },
        // 获取当前表格数据
        getCurPageData() {
          return [...this.tableData]
        },
        // 直接绑定表格数据数据方法
        loadData(data) {
          this.tableData = data
        },
      }
    }
  </script>

测试自定义table组件

<template>
  <div>
    <my-table ref="tableInfo" :tableInfo="tableInfo" @row-click="handleSelect"></my-table>
    <button @click="getList">取消</button>
  </div>
</template>
<script>
  import MyTable from "@/components/custom/MyTable";
  export default {
    name: "TableTest",
    components: {
      MyTable
    },
    data() {
      return {
        tableInfo: this.getTableInfo(),
        tableData: [{
          date: '2016-05-02',
          name: '王小虎',
          address: '上海市普陀区金沙江路 1518 弄'
        }, {
          date: '2016-05-04',
          name: '王小虎',
          address: '上海市普陀区金沙江路 1517 弄'
        }, {
          date: '2016-05-01',
          name: '王小虎',
          address: '上海市普陀区金沙江路 1519 弄'
        }, {
          date: '2016-05-03',
          name: '王小虎',
          address: '上海市普陀区金沙江路 1516 弄'
        }]
      }
    },
    mounted() {
      this.getList()
    },
    methods: {
      // 设置tableInfo
      getTableInfo() {
        return {
          fieldList: [
            { prop: 'date', label: '日期', align: 'center', width: 120 },
            { prop: 'name', label: '姓名', align: 'center', width: 120 },
            { prop: 'address', label: '地址', align: 'center', width: 160 },
          ],
        }
      },
      getList() {
        this.$refs.tableInfo.loadData(this.tableData)
      },
      handleSelect(row) {
        this.$refs.tableInfo.getTbInstance().toggleRowSelection(row)
      },
    }
  };
</script>

父组件调用子组件方法this.$refs.tableInfo.methodXXX()

父组件获取子组件原生对象实例this.$refs.tableInfo.getTbInstance(),拿到原生对象后可以调用子组件原生对象的方法

### vue-element el-table 组件中实现自定义表尾 为了在 `el-table` 中实现自定义表尾,可以利用 `el-table-footer` 插槽来定制表格底部的内容。通过这种方式能够灵活地向表格添加总计行、统计信息或其他任何需要展示的数据。 下面是一个简单的例子,展示了如何创建带有自定义脚部的表格: ```html <template> <div class="table-container"> <!-- 定义表格 --> <el-table :data="tableData" style="width: 100%"> <el-table-column prop="date" label="日期"></el-table-column> <el-table-column prop="name" label="姓名"></el-table-column> <el-table-column prop="address" label="地址"></el-table-column> <!-- 使用 slot-scope 获取作用域插槽数据 --> <slot name="footer" :scope="props"> <el-table-footer v-if="$scopedSlots.footer"> <tr> <td colspan="3">这里是自定义的表尾</td> </tr> </el-table-footer> </slot> <!-- 或者直接使用具名插槽方式 --> <template #footer> <span>这是另一种形式的自定义表尾</span> </template> </el-table> </div> </template> <script setup lang="ts"> import { ref } from 'vue'; const tableData = ref([ { date: '2016-05-03', name: 'Tom', address: 'No. 189, Grove St, Los Angeles' }, // 更多条目... ]); </script> ``` 上述代码片段中的 `<el-table>` 标签包含了两个不同的方法来自定义表尾部分:一个是通过作用域插槽(即 `v-slot`),另一个则是更简洁的方式——直接使用具名插槽 (`#footer`) 来插入 HTML 片段作为表尾内容[^2]。 对于更加复杂的场景,比如计算并显示某些字段的总和或平均值,则可以在 JavaScript 部分处理逻辑运算,并将结果显示于模板内的相应位置。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值