美文网首页
vue 移动端表格性能问题 自实现分页和别人的分页对接

vue 移动端表格性能问题 自实现分页和别人的分页对接

作者: 吉凶以情迁 | 来源:发表于2025-06-27 10:00 被阅读0次

由于需求的踢出,重启自己去年写的以前的unip vue项目,
uniapp unitable过多数据加载卡顿的前端解决思路 - 简书

发现各种 跑不起来,uniapp的很多ui出问题了,很丑,uniapp若不是为了以后能跨端我都想弃用了, 为了美化使用,至少做出和安卓的material design 样式差不多不显得很丑,我就找啊找,找到了一个比较好的ui varletjs 能兼容uniapp.

现在折腾到表格了,其它的批量换掉了。

由于移动端的表格超过几百条就会卡顿,但是我又不想做分页接口,也就是说数据源依然是一次性查询多少条,
这种情况 照样能分页的 那就是对设置过来的东西分页。

用法就是这样,

    <smarttable
    :columns="columns" :rows="rows" 
         />

其实本来是直接支持 rows不需要指定列的,后面是用到了某个表格 ,发现功能比较弱,我就直接一次性在数据源的地方封装好了。

    const { columns, rows } = resDataToTable(res.data)
export function resDataToTable(data : Record<string, any>, key = "rows") : {
    columns : Array<any>,
    rows : Array<any>
} {
    let currentColumns = []

    //#ifndef  APP-NVUE
    currentColumns.push({
        "title": '#'
    })
    // #endif
    if (data[key]) {
        var currentRows : Array<any> = data[key]
        if (currentRows.length > 0) {
            let currentJSON = currentRows[0]
            Object.keys(currentJSON).forEach((currentTitle, index) => {
                currentColumns.push({
                    "title": currentTitle
                })
            });

        } else {

        }
        return { columns: currentColumns, rows: currentRows };

    } else {
        return { columns: [], rows: [] };
    }
}

如图 ,上面是我写的,下面是var-page


image.png

<block v-if="total>0">
        <view class="hor w100" style="font-size: 12px;margin: 5px 2px;flex-direction: row;align-items: center;">
            <button size="mini" class="customBtn" @click="PrePage">&lt;</button>
            <text style="text-align: center;min-width:30px;">{{currentPage}}/{{pageTotal}} </text>
            <button size="mini" class="customBtn" @click="NextPage">&gt;</button>
            <text>共{{rows?rows.length:0}}条</text>
            <view style="flex:1;"></view>
            <input ref="input" type="number" @input="onInput" placeholder="分页/跳转"
                style="max-width: 60px;border:1px #ccc solid;text-align: center;margin:0 5px;font-size: 12px;min-height: 30px;"
                maxlength="3" />
            <button size="mini" class="customBtn" @click="GoClick">跳转</button>
            <button size="mini" class="customBtn" @click="SplitClick">分页</button>

        </view>
    </block>
    <var-pagination :current="currentPage" :size="pageSize" :size-option="[5,10,50,100,200,500]" :simple="true"
        :total="total" @change="onPaginationChange" show-quick-jumper :show-size-changer="true"
        :show-total="total => `${total}`" />
    <var-table ref="table" default="暂无数据" sortable="true">
        <thead>
            <tr>
                <block :data-index="index" :data-item="bean" v-for="(bean, index) in columns" :key="index">
                    <th style="text-align: center;white-space: nowrap">{{bean.title+""}}</th>
                </block>
            </tr>
        </thead>
        <tr v-for="(item, index) in splitrows" :key="index" style="width: 750rpx;">
            <block :data-index="index" :data-item="bean" v-for="(bean, index) in columns" :key="index">
                <td style="text-align: center;white-space: nowrap">
                    {{item[bean.title]+""}}
                </td>
            </block>
        </tr>
    </var-table>

可以看到他们都比我共用了变量,

对接 var-pagination只需要把之前的对接上就行了。
它的分页测试发现,切换分页的时候 这个size会自动变, 也就是说,我这里 重新计算一下问题就不大。

    onPaginationChange: function(currentPage, size) {
        
                this.pageSize = size
                this.pageTotal = Math.ceil(this.total / this.pageSize)
                this.onPageChange(currentPage);
                console.log("current:" + current + ",size:" + size)
    },


最后是完整代码了。

<template>
    <block v-if="total>0">
        <view class="hor w100" style="font-size: 12px;margin: 5px 2px;flex-direction: row;align-items: center;">
            <button size="mini" class="customBtn" @click="PrePage">&lt;</button>
            <text style="text-align: center;min-width:30px;">{{currentPage}}/{{pageTotal}} </text>
            <button size="mini" class="customBtn" @click="NextPage">&gt;</button>
            <text>共{{rows?rows.length:0}}条</text>
            <view style="flex:1;"></view>
            <input ref="input" type="number" @input="onInput" placeholder="分页/跳转"
                style="max-width: 60px;border:1px #ccc solid;text-align: center;margin:0 5px;font-size: 12px;min-height: 30px;"
                maxlength="3" />
            <button size="mini" class="customBtn" @click="GoClick">跳转</button>
            <button size="mini" class="customBtn" @click="SplitClick">分页</button>

        </view>
    </block>
    <var-pagination :current="currentPage" :size="pageSize" :size-option="[5,10,50,100,200,500]" :simple="true"
        :total="total" @change="onPaginationChange" show-quick-jumper :show-size-changer="true"
        :show-total="total => `${total}`" />
    <var-table ref="table" default="暂无数据" sortable="true">
        <thead>
            <tr>
                <block :data-index="index" :data-item="bean" v-for="(bean, index) in columns" :key="index">
                    <th style="text-align: center;white-space: nowrap">{{bean.title+""}}</th>
                </block>
            </tr>
        </thead>
        <tr v-for="(item, index) in splitrows" :key="index" style="width: 750rpx;">
            <block :data-index="index" :data-item="bean" v-for="(bean, index) in columns" :key="index">
                <td style="text-align: center;white-space: nowrap">
                    {{item[bean.title]+""}}
                </td>
            </block>
        </tr>
    </var-table>

</template>

<script>
    import {
        showToast,
        showLoading,
        showErrorToast,
        hideLoading,
        showShortErrorToast
    } from '@/utils/util';
    export default {

        name: "smarttable",
        data() {
            return {
                android: false,
                nvue: false,
                pageTotal: 1,
                inputvalue: '1',
                splitrows: [],
                currentPage: 1,
                total: 0,

                pageSize: 30

            }

        },
        watch: {
            rows: {
                handler(newVal) {
                    console.log("watch rows")
                    this.currentPage = 1;
                    this.total = newVal.length;
                    this.pageTotal = Math.ceil(this.total / this.pageSize)
                    this.splitrows = this.paginate(newVal, 1);
                    console.log("rows receive", this.splitrows.length)
                },
                deep: false,
            },
        },


        props: {
            rows: {
                type: Array,
                default: () => []
            },

            columns: {
                type: Array,
                default: () => []
            }


        },
        mounted() {
            //#ifdef  APP-NVUE

            this.nvue = true
            // #endif
            //  const systemInfo = uni.getSystemInfoSync();
            console.log("mounted ---", this.rows.length)
            if (this.rows.length > 0 && this.total == 0) {
                this.currentPage = 1;
                this.total = this.rows.length;
                this.pageTotal = Math.ceil(this.total / this.pageSize)
                this.splitrows = this.paginate(this.rows, 1);
            }
            //  this.android = systemInfo.platform.toLowerCase() === 'android';
        },

        beforeCreate() {

            console.log("beforecreate")

        },
        methods: {
            paginate(rowsarg, currentPage) {
                let current;
                if (rowsarg.length > this.pageSize) {
                    const startIndex = (currentPage - 1) * this.pageSize;
                    const endIndex = startIndex + this.pageSize;
                    current = rowsarg.slice(startIndex, endIndex);
                } else {
                    current = rowsarg;
                }
                for (let a = 0; a < current.length; a++) {
                    let model = current[a]
                    let currentId = (a + 1) + (this.currentPage > 1 ? (this.pageSize * (this.currentPage - 1)) : 0);
                    //#ifndef  APP-NVUE
                    model["#"] = currentId
                    // #endif

                }
                return current;
            },
            onInput(e) {
                let value = e.detail.value
                this.inputvalue = value
                /*      let a = Number(value)
                        if (a && this.total > this.pageSize && a < this.total / this.pageSize) {

                        } */
            },
            PrePage() {
                let temp = this.currentPage - 1;
                if (temp < 1) {
                    showShortErrorToast("已是第一页了!")
                } else {
                    this.onPageChange(temp)
                }

            },

            NextPage() {

                let temp = this.currentPage + 1;
                let pageTotal = Math.ceil(this.total / this.pageSize)
                if (temp > pageTotal) {
                    console.log("pageTotal:" + pageTotal + ",next:" + temp)
                    showShortErrorToast("已是最后一页了!")
                } else {
                    this.onPageChange(temp)
                }

            },
            SplitClick() {
                let value = this.inputvalue;
                let numberPage = Number(value)
                if (value < 5 || value > 1000) {
                    showShortErrorToast("分页范围超出,必须在5到1000之间,当前为" + value)
                } else {
                    this.pageSize = numberPage
                    this.pageTotal = Math.ceil(this.total / this.pageSize)
                    this.onPageChange(1);

                }
            },
            onPaginationChange: function(currentPage, size) {
                let value = this.inputvalue;
                this.pageSize = size
                this.pageTotal = Math.ceil(this.total / this.pageSize)
                this.onPageChange(currentPage);
                console.log("current:" + current + ",size:" + size)
            },
            GoClick() {
                let value = this.inputvalue; // this.$refs.input.value
                let a = Number(value)
                let pageTotal = Math.ceil(this.total / this.pageSize)
                if (a) {
                    if (this.total > 0 && a <= pageTotal) {
                        /*          this.currentPage = value;
                                    this.splitrows = this.paginate(this.rows, this.currentPage); */
                        this.onPageChange(value);
                        //          console.log("currentInputAndCurrentPage", this.inputvalue, this.currentPage)

                    } else {
                        console.error("page more than max page  ", pageTotal, "totalCount", this.total, a);
                        showShortErrorToast("页数超出,最大页不能超过" + pageTotal + "页")
                    }

                } else {
                    showShortErrorToast("输出错误")
                    console.error("error input ", a, this.$refs);
                }

            },
            onPageChange: function(pageArg) {

                let pageTotal = Math.ceil(this.total / this.pageSize)
                if (pageArg > pageTotal) {
                    showShortErrorToast("已到末尾了")
                } else {
                    this.currentPage = pageArg; //e.current;
                    this.splitrows = this.paginate(this.rows, this.currentPage);
                    console.log("onPageChange", pageArg, this.currentPage, pageTotal)
                    //e={type,current} 
                }

            }

        }
    }
</script>

<style>
    .customBtn {
        margin: 0 5px;
        text-align: center;
        font-size: 12px !important;
        padding: 0 10px;
    }
</style>

相关文章

网友评论

      本文标题:vue 移动端表格性能问题 自实现分页和别人的分页对接

      本文链接:https://www.haomeiwen.com/subject/pdupgjtx.html