vue 封装Table组件

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

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

<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>

在具体的父组件中使用:

<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>
        // {{ this will not be compiled }}
    </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>

你可能感兴趣的:(Vue,vue.js,javascript,前端)