由于需求的踢出,重启自己去年写的以前的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"><</button>
<text style="text-align: center;min-width:30px;">{{currentPage}}/{{pageTotal}} </text>
<button size="mini" class="customBtn" @click="NextPage">></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"><</button>
<text style="text-align: center;min-width:30px;">{{currentPage}}/{{pageTotal}} </text>
<button size="mini" class="customBtn" @click="NextPage">></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>








网友评论