element-ui简单table封装
面对element-ui table 有好多可以复用,首先来学习下简单封装复用table写法,实现高效小前端,减少一下代码复用,提高效率完成table数据渲染复用;文章后面涉及到VUE3+element-plus写法
效果图大致(主题颜色是本人项目的修改过后)
1、首先创建一个table封装的组件
<template>
<!--
@param tableData 父组件传值
@param loading [Boolean] 加载提示
@param border [Boolean] table边框
-->
<el-table
ref="table"
:data="tableData"
v-loading="loading"
element-loading-text="Loading"
:border="border"
fit highlight-current-row
tooltip-effect="dark"
style="width:100%"
@sort-change="handleSortChange"
@selection-change="handleSelectionChange">
<!--
@name 展开查看详情
@param tableLabel 父组件传值
@param label [string] 名称
@param render 配置格式化数据
-->
<el-table-column type="expand">
<template slot-scope="scope">
<el-form
class="table-expand"
>
<el-form-item
v-for="(item,index) in tableLabel"
:key="index"
:label="item.label">
<span v-if="item.render">
{{item.render(scope.row)}}
</span>
<span v-else>{{scope.row[item.param]}}</span>
</el-form-item>
</el-form>
</template>
</el-table-column>
<!--
@name 操作
@param tableOption 父组件传值
@param label [string] 名称
@param width [string] 宽度
@param options [array] 按钮数组
@param type 按钮类型
@param icon 按钮图标
@param handleButton 按钮方法
-->
<el-table-column
v-if="tableOption.label"
:width="tableOption.width"
:label="tableOption.label"
align="center"
class-name="small-padding fixed-width">
<template slot-scope="scope">
<el-button
v-for="(item,index) in tableOption.options"
:key="index"
:type="item.type"
:icon="item.icon"
@click="handleButton(item.methods,scope.row,scope.$index)"
size="mini">
{{item.label}}
</el-button>
</template>
</el-table-column>
<!--
@name 标题+表格数据显示
@param tableLabel 父组件传值
@param width 【string】宽度
@param align 【string】对齐方式
@param label [string] 名称
@param sortable [Boolean] 排序
@param render 配置格式化数据
-->
<div
v-for="(item,index) in tableLabel"
:key="index">
<el-table-column
v-if="item.show"
:width="item.width ? item.width : ''"
:align="item.align"
:label="item.label"
:prop="item.param"
:sortable="item.sortable ? 'custom' : false">
<template slot-scope="scope">
<span v-if="item.render">
{{item.render(scope.row)}}
</span>
<span v-else>{{scope.row[item.param]}}</span>
</template>
</el-table-column>
</div>
</el-table>
</template>
<script>
/**
* @name 表格封装
* @export TableElement
* @param loading [Boolean] 配置加载提示
* @param tableData [Array] 数据
* @param tableMain [Array] 数据详情
* @param tableLabel [Array] 配置表格头部
* @param tableOption [Object] 操作按钮
* @param border [Boolean] 配置边框
*/
export default {
props:{
loading:{
type:Boolean,
default:false
},
tableData:{
type:Array,
default: () => {
return []
}
},
tableMain:{
type:Array,
default: () => {
return []
}
},
tableLabel:{
type:Array,
default: () => {
return []
}
},
tableOption:{
type:Object,
default: () => {
return {}
}
},
border:{
type:Boolean,
default: false
}
},
components:{},
methods: {
// methods:按钮名称 row:同一行的数据 index:第几行(0开始)
handleButton(methods,row,index){ // 按钮事件
console.log(row)
this.$emit('handleButton',{'methods':methods,'row':row})
},
handleSortChange(val){ // 排序
this.$emit('handleSortChange',val)
},
handleSelectionChange(val){
this.$emit('handleSelectionChange',val)
}
}
}
</script>
<style lang="scss" scoped>
.table-expand {
font-size: 0;
display: flex;
flex-wrap: wrap;
}
.table-expand label {
width: 90px;
color: #99a9bf;
}
.table-expand .el-form-item {
margin-right: 0;
margin-bottom: 0;
width: 50%;
}
</style>
2、table 组件导入使用
<template>
<div>
<TableElement
:loading="loading"
:table-data="tableData"
:table-label="tableLabel"
:table-option="tableOption"
@handleButton="handleButton"
@handleSortChange="handleSortChange"
@handleSelectionChange="handleSelectionChange"
></TableElement>
</div>
</template>
<script>
import TableElement from "@/components/Table/index"; // 导入table组件,具体路径以自己为主
export default {
data() {
return {
loading:false,
border:true,
tableData: [
{
usr:'yy',
company:'hahahha',
email:'find@allyum.com',
registTime:'2019 8',
status:'1'
},
{
usr:'aa',
company:'hahahha',
email:'find@allyum.com',
registTime:'2019 8',
status:'1'
},{
usr:'c',
company:'hahahha',
email:'find@allyum.com',
registTime:'2019 8',
status:'1'
},{
usr:'b',
company:'hahahha',
email:'find@allyum.com',
registTime:'2019 8',
status:'1'
}
],
tableLabel: [
{ label: "用户名", param: "usr", align: "center", sortable: true,show:true },
{ label: "公司名称", param: "company", align: "center",show:false },
{ label: "办公邮箱", param: "email", align: "center", width: "200",show:true },
{ label: "注册时间",param: "registTime",lign: "center",show:true,ortable: true},
{ label: "审核状态",param: "status",align: "center",show:true,sortable: true,
render: row => {
if (row.status === 0) {
return "未审核";
} else if (row.status === 1) {
return "审核通过";
} else if (row.status === 2) {
return "审核不通过";
} else {
return "禁用";
}
}
}
],
tableOption: {
label: "操作",
width: "200",
options: [
{
label: "预览",
type: "primary",
icon: "el-icon-view",
methods: "preview"
},
{
label: "审核",
type: "primary",
icon: "el-icon-upload2",
methods: "audit"
}
]
}
};
},
methods:{
handleButton(data) {
switch(data.methods) {
case 'preview':
this.preview()
break;
case 'audit':
console.log('audit')
break;
}
},
preview() {
console.log('preview');
},
// 排序规则
handleSortChange() {
console.log('排序规则')
},
handleSelectionChange() {}
},
components: {
TableElement
}
};
</script>
<style lang="scss" scoped>
</style>
A、扩展“vue3 + element-plus”,table组件封装
<template>
<div>
<!--
@param tableData 父组件传值
@param loading [Boolean] 加载提示
@param border [Boolean] table边框
-->
<el-table
ref="table"
:data="tableData"
v-loading="loading"
element-loading-text="Loading"
:border="border"
fit
highlight-current-row
tooltip-effect="dark"
style="width: 100%"
@sort-change="handleSortChange"
@selection-change="handleSelectionChange"
>
<!--
@name 展开查看详情
@param tableLabel 父组件传值
@param label [string] 名称
@param render 配置格式化数据
-->
<el-table-column type="expand">
<template #default="props">
<el-form class="table-expand">
<el-form-item
v-for="(item, index) in tableLabel"
:key="index"
:label="item.label"
>
<span v-if="item.render">
{{ item.render(props.row) }}
</span>
<span v-else>{{ props.row[item.param] }}</span>
</el-form-item>
</el-form>
</template>
</el-table-column>
<!--
@name 操作
@param tableOption 父组件传值
@param label [string] 名称
@param width [string] 宽度
@param options [array] 按钮数组
@param type 按钮类型
@param icon 按钮图标
@param handleButton 按钮方法
-->
<el-table-column
v-if="tableOption.label"
:width="tableOption.width"
:label="tableOption.label"
align="center"
class-name="small-padding fixed-width"
>
<template #default="props">
<el-button
v-for="(item, index) in tableOption.options"
:key="index"
:type="item.type"
:icon="item.icon"
@click="handleButton(item.methods, props.row, props.$index)"
size="mini"
>
{{ item.label }}
</el-button>
</template>
</el-table-column>
<!--
@name 标题+表格数据显示
@param tableLabel 父组件传值
@param width 【string】宽度
@param align 【string】对齐方式
@param label [string] 名称
@param sortable [Boolean] 排序
@param render 配置格式化数据
-->
<div v-for="(item, index) in tableLabel" :key="index">
<el-table-column
v-if="item.show"
:width="item.width ? item.width : ''"
:align="item.align"
:label="item.label"
:prop="item.param"
:sortable="item.sortable ? 'custom' : false"
>
<template #default="props">
<span v-if="item.render">
{{ item.render(props.row) }}
</span>
<span v-else>{{ props.row[item.param] }}</span>
</template>
</el-table-column>
</div>
</el-table>
</div>
</template>
<script lang="ts">
/**
* @name 表格封装
* @export TableElement
* @param loading [Boolean] 配置加载提示
* @param tableData [Array] 数据
* @param tableMain [Array] 数据详情
* @param tableLabel [Array] 配置表格头部
* @param tableOption [Object] 操作按钮
* @param border [Boolean] 配置边框
*/
export default {
props: {
loading: {
type: Boolean,
default: false,
},
tableData: {
type: Array,
default: () => {
return [];
},
},
tableMain: {
type: Array,
default: () => {
return [];
},
},
tableLabel: {
type: Array,
default: () => {
return [];
},
},
tableOption: {
type: Object,
default: () => {
return {};
},
},
border: {
type: Boolean,
default: false,
},
},
setup(props: any, { emit }: { emit: any }) {
// // methods:按钮名称 row:同一行的数据 index:第几行(0开始)
const handleButton = (methods: string, row: any, index: number) => {
emit("handleButton", { methods: methods, row: row });
};
const handleSortChange = (val: any) => {
// 排序
emit("handleSortChange", val);
};
const handleSelectionChange = (val: any) => {
emit("handleSelectionChange", val);
};
return {
handleButton,
handleSortChange,
handleSelectionChange,
};
},
};
</script>
<style lang="scss" scoped>
.table-expand {
font-size: 0;
display: flex;
flex-wrap: wrap;
}
.table-expand label {
width: 90px;
color: #99a9bf;
}
.table-expand .el-form-item {
margin-right: 0;
margin-bottom: 0;
width: 50%;
}
</style>
B、vue3 组件导入使用
<template lang="">
<div>
{{loading}}
<ELTable
:loading="loading"
:table-data="tableData"
:table-label="tableLabel"
:table-option="tableOption"
></ELTable>
</div>
</template>
<script lang="ts">
/**
* @name 管理用户
* */
import {
defineComponent,
reactive,
ref
} from 'vue'
import ELTable from '@/components/table/table.vue'
interface costomerData {
tableData: any;
loading: boolean;
tableLabel: any;
tableOption: object;
handleButton: (data: any) => void;
handleSortChange: () => void;
handleSelectionChange: () => void;
}
export default defineComponent({
components: {
ELTable
},
setup(): costomerData {
const tableData = reactive([{
usr: 'yy',
company: 'hahahha',
email: 'find@allyum.com',
registTime: '2019 8',
status: '1'
},
{
usr: 'aa',
company: 'hahahha',
email: 'find@allyum.com',
registTime: '2019 8',
status: '1'
}, {
usr: 'c',
company: 'hahahha',
email: 'find@allyum.com',
registTime: '2019 8',
status: '1'
}, {
usr: 'b',
company: 'hahahha',
email: 'find@allyum.com',
registTime: '2019 8',
status: '1'
}
])
const tableLabel = reactive([
{ label: "用户名", param: "usr", align: "center", sortable: true,show:true },
{ label: "公司名称", param: "company", align: "center",show:false },
{ label: "办公邮箱", param: "email", align: "center", width: "200",show:true },
{ label: "注册时间",param: "registTime",lign: "center",show:true,ortable: true},
{ label: "审核状态",param: "status",align: "center",show:true,sortable: true,
render: (row:any) => {
if (row.status === 0) {
return "未审核";
} else if (row.status === 1) {
return "审核通过";
} else if (row.status === 2) {
return "审核不通过";
} else {
return "禁用";
}
}
}
])
const loading = ref<boolean>(false);
const tableOption = reactive({
label: "操作",
width: "200",
options: [
{
label: "预览",
type: "primary",
icon: "el-icon-view",
methods: "preview"
},
{
label: "审核",
type: "primary",
icon: "el-icon-upload2",
methods: "audit"
}
]
})
const handleButton = (data: any) => {
switch (data.methods) {
case "preview":
preview(data.row);
break;
case "audit":
console.log("audit");
break;
}
};
const preview = (row: any) => {
console.log(row); // 获取到编辑的一行数据
};
// 排序规则
const handleSortChange = () => {
console.log("排序规则");
};
const handleSelectionChange = () => {};
return {
tableData,
tableLabel,
tableOption,
loading,
handleButton,
handleSortChange,
handleSelectionChange,
}
}
})
</script>
效果图大致(主题颜色是本人项目的修改过后)
总结
- 简单的学习封装,如果有更好建议可以在下面留言
- 上面的有写规则例如排序的还没完善,后面更新一些规则进去
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。