vue3 elementPlus表格基础功封装

<template>
    <div class="my-table">

        <el-table v-bind="attrs" @row-dblclick="rowDblclick" :data="tableData" border>
            <slot name="checkbox">
                <el-table-column width="80px" v-if="showCheckbox">
                    <template #header>
                        <el-checkbox :indeterminate="checkboxMsg.isIndeterminate" v-model="checkboxMsg.checkAll"
                            @change="handleCheckAllChange">
                        </el-checkbox>
                    </template>
                    <template #default="scope">
                        <div class="inline-block" @click="clickCheckbox(scope.row)">
                            <el-checkbox :disabled="scope.row.disabled" v-model="scope.row.checked"
                                @change="handleCheckChange($event, scope.row)">
                            </el-checkbox>
                        </div>
                    </template>
                </el-table-column>
            </slot>
            <el-table-column type="index" label="序号" width="80" v-if="!hideIndex" />
            <el-table-column v-for="item in column" :key="item.prop" :show-overflow-tooltip="tooltip"  :prop="item.prop"
                :label="item.label" :width="item.width" v-bind="item.other" />
            <slot name="handle">
                <el-table-column v-if="!hideHandle" fixed="right" label="操作" :width="handleWidth">
                    <template #default="scope">
                        <my-btn v-if="!hideView" type="primary" size="small" @click="handleClick(scope, 'view')">查看</my-btn>
                        <my-btn v-if="!hideEdit" type="warning" size="small" @click="handleClick(scope, 'edit')">修改</my-btn>
                        <el-popconfirm v-if="!hideDel" title="确定要删除这个吗?" @confirm="handleClick(scope, 'del')">
                            <template #reference>
                                <my-btn type="danger" size="small">删除</my-btn> </template>
                        </el-popconfirm>
                    </template>
                </el-table-column>
            </slot>
        </el-table>
        <el-pagination v-if="!hidePagination" :current-page="pageNum" :page-size="pageSize" :page-sizes="pageSizes"
            layout="sizes, prev, pager, next" :total="total" @size-change="sizeChange" @current-change="currentChange" />
    </div>
</template>

<script setup >
const { proxy } = getCurrentInstance()
defineOptions({
    name: "MyTable",
    inheritAttrs: false,
})
const attrs = useAttrs();
console.log(attrs)
const prop = defineProps({
    column: {
        type: Array,
        default: () => {
            [
                {
                    prop: "",
                    width: "",
                    label: "",
                    other: {},
                },
            ];
        },
    },
    tableData: {
        type: Array,
        default: () => [],
    },
    tooltip:{
        type: Boolean,
        default: true,
    },
    hideHandle: {
        type: Boolean,
        default: false,
    },
    hideView: {
        type: Boolean,
        default: false,
    },
    hideEdit: {
        type: Boolean,
        default: false,
    },
    hideDel: {
        type: Boolean,
        default: false,
    },
    hidePagination: {
        type: Boolean,
        default: false,
    },
    hideIndex: {
        type: Boolean,
        default: false,
    },
    showCheckbox: {
        type: Boolean,
        default: false,
    },
    pageNum: {
        type: Number,
        default: 1,
    },
    pageSize: {
        type: Number,
        default: 1,
    },
    pageSizes: {
        type: Array,
        default: () => [10, 20, 50, 100],
    },
    total: {
        type: Number,
        default: 1,
    },
    max: {
        type: Number,
        default: 0,
    },
    key: {
        type: String,
        default: 'id'
    }
});

const {
    column,
    tableData,
    hideHandle,
    hideView,
    hideEdit,
    hideDel,
    pageNum,
    pageSize,
} = toRefs(prop);

let handleWidth = computed(() => {
    let width = 200;
    if (hideView.value) {
        width -= 60;
    }
    if (hideEdit.value) {
        width -= 60;
    }
    if (hideDel.value) {
        width -= 60;
    }
    return Math.max(80, width);
});

const emits = defineEmits([
    "handleEvent",
    "dblclic",
    "update:pageNum",
    "update:pageSize",
    "paginationChange"
]);

const handleClick = (value, type) => {
    emits("handleEvent", { value, type });
};
const rowDblclick = (row, column) => {
    emits("dblclic", { row, column });
}
const sizeChange = (value) => {
    emits("update:pageSize", value);
    emits("update:pageNum", 1);
    emits("paginationChange");

};
const currentChange = (value) => {
    emits("update:pageNum", value);
    emits("paginationChange");
};


// 多选部分
const checkboxMsg = reactive({
    isIndeterminate: false,
    checkAll: false,
    selectedList: []
})


const clickCheckbox = (item) => {
    // 处理不可选的被选中的情况
    let { disabled, checked } = item
    if (disabled && checked) {
        item.checked = false
        handleCheckChange(false, item)
    }
}
const handleCheckChange = (e, msg) => {
    if (e && prop.max && checkboxMsg.selectedList.length >= prop.max) {
        proxy.$message.warning(`最大可選為${prop.max}`);
        nextTick(() => {
            // // 同步赋值会导致e的值异常
            msg.checked = false
        })
        return
    }
    const key = prop.key
    let val = msg[key]
    if (e) {
        checkboxMsg.selectedList.push({
            ...msg
        })
    } else {
        let index = checkboxMsg.selectedList.findIndex(item => {
            return val === item[key]
        })
        if (~index) {
            checkboxMsg.selectedList.splice(index, 1)
        }
    }
    examineChecked()
}

const examineChecked = (init = false) => {
    let checkedLength = 0
    prop.tableData.forEach(item => {
        if (item.checked) {
            init && checkboxMsg.selectedList.push({
                ...item
            })
            checkedLength++
        }
    })
    if (checkedLength == prop.tableData.length) {
        checkboxMsg.checkAll = true
        checkboxMsg.isIndeterminate = false
    } else {
        checkboxMsg.checkAll = false
        if (checkedLength) {
            checkboxMsg.isIndeterminate = true
        } else {
            checkboxMsg.isIndeterminate = false
        }
    }
}

const handleCheckAllChange = (e) => {
    if (e && prop.max && checkboxMsg.selectedList.length >= prop.max) {
        proxy.$message.warning(`最大可選為${prop.max}`);
        checkboxMsg.checkAll = false
        return
    }
    prop.tableData.forEach(item => {
        if (!item.disabled && e != item.checked) {
            item.checked = e
            handleCheckChange(e, item)
        }
    })
}
defineExpose({
    getSelectedList() {
        return checkboxMsg.selectedList
    },
    examineChecked
})
</script>

<style scoped>
.my-table {
    width: fit-content;
    max-width: 100%;
}

.my-table :deep(td),
.my-table :deep(th) {
    text-align: center;
}

.my-table .el-table {
    margin-top: 10px;
    margin-bottom: 10px;
}

.my-table .el-pagination {
    justify-content: center;
}
</style>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值