组件封装练习1---table表格

技术栈:

vue3,html,less,antd-vue

封装代码

<template>
    <div class="tabalBox">
        <table :class="tabalFlex ? 'tabalFlex' : ''" id="table">
            <tr class="trHead">
                <th v-for="item in columns">
                    <a-checkbox v-if="item.key == 'select'" :checked="checkAll"             
                    @click="getAll"></a-checkbox>
                    <span>
                        {{ item.title }}
                        <div v-if="item.sort">
                            <button @click="item.sort.top()"></button>
                            <button @click="item.sort.down()"></button>
                        </div>
                    </span>
                </th>
            </tr>
            <!-- 
                参数接受的变量
                width:设置别个宽度
                style:设置表格样式
                select:放在columns的多选属性
             -->
            <tr v-for="(item, index) in dataList">
                <template v-for="value in columns">
                    <td :width="value.width" :style="value.style">
                        <a-checkbox v-if="value.key == 'select'" @change="beCheck(index,     
                        $event)" :value="item.id"
                            :checked="checkDataArr[index]">
                        </a-checkbox>
                        <span :title="valueKey(item, value.key)" v-if="!value.slots && 
                            value.key != 'id'">
                            {{ valueKey(item, value.key) }}
                        </span>
                        <span v-else-if="value.key == 'id'">
                            {{ currentPage.size * (currentPage.current - 1) + index + 1 
                             }}
                        </span>
                        <!-- 插槽 -->
                        <slot v-else :name="value.slots" :value="item"></slot>
                    </td>
                </template>
            </tr>
            <slot name="addNewTr"></slot>
        </table>
    </div>
</template>

<script lang='ts' setup>
import { ref, onMounted, watch } from "vue"
const father = defineProps<{
    columns: any[],//表头参数
    dataList: any[],//表格数据
    currentPage?: any,//分页
    delIdArr: string[],//多选删除id数组
    tabalFlex?: boolean
}>()
//接受多选参数函数
const fatherFn = defineEmits(['chooseId'])

const checkDataArr = ref<boolean[]>([]);
const checkAll = ref<boolean>(false)

//在创建阶段渲染所有选中数组
onMounted(() => {

    checkDataArr.value = father.dataList.map(() => false)
})

watch(
    () => [father.delIdArr, father.dataList],
    (newValue, oldValue) => {

        if (!newValue[0][0]) {
            checkDataArr.value = father.dataList.map(() => false)
            checkAll.value = false
        }

        if (newValue[1].length != oldValue[1].length) {
            checkDataArr.value = father.dataList.map(() => false)
        }

    },
    {
        deep: true
    }
)

//选中某一个
const beCheck = function (num: number, e: any) {
    checkDataArr.value[num] = e.target.checked
    if (checkDataArr.value.indexOf(true) != -1) {
        checkAll.value = true
    } else {
        checkAll.value = false
    };
    choiceDataId()
}

//选中所有
const getAll = function () {
    checkAll.value = !checkAll.value
    if (checkAll.value) {
        checkDataArr.value = checkDataArr.value.map(() => true)
    } else {
        checkDataArr.value = checkDataArr.value.map(() => false)
    }
    choiceDataId()
}

//选中id
function choiceDataId() {
    let arr: string[] = []
    checkDataArr.value.forEach((item: boolean, index: number) => {
        if (item) {
            arr.push(father.dataList[index].id)
        }
    })
    fatherFn('chooseId', {
        value: arr,
    })
}

//对value.key进行进一步解析
function valueKey(item: any, str: string): string {
    // console.log("item", item);
    let newStr = ""
    if (str.indexOf('.') == -1) {
        str == 'price' ? newStr = "¥" + item[str] : newStr = item[str]
    } else {
        let arr = str.split('.');
        if (item[arr[0]] == null || (item[arr[0]][arr[1]] == null || undefined)) {
            newStr = "数据丢失了"
        } else {
            newStr = item[arr[0]][arr[1]]
        }
    }

    return newStr
}
</script>

<style scoped lang="less">
.tabalBox {
    min-height: 500px;
}

.tabalFlex {
    table-layout: fixed;
}


table {
    width: 100%;
    border-top: 1px solid rgba(46, 203, 191, 1);

    tr:nth-child(1) {
        background-color: #F8F8F8;
    }

    tr:nth-child(2n+3) {
        background-color: rgba(13, 152, 162, 0.08);
    }

    tr {
        height: 60px;
        width: 100%;

        th {
            >span {
                display: flex;
                align-items: center;
                justify-content: center;

                >div {
                    display: flex;
                    flex-direction: column;
                    align-items: center;
                    justify-content: center;
                    margin-left: 5px;

                    button {
                        // width: 15px;
                        // height: 15px;
                        border: 7.5px solid transparent;
                        background-color: transparent;
                        cursor: pointer;
                    }

                    button:nth-child(1) {
                        border-bottom: 7.5px solid #ccc;
                        margin-bottom: 5px;
                    }

                    button:nth-child(2) {
                        border-top: 7.5px solid #ccc;
                    }
                }
            }
        }

        td {
            text-align: center;

            a {
                color: #000;
                cursor: auto;
            }
        }

    }
}
</style>

页面引用使用

<tamplate>
    <MyTable :columns="columns" :dataList="dataList" :delIdArr="[]"                     :currentPage="currentPage">
        <template v-slot:avatarUrl="slotProps">
          <div>
            <img style="height: 20px;border-radius: 10px;" :src="slotProps.value.user.avatarUrl" alt="">
              {{ slotProps.value.user.nickName }}
           </div>
        </template>
    </MyTable>
</template>

<script setup lang="ts">
import {ref} from "vue"
import {MyTable} from "./../components/myTable.vue"

const delIdArr = ref<string[]>([])//根据需求传值,不需要多选框可直接传空数组
const dataList = ref<any[]>([])
const columns = ref<any[]>([
    {
        title:"全选",
        key:"select"
    },
    {
        title: "序号",
        key: "id",
    },
    {
        title: "设备编号",
        key: "machineId",
        slots: "machineId",
        style: {
            color: "rgba(15, 79, 149, 1)"
        }
    },
    {
        title: "头像/昵称",
        key: "avatarUrl",
        slots: "avatarUrl"
    },
    {
        title: "手机号",
        key: "user.phoneNumber",
    },
    {
        title: "金额(元)",
        key: "money",
        slots: "money",
        style: {
            color: "rgba(255, 142, 18, 1)"
        }
    },
    {
        title: "重量Kg",
        key: "weight"
    },
    {
        title: "投递次数",
        key: "userCount",
        sort: {
            show: true,
            top: () => {
                  //正序
            },
            down: () => {
                  //降序
            }
        }
    },
    {
        title: "积分",
        key: "amount",
        style: { color: 'rgba(249, 88, 88, 1)' }
    },
    {
        title: "申请时间",
        key: "createTime",
    },
    {
        title: "开门图片",
        key: "openImage",
        slots: "openImage",
    },
    {
        title: "关门图片",
        key: "closeImage",
        slots: "closeImage",
    },
    {
        title: "操作",
        key: "action",
        slots: "action"
    }
])
</script>

解析

表头:表头通过循环colums实现

表格:数据有datalist提供,并且通过colums的key值渲染数据,因为有些表格数据可能涉及插槽,传参如上。

其中解析参数时,还对基本的对象参数进行了解析,解析函数如上valueKey的function,但是多个对象嵌套的参数没法使用,比如a.b.c.d,这类需要用到递归,后期需要继续改进

总结

该组件封装下来感觉跟antd的表格组件差不多,虽说功能欠缺了很多,但是写的时候感觉很多逻辑都几乎相同,中间主要用到了父子组件传参,v-for,还有插槽等技术,需要先对这几个基础有一定的了解。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值