首页 > 移动开发 > 移动测试 > 如何解决快应用页面滑动卡顿问题
问题现象
页面一次加载了 100 条数据,页面滑动出现卡顿。
<template>
<div class="container">
<div class="nav">
<text class="nav-item">list</text>
</div>
<!-- List -->
<list class="list" onclick="listClick" onlongpress="listLongPress"
onscrollbottom="scrollbottom" id="list" scrollpage="{{scrollPage}}">
<list-item type="listItem" class="item" onclick="listItemClick"
if="{{listData.length>0}}">
<div for="{{listData}}" style="flex-direction:column;">
<text class="txt">{{$item}}--{{$idx}}</text>
</div>
</list-item>
<!-- Loading More -->
<list-item type="loadMore" class="load-more" if="{{loadMore}}">
<progress type="circular"></progress>
<text>More</text>
</list-item>
</list>
</div>
</template>
<style>
.container{
flex-direction: column;
}
.list {
padding-left: 10px;
padding-right: 10px;
columns: 1;
flex-direction: column;
border-color: #FF0000;
border-width: 5px;
}
.item {
flex-direction: column;
align-items: flex-start;
margin-bottom: 15px;
border-color: #9400D3;
border-width: 5px;
margin-right: 20px;
background-color: #f76160;
}
.load-more {
justify-content: center;
align-items: center;
height: 100px;
border-color: #bbbbbb;
border-bottom-width: 1px;
}
.btn-little {
flex: 1;
height: 80px;
margin-left: 15px;
border-radius: 5px;
color: #ffffff;
font-size: 30px;
text-align: center;
background-color: #0faeff;
}
.nav {
padding-left: 60px;
padding-right: 60px;
padding-bottom: 30px;
}
.nav-item {
flex: 1;
padding-bottom: 30px;
border-bottom-width: 5px;
border-color: #fbf9fe;
font-size: 35px;
color: #666666;
text-align: center;
}
</style>
<script>
import prompt from '@system.prompt'
export default {
data: {
componentName: 'list',
loadMore: true,
listAdd: ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'],
listData: [],
scrollPage: false,
},
onInit: function () {
this.$page.setTitleBar({ text: 'list' })
for(var index = 0;index < 100;index++){
this.listData[index] = 'A';
}
},
scrollbottom: function () {
prompt.showToast({
message: 'The list slides to the bottom and starts loading other data.'
})
// Load next page
var that = this
var renderData = [].concat(that.listData, that.listAdd)
setTimeout(function () {
that.listData = renderData
}, 1000)
},
// monitoring during sliding
scroll: function (e) {
let msg = 'scroll' + '.scrollX:' + e.scrollX
+ ' .scrollY:' + e.scrollY
+ ' .scrollState:' + e.scrollState
console.info(msg)
},
listItemClick: function (e) {
e.stopPropagation()
console.info('List Item is clicked.')
prompt.showToast({
message: 'List Item is clicked.'
})
},
listClick: function (e) {
e.stopPropagation()
console.info('List is clicked.')
prompt.showToast({
message: 'List is clicked.'
})
},
listLongPress: function (e) {
e.stopPropagation()
console.info('List is long pressed.')
prompt.showToast({
message: 'List is long pressed.'
})
},
}
</script>
以上代码使用list 、list-item 来加载大规模数据,但是使用方法不当,导致list-item 的视图view 没有被复用。
我们知道快应用的引擎是一个android apk ,list 、list-item 的实现最终都是通过android 的ListView 、BaseAdapter 等这些实现的,了解这些其实知道列表界面上超过屏幕显示的区域是不会重新创建视图的,而是复用第一次在界面上可见区域的那些view 的,只需要把数据刷新一下即可。每一行的视图view 其实就是list-item 。
以上代码虽然看起来是列表,但是只有1 个list-item ,开发者在list-item 内部使用了for 循环,每循环一次,都会创建一个新的view ,当数据量很大时,内存占用越多,手机内存吃紧,不断地做申请、释放内存的操作,应用性能受到严重影响,导致滑动卡顿。
基于list 组件的特点,在list-item 内部内部需谨慎使用if 指令或for 指令,根据列表每行数据特点,在list-item 上设置不同的type ,尽可能复用list-item ,在list-item 上使用for 语句。修改后代码如下( 注意list-item部分):
<template>
<div class="container">
<div class="nav">
<text class="nav-item">list</text>
</div>
<!-- List -->
<list class="list" onclick="listClick" onlongpress="listLongPress"
onscrollbottom="scrollbottom" id="list" scrollpage="{{scrollPage}}">
<list-item type="listItem" class="item item-color" onclick="listItemClick"
for="{{listData}}">
<text class="txt">{{$item}}--{{$idx}}</text>
</list-item>
<!-- <list-item type="listItem" class="item" onclick="listItemClick"
if="{{listData.length>0}}">
<div for="{{listData}}" style="flex-direction:column;">
<text class="txt">{{$item}}--{{$idx}}</text>
</div>
</list-item> -->
<!-- Loading More -->
<list-item type="loadMore" class="load-more" if="{{loadMore}}">
<progress type="circular"></progress>
<text>More</text>
</list-item>
</list>
</div>
</template>
代码运行效果图对比:

图 1 修改后效果

图 2 修改前效果
从上面效果图中我们看到,虽然都是列表数据,但是图1 每一行都是一个list-item (list-item 的css 中背景色设置的是红色),而且type 值都一样,能很好地复用list-item ,但是图2 中只有1 个list-item ,里面列表数据都是作为list-item 的子节点。图2 的效果和使用普通的div 加载大量列表数据是一样的,根源在于开发者没有很好地理解list 、list-item 的原理。
欲了解更多详情,请参见:
快应用list 开发指导:
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/69970551/viewspace-2787085/ ,如需转载,请注明出处,否则将追究法律责任。