vue 封装Table组件

基于element-plus UI 框架封装一个table组件

在项目目录下的components新建一个Table.vue

javascript 复制代码
<template>
    <section class="wrap">
        <el-table
            ref="table"
            :data="tableData" 
            v-loading="loading" 
            style="width: 100%"
            :stripe="stripe"
            :border="border"
            :row-key="(row) => { return row.id }"
            @selection-change="handleSelectionChange"
            :height="tableHeight"
            >
            // 复选框列 type="selection"
            <el-table-column
                v-if="selection"
                type="selection"
                width="56"
                align="center"
                :fixed="fixed"
            >
            </el-table-column>
            // 序号列 type="index"
            <el-table-column
                v-if="index"
                type="index"
                width="56"
                label="序号"
                :fixed="fixed"
            ></el-table-column>
            <template v-for="(item, index) in tableProps" :key="index">
                <el-table-column 
                    :prop="item.prop" 
                    :label="item.label" 
                    :width="item.width" 
                    :type="item.type"
                    :show-overflow-tooltip="item.showOverflowTooltip" 
                    :align="item.align"
                    :fixed="item.fixed"
                    :sortable="item.sort"
                    :formatter="item.formatter"
                   >
                   <template v-if="item.prop === 'operation'" #default="scope">
                        <el-button size="small" type="success" @click="handleEdit(scope.row)">编辑</el-button>
                        <el-button size="small" type="danger" @click="handleDelete(scope.$index, scope.row)">删除</el-button>
                        <el-button size="small" type="warning" @click="handleAdd(scope.$index, scope.row)">新增</el-button>
                   </template>
                </el-table-column>
            </template>
        </el-table>
    </section>
</template>

<script setup>
import { ref, watch } from 'vue'

const tableData = ref([])
const loading = ref(true)

// 监听父组件传递过来的数据
watch(() => props.data, (val) => {
    tableData.value = val
    loading.value = false
})

// 声明要触发的emits
const emits = defineEmits(['selectionChange','deleteItem', 'editItem', 'addItem'])

// 父组件传递过来的props
const props = defineProps({
    data: {
        type: Array,
        default: () => [],
    },
    tableProps: {
        type: Array,
    },
    tableHeight: {
        type: String,
        default: '500'
    },
    selection: Boolean,
    index: Boolean,
    border: Boolean,
    stripe: Boolean,
})

// 定义表格的列属性
const tableProps = ref([
    {
        type: 'selection',
        label: '',
        width: '55',
        align: 'center'
    },
    {
        type: 'index',
        label: 'No.',
        width: '55',
        align: 'center'
    },
    {
        prop: 'name',
        label: '姓名',
        width: '',
        showOverflowTooltip: true,
        align: 'center'
    },
    {
        prop: 'username',
        label: '用户名',
        width: 120,
        showOverflowTooltip: true,
        align: 'center'
    },
    {
        prop: 'email',
        label: '邮箱',
        width: '',
        showOverflowTooltip: true,
        align: 'center'
    },
    {
        prop: 'phone',
        label: '联系电话',
        width: '',
        showOverflowTooltip: true,
        align: 'center',
        // 单元格格式化函数,参考element-plus formatter
        formatter: (row) => {
          return `+86 ${ row.phone }`;
        },
    },
    {
        prop: 'website',
        label: '网址',
        width: '',
        showOverflowTooltip: true,
        align: 'center',
    },
    {
        prop: 'operation',
        label: '操作',
        align: 'center',
        formatter: (row,column) => {}
    }
])

const handleAdd = (row) => {
    emits('addItem', row)
}

const handleEdit = (rowData) => {
    emits('editItem', rowData)
}

const handleDelete = (index, rowData) => {
    emits('deleteItem', index)
}

const handleSelectionChange = (row) => {
    console.log('row data are: ', row[0].name)
}

</script>

在具体的父组件中使用:

javascript 复制代码
<template>
    <section class="container">
        <section class="table-wrap">
            <Table 
                :data="tableData" 
                ref="table" 
                border
                stripe 
                @selectionChange="handleSelectionChange" 
                @editItem="handleEdit"
                @addItem="handleAdd"
                @deleteItem="handleDelete">
            </Table>
        </section>
        // <span v-pre>{{ this will not be compiled }}</span>
    </section>
</template>

<script setup>
import { ref, reactive, toRefs, onMounted } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import Table from '@/components/Table.vue'

onMounted(() => {
    queryData()
})
const table = ref(null)

const data = reactive({
    /*  materialForm: {
        materailName: '',
        materialCode: '',
        snCode: '',
        productCode: '',
        productName: '',
        result: '',
        workOrder: [],
        productLine: [],
    },
    loading: false,
    lineList: [],
    orderList: [],
    */
    tableData: [],
})

const { materialForm, lineList, orderList, tableData, loading } = toRefs(data)

const title = ref("")

const addData = (param) => {
    param.id = Math.random()
    // const data = Object.assign({}, param) // 拷贝一个对象
    const data = { ...param }
    // const data = JSON.parse(JSON.stringify(param)) // 深拷贝
    tableData.value.push(data)
}

const handleAdd = () => {
    editRef.value.openDialog()
    title.value = '新增'
    formData.value = {}
}
const handleDelete = (index, row) => {
    ElMessageBox.confirm('此操作将会删除本条数据,请确定是否继续执行?','提示',
        {
            confirmButtonText: '确定',
            cancelButtonText: '取消',
            closeOnClickModal: false,
            type: 'warning',
        }
    )
        .then(() => {
            ElMessage({
                type: 'success',
                message: '删除成功',
            })
            tableData.value.splice(index, 1)
        })
        .catch(() => {
            ElMessage({
                type: 'info',
                message: '取消操作',
            })
        })
}

const handleSelectionChange = () => {
    table.value.handleSelectionChange()
}

provide('formObj', { title, formData, addData })

const handleEdit = (rowData) => {
    title.value = '编辑'
    const param = {...rowData}
    formData.value = param
    // formData.value = Object.assign({}, rowData)
    // 避免引用传递,做一次数据拷贝
    // formData.value = JSON.parse(JSON.stringify(row))
    editRef.value.openDialog()
}

const query = () => {
    queryData()
}

const reset = (formEl) => {
    if (!formEl) return
    formEl.resetFields()
    queryData()
}

const queryData = () => {
    loading.value = true
    // const param = { ...materialForm.value, ...{ name: 'zhangsan', age: 20 } }
    fetch("https://jsonplaceholder.typicode.com/users").then((resposne) => resposne.json()).then((json) => {
        loading.value = false
        tableData.value = json
    })
}

</script>
相关推荐
大杯咖啡4 分钟前
localStorage与sessionStorage的区别
前端·javascript
RaidenLiu15 分钟前
告别陷阱:精通Flutter Signals的生命周期、高级API与调试之道
前端·flutter·前端框架
非凡ghost16 分钟前
HWiNFO(专业系统信息检测工具)
前端·javascript·后端
非凡ghost18 分钟前
FireAlpaca(免费数字绘图软件)
前端·javascript·后端
非凡ghost24 分钟前
Sucrose Wallpaper Engine(动态壁纸管理工具)
前端·javascript·后端
拉不动的猪26 分钟前
为什么不建议项目里用延时器作为规定时间内的业务操作
前端·javascript·vue.js
该用户已不存在33 分钟前
Gemini CLI 扩展,把Nano Banana 搬到终端
前端·后端·ai编程
地方地方34 分钟前
前端踩坑记:解决图片与 Div 换行间隙的隐藏元凶
前端·javascript
炒米233337 分钟前
【Array】数组的方法
javascript
jason_yang38 分钟前
vue3+element-plus按需自动导入-正确姿势
vue.js·vite·element