前端table分页组件开发(手写组件)

这段时间,在开发过程中接到一个需求,当时接到这个需求的时候,本来想着是找一找ui组件啥的来,但是后面找了一圈后,没有找到符合的,没办法,只能自己花点时间写一下了

先看下需求,在页面的顶部加入一样table,当我们点击table时底部的页面切换,中间的内容根据切换的tab来切换,tablei里还有小table,当点吉小table时,小table也跟着切换,先来看下实际的结果图

 先说一下我的逻辑吧,我将顶部的table写成一个组件,将父组件渲染table的数据通过props将数据传递过来,在用watch监听props数据,当切换父组件时,顶部table实时更新,代码如下:

 通过将父组件的数据拿到后,在页面上渲染出来,然后写2套css,一套是选中的状态还有一套是没有选中的状态,在html代码里,给class加上三木运算,根据某个参数来觉得当前选中的内容,

 到现在是实现了,当点击父组件的内容是,顶部table实时更新,然后要实现的就是我们点击顶部的table,父组件的内容更新了,这里我们需要做的就是,获取到当前点击的是什么内容,然后通过emit函数,将我们选中的内容传递出去,让父组件根据我们传递的数据实时渲染。大概逻辑就是,我们顶部table里分一级table和二级table,这些都是通过for循环渲染出来的,for循环的key不就是最好的数据吗?代码如下

 然后,因为我们的二级table是写在一级table里的,所以我们在一级table的点击事件里把emit写上,当我们点击一级table时,将当前选中的数据传递出去;

 到这里后,还有一个小bug,就是,比如我们切换第一个table,第一个table的二级table选中了某一项后,然后切换到第二个table时会导致里面的二级table没有重置,因为我选中哪一个table都是通过下标来确定的,下标没有重置就会导致没有数据,比如我第一个table有3个二级table,而第二个table则只有2个,当我们在第一个table时将二级table选中第三个的话,就会导致我们切换到第二个table时第二个table的二级table没有选中数据,因为没有下标是2的数据,这时候我们就要监听一级table的下标,当下标变化时,将二级table的下标重置为0,也就是重新选中第一个table。

 这里解释下,为什么在emit那里要用到settimeout,这是因为,像父组件传值比我们赋值要快,这样就是导致像父组件传的值都是旧值,,简单说,wacth比emit执行的慢,只能让emit等待下了,等watch将数据更新后在提交了。

总代码如下:

<template>
    <div class="table-container">
        <table cellspacing="0" cellpadding="0">
            <tr>
                <td :class="outerindex == key ? 'box' : 'onbox'"
                    :style="key == 0 ? 'border-radius: 4px 0px 0px 4px;' : key == length - 1 ? 'border-radius: 0px 4px 4px 0px;' : ''"
                    v-for="(item, key) in tabledata" :key="key" @click="table(key)">
                    <span>{{ item.name }}</span>
                    <div>
                        <button v-for="(itemb, key) in item.tab" :key="key"
                            :class="withinindex == key ? 'button' : 'onbutton'" @click="innertable(key)">{{ itemb.tabName
                            }}</button>
                    </div>
                </td>
            </tr>
        </table>
    </div>
</template>
<script lang="ts">
import { reactive, ref, watch, onMounted, computed } from "vue"

export default ({
    name: 'tab',
    props: {
        tablearr: Object
    },
    setup(props: any, contest: any) {
        // 思考 ref 响应式和 reactive 响应式的区别; 修改对象属性值,是否会刷新数据
        let tabledata = reactive(props.tablearr)


        console.log(props.tablearr, 12)
        let outerindex = ref(0)  //外层大table每次默认选择第一个

        let withinindex: any = ref(0) //里层小tab每次进入时默认选择第一个

        const length = ref(0)
        onMounted(() => {
            length.value = props.tablearr.length
        })


        watch(props, () => {  //监听父组件传过来的props数据,当父组件切换小table时,子组件实时更新
            tabledata = props.tablearr

        })

        watch(outerindex, () => {  //当切换最外层的的table时,必须将里层的table重置到第一位
            withinindex.value = 0
        })

        const table = (key: any) => {  //点击大table对小tab进行切换
            outerindex.value = key
            setTimeout(()=>{contest.emit("item", [outerindex.value, withinindex.value])},50)//当点击table时,将当前选择的是哪个table告诉父组件,暂定格式是 [外层table的下标,里层table的下标]
        }

        const innertable = (key: any) => {
            withinindex.value = key
        }

        return {
            tabledata,
            outerindex,
            table,
            withinindex,
            length,
            innertable
        }
    }
})
</script>
<style lang="stylus" scoped>
.table-container{
    td{
        height:68px;
        width:173px;
    }
    span{
        font-weight: 550;
        font-size:16px;
    }
    button{
        width:45px;
        height:30px;
        border: none;
        margin-left:2px;
    }

/*选中的状态 */
    .box{
      border: 1px solid #26D6B9;
      background: #F8FFFE;
      table{
        border: 0;
      }
        span{
            font-family: "思源黑体 Regular";
            color: #3E3E3E;
        }
        .button,.onbutton{
            border-bottom: 2px solid  #26D6B9;
            background:rgba(0,0,0,0);
            color:#0AC8A9;
        }
        .onbutton{
            border-bottom: 2px solid #E4E7ED;
            color:#707070;
        }



    }

    /*未选中的状态 */
    .onbox{
        border: 1px solid #DCDFE5;
        span{
            color: #707070;
        }
        button{
            border-bottom: 2px solid   #E4E7ED;
            background:rgba(0,0,0,0);
            color:#707070;
        }
    }

}

</style>
    

父组件传递来的数据:

            tabs: [{buttonName: '新增排放源',
                    tab: [
                        { tabName: '材料', name: 1, sendType: 10 },
                        { tabName: '能耗', name: 2, sendType: 11 },},
                    {buttonName: '新增排放源',
                    tab: [
                        { tabName: '材料', name: 1, sendType: 10 },
                        { tabName: '能耗', name: 2, sendType: 11 },}]
            
        
                
      

BAIBAI

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
要使用 `el-table` 实现分页功能,可以按照以下步骤进行: 1. 在页面上引入 `el-pagination` 组件,或者使用 `el-table` 内置的分页组件。 2. 在 `el-table` 组件中添加 `:data` 属性,绑定数据源。 3. 在 `el-table` 组件中添加 `:page-size` 属性,设置每页显示的数据量。 4. 在 `el-table` 组件中添加 `:current-page` 属性,绑定当前页码。 5. 在 `el-table` 组件中添加 `@size-change` 和 `@current-change` 事件,分别处理分页大小和页码改变的逻辑。 6. 在 `el-table` 组件中添加 `slot="append"`,在表格下方添加分页组件。 下面是一个示例代码: ```html <template> <div> <el-table :data="tableData" :page-size="pageSize" :current-page.sync="currentPage" @size-change="handleSizeChange" @current-change="handleCurrentChange"> <el-table-column prop="name" label="姓名"></el-table-column> <el-table-column prop="age" label="年龄"></el-table-column> <el-table-column prop="address" label="地址"></el-table-column> <el-table-column prop="email" label="邮箱"></el-table-column> <el-table-column prop="phone" label="电话"></el-table-column> <el-table-column prop="company" label="公司"></el-table-column> <template slot="append"> <el-pagination :current-page.sync="currentPage" :page-size="pageSize" :total="total" @size-change="handleSizeChange" @current-change="handleCurrentChange" layout="total, sizes, prev, pager, next, jumper"></el-pagination> </template> </el-table> </div> </template> <script> export default { data() { return { tableData: [], // 数据源 currentPage: 1, // 当前页码 pageSize: 10, // 每页显示数据量 total: 0, // 总数据量 }; }, methods: { // 分页大小改变 handleSizeChange(val) { this.pageSize = val; this.getData(); }, // 页码改变 handleCurrentChange(val) { this.currentPage = val; this.getData(); }, // 获取数据 getData() { // 发送请求获取数据 // ... // 设置总数据量 this.total = 100; // 设置数据源 this.tableData = [{ name: "张三", age: 20, address: "北京市", email: "[email protected]", phone: "13812345678", company: "ABC公司" }, { name: "李四", age: 25, address: "上海市", email: "[email protected]", phone: "13912345678", company: "DEF公司" }, { name: "王五", age: 30, address: "广州市", email: "[email protected]", phone: "13712345678", company: "GHI公司" }]; }, }, mounted() { this.getData(); }, }; </script> ```

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

香蕉麻花皮

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值