基于Vue3封装El-Table 组件

1,899 阅读2分钟

前言

大家看到这个标题可能觉得这个有啥可讲的呢?我觉得在日常开发中有必要对table进行封装,其实对于每个公司的UI风格来说,我们做一次封装还是很有必要的,可以让你尽快的完成项目,避免加班,当然,我相信这篇文章会对你封装组件有一定的启发,废话不多说,开始!

初始化Table组件

这里用到的Element-Plus组件库,我们首先初始化一个表格,这里没啥说的,直接CV过来就可以了,代码如下

<template>
  <el-table :data="tableData" style="width: 100%">
    <el-table-column prop="date" label="Date" width="180" />
    <el-table-column prop="name" label="Name" width="180" />
    <el-table-column prop="address" label="Address" />
  </el-table>
</template>

<script setup>
const tableData = [
  {
    date: '2016-05-03',
    name: 'Tom',
    address: 'No. 189, Grove St, Los Angeles',
  },
  {
    date: '2016-05-02',
    name: 'Tom',
    address: 'No. 189, Grove St, Los Angeles',
  },
  {
    date: '2016-05-04',
    name: 'Tom',
    address: 'No. 189, Grove St, Los Angeles',
  },
  {
    date: '2016-05-01',
    name: 'Tom',
    address: 'No. 189, Grove St, Los Angeles',
  },
]
</script>

定义数据配置表头

我们通过在调用这个组件的页面的传入配置数据从而达到我们想要的样式,组件中接收进行接收循环,就可以实现自定义表头的目的

  1. 调用table组件的页面
<template>
  <div>
    <MyTable :column = column></MyTable>
  </div>
</template>

<script setup>
import MyTable from '../components/table/index.vue'
import { reactive } from 'vue'

const column = [
  {label:'日期', prop:'date' },
  {label:'姓名', prop:'name' },
  {label:'地址', prop:'address'}
]
</script>
<style scoped>
</style>
  1. table组件
<template>
  <el-table :data="tableData" style="width: 100%">
    <el-table-column v-for="item in column" :key="item.prop" :prop="item.prop" :label="item.label"  />
  </el-table>
</template>

<script setup>
const props = defineProps({
  column:{
    type:Array,
    default:() => []
  }
})
const tableData = [
  {
    date: '2016-05-03',
    name: 'Tom',
    address: 'No. 189, Grove St, Los Angeles',
  },
  {
    date: '2016-05-02',
    name: 'Tom',
    address: 'No. 189, Grove St, Los Angeles',
  },
  {
    date: '2016-05-04',
    name: 'Tom',
    address: 'No. 189, Grove St, Los Angeles',
  },
  {
    date: '2016-05-01',
    name: 'Tom',
    address: 'No. 189, Grove St, Los Angeles',
  },
]
</script>

这样我们就实现了通过传入配置来自定义表头,这样雏形基本出来,接下来的代码只会展示修改的代码,最后会贴上完整代码供参考

复选框,索引等属性的配置

  1. 复选框 索引 <MyTable :column = column checkbox index></MyTable>
    table
<template>
  <el-table :data="tableData" style="width: 100%">
    <el-table-column v-if="index" type="index" width="50" />
    <el-table-column v-if="checkbox" type="selection" width="55" />
    <el-table-column v-for="item in column" :key="item.prop" :prop="item.prop" :label="item.label"  />
  </el-table>
</template>

const props = defineProps({
  column:{
    type:Array,
    default:() => []
  },
  // 加入复选框配置
  checkbox:Boolean,
  // 加入索引
  index:Boolean
  
})

表格中的一些配置,都可以以这样的方式进行配置,大家可以根据自己的需求进行配置,这里就不赘述了

自定义渲染文本

平常开发中表格不可能全都是文本,可能会有链接,按钮或者其他的东西,这个时候我们就可以给配置加上类型做出判断,如下,比如我们要渲染一个链接

渲染自定义的文本以及按钮

<template>
  <div>
    <MyTable :column = column>
      <template v-slot:operation>
        <el-button type="primary">编辑</el-button>
        <el-button type="primary">删除</el-button>
      </template>
    </MyTable>
  </div>
</template>

<script setup>
import MyTable from '../components/table/index.vue'
import { reactive } from 'vue'

const column = [
  { label:'日期', prop:'date' },
  { label:'姓名', prop:'name' },
  { type:'function',
    label:'地址', 
    prop:'address',
    callback:(data) => {
      return `<a href='#'>${data.address}</a>`
    }
  },
  {
    type:'solt',
    label:'操作',
    prop:'operation',
    slot_name:'operation'
  }
]
</script>
<style scoped>
</style>

table组件

<template>
  <el-table :data="tableData" style="width: 100%">
    <el-table-column v-if="index" type="index" width="50" />
    <el-table-column v-if="checkbox" type="selection" width="55" />
    <template v-for="item in column">
      <!-- 判断文本类 -->
      <el-table-column v-if="item.type == 'function'"  :prop="item.prop" :label="item.label" >
        <template  #default="scope">
          <div v-html="item.callback && item.callback(scope.row)"></div>
        </template>
      </el-table-column>
      <!-- 判断按钮类 -->
      <el-table-column v-else-if="item.type == 'solt'"  :prop="item.prop" :label="item.label" >
      <template #default="scope">
        <slot :name="item.slot_name"></slot>
       </template>
      </el-table-column>
      <el-table-column v-else :key="item.prop" :prop="item.prop" :label="item.label"  />
    </template>
  </el-table>
</template>

<script setup>
const props = defineProps({
  column:{
    type:Array,
    default:() => []
  },
  checkbox:Boolean,
  index:Boolean
})
const tableData = [
  {
    date: '2016-05-03',
    name: 'Tom',
    address: 'No. 189, Grove St, Los Angeles',
  },
  {
    date: '2016-05-02',
    name: 'Tom',
    address: 'No. 189, Grove St, Los Angeles',
  },
  {
    date: '2016-05-04',
    name: 'Tom',
    address: 'No. 189, Grove St, Los Angeles',
  },
  {
    date: '2016-05-01',
    name: 'Tom',
    address: 'No. 189, Grove St, Los Angeles',
  },
]
</script>

以上就是对渲染自定义内容的封装,主要是定义配置项,我们可以配置按钮,开关等,这些其实已经覆盖了常规开发需求
当我们完成上述封装后,比如当点击编辑按钮是需要传递数据到另一个页面,这个时候我们就需要再用到插槽完善我们的封装,我们可以在solt标签中加入属性,把数据传出去

<template #default="scope">
  <slot :name="item.slot_name" :data="scope.row"></slot>
</template>

这里加入自定义属性data,然后我们在调用的页面中接受这个数据,这样就可以在jump函数中做处理了

<MyTable :column = column>
  <template v-slot:operation="slot"> 
    <el-button type="primary" @click="jump(slot.data)">编辑</el-button>
    <el-button type="primary">删除</el-button>
  </template>
</MyTable>

数据回调

我们请求数据后应该将数据抛出,方便table组件外进行使用,先定义一个标记位(onLoad),因为并不是所有组件都需要这个回调数据

import { onMounted, defineEmits } from 'vue'
const emit = defineEmits(['onload'])

const props = defineProps({
  column:{
    type:Array,
    default:() => []
  },
  checkbox:Boolean,
  index:Boolean,
  onLoad:Boolean,
})
onMounted(() => {
  api()
})
const api = () => {
  // 请求数据成功后抛出
  onLoad && emit('onload','后台数据')
}
<MyTable :column = column on-load @onload='onload'></MyTable>

const onload = (data) => {
  console.log(data);
}

获取checkbox的数据

当我们点击选择框时,需要把选中的数据传出

<el-table :data="tableData" style="width: 100%" @selection-change="handleSelectionChange">
<el-table/>

const updateList = (data) => {
  checkList = data
}

table

<template>
  <div>
    <MyTable :column = column checkbox on-load @onload='onload' @updateList='updateList'>
      <template v-slot:operation="slot"> 
        <el-button type="primary" @click="jump(slot.data)">编辑</el-button>
        <el-button type="primary">删除</el-button>
      </template>
    </MyTable>
  </div>
</template>

<script setup>
import MyTable from '../components/table/index.vue'
import { reactive } from 'vue'
let checkList = []

const updateList = (data) => {
  checkList = data
}

</script>
<style scoped>
</style>

以上就是对table的封装,最会附上完整代码

<template>
  <div>
    <MyTable :column = column checkbox on-load @onload='onload' @updateList='updateList'>
      <template v-slot:operation="slot"> 
        <el-button type="primary" @click="jump(slot.data)">编辑</el-button>
        <el-button type="primary">删除</el-button>
      </template>
    </MyTable>
  </div>
</template>

<script setup>
import MyTable from '../components/table/index.vue'
import { reactive, watch } from 'vue'
let checkList = []
const onload = (data) => {
  console.log(data);
}
const jump = (data) => {
  console.log(data);
}
const updateList = (data) => {
  checkList = data
}
const column = [
  { label:'日期', prop:'date' },
  { label:'姓名', prop:'name' },
  { type:'function',
    label:'地址', 
    prop:'address',
    callback:(data) => {
      return `<a href='#'>${data.address}</a>`
    }
  },
  {
    type:'solt',
    label:'操作',
    prop:'operation',
    slot_name:'operation',
  }
]
</script>
<style scoped>
</style>

table

<template>
  <el-table :data="tableData" style="width: 100%" @selection-change="handleSelectionChange">
    <el-table-column v-if="index" type="index" width="50" />
    <el-table-column v-if="checkbox" type="selection" width="55" />
    <template v-for="item in column">
      <!-- 判断文本类 -->
      <el-table-column v-if="item.type == 'function'"  :prop="item.prop" :label="item.label" >
        <template  #default="scope">
          <div v-html="item.callback && item.callback(scope.row)"></div>
        </template>
      </el-table-column>
      <!-- 判断按钮类 -->
      <el-table-column v-else-if="item.type == 'solt'"  :prop="item.prop" :label="item.label" >
        <template #default="scope">
          <slot :name="item.slot_name" :data="scope.row"></slot>
        </template>
      </el-table-column>
      <el-table-column v-else :key="item.prop" :prop="item.prop" :label="item.label"  />
    </template>
  </el-table>
</template>

<script setup>
import { onMounted, defineEmits } from 'vue'
const emit = defineEmits(['onload','updateList'])

const props = defineProps({
  column:{
    type:Array,
    default:() => []
  },
  checkList:{
    type:Array,
    default:() => []
  },
  checkbox:Boolean,
  index:Boolean,
  onLoad:Boolean,
})
onMounted(() => {
  api()
})
const handleSelectionChange = (value) => {
  emit('updateList',value)
}
const api = () => {
  // 请求数据成功后抛出
  props.onLoad && emit('onload','后台数据')
}
const tableData = [
  {
    date: '2016-05-03',
    name: 'Tom',
    address: 'No. 189, Grove St, Los Angeles',
  },
  {
    date: '2016-05-02',
    name: 'Tom',
    address: 'No. 189, Grove St, Los Angeles',
  },
  {
    date: '2016-05-04',
    name: 'Tom',
    address: 'No. 189, Grove St, Los Angeles',
  },
  {
    date: '2016-05-01',
    name: 'Tom',
    address: 'No. 189, Grove St, Los Angeles',
  },
]
</script>

以上只是提供了一些封装的思路,可以在这上面继续封装,比如可以引入动态组件,让配置更加灵活,反正就自己开发吧!今天就说到了,希望对你有用

夫学须静也,才须学也,非学无以广才,非志无以成学。淫慢则不能励精,险躁则不能治性。年与时驰,意与日去,遂成枯落