适用场景
简单场景
开发者在页面中实现长列表
或者屏幕滚动
等效果时,习惯使用div组件
做循环遍历
示例如下:
假设开发者要这样的效果:一个结构简单的商品列表
使用 div 组件的代码如下:
<template>
<!-- div实现 -->
<div class="tutorial-page">
<!-- 商品列表 -->
<block for="productList">
<div class="content-item" onclick="route($item.url)">
<image class="img" src="{{$item.img}}"></image>
<div class="text-wrap">
<div class="top-line">
<text class="text-name">{{$item.name}}</text>
<text class="text-price">{{$item.price}}</text>
</div>
<text class="bottom-line">{{$item.brief}}</text>
</div>
</div>
</block>
<!-- 加载更多,监听通用事件appear,出现时加载更多数据 -->
<div class="load-more" onappear="loadMoreData">
<progress type="circular"></progress>
<text>加载更多</text>
</div>
</div>
</template>
然而,当 DOM 结构复杂时,滚动页面会出现卡顿现象,因为 Native 无法复用 div 组件实现的列表元素
为了得到流畅的列表滚动体验,推荐开发者使用list组件
替代div组件
实现长列表布局,因为 Native 会复用相同type属性
的list-item
使用 list 组件的代码如下:
<template>
<!-- 列表实现 -->
<list class="tutorial-page" onscrollbottom="loadMoreData">
<!-- 商品列表 -->
<block for="productList">
<list-item type="product" class="content-item" onclick="route($item.url)">
<image class="img" src="{{$item.img}}"></image>
<div class="text-wrap">
<div class="top-line">
<text class="text-name">{{$item.name}}</text>
<text class="text-price">{{$item.price}}</text>
</div>
<text class="bottom-line">{{$item.brief}}</text>
</div>
</list-item>
</block>
<!-- 加载更多,type属性自定义命名为loadMore -->
<list-item type="loadMore" class="load-more">
<progress type="circular"></progress>
<text>加载更多</text>
</list-item>
</list>
</template>
要实现 DOM 片段的复用,要求相同type属性
的 DOM 结构完全相同。所以,设置相同type属性
的list-item
是优化列表滚动性能的关键
注意:
list-item
内不能再嵌套list
list-item
的type属性
为必填属性list-item
内部需谨慎使用if指令
或for指令
,因为相同type属性
的list-item
的 DOM 结构必须完全相同,而使用if指令
或for指令
会造成 DOM 结构差异提示:
若遇到类似xxx cannot be cast to xxx at …list的错误,请检查list-item组件
是否存在如下情形:
- 未设置
type属性
。解决方案:设置type属性
- 内部使用了
if指令
。解决方案:使用show指令
代替if指令
,或设置不同的type属性
- 设置为相同的
type属性
,但 DOM 结构不一致。解决方案:设置不同的type属性
复杂场景
实现简单的商品列表,了解list组件
的基本用法和优化性能的关键后,接下来通过实现多种列表元素类型的复杂列表,进一步了解list组件
示例如下:
假设开发者要实现这样的效果:一个商品列表页,图片位于左边和图片位于右边的商品交错显示
列表中的列表元素可以分为三类,设置三种不同type属性
的list-item
。分别为:
- 图片在左,文字在右的
list-item
,type属性
自定义命名为productLeft
- 图片在右,文字在左的
list-item
,type属性
自定义命名为productRight
- 加载更多的
list-item
,type属性
自定义命名为loadMore
示例代码如下:
<template>
<!-- list中可以划分为三种类型的DOM结构,对应三种type属性的list-item -->
<list class="tutorial-page" onscrollbottom="loadMoreData">
<block for="{{productList}}">
<!-- 图片在左,文字在右的list-item,type属性自定义命名为productLeft -->
<list-item type="productLeft" class="content-item" if="{{$idx%2 === 0}}" onclick="route($item.url)">
<image class="img" src="{{$item.img}}"></image>
<div class="text-wrap">
<div class="top-line">
<text class="text-name">{{$item.name}}</text>
<text class="text-price">{{$item.price}}</text>
</div>
<text class="bottom-line">{{$item.brief}}</text>
</div>
</list-item>
<!-- 图片在右,文字在左的list-item,type属性自定义命名为productRight -->
<list-item type="productRight" class="content-item" if="{{$idx%2 === 1}}" onclick="route($item.url)">
<div class="text-wrap">
<div class="top-line">
<text class="text-name">{{$item.name}}</text>
<text class="text-price">{{$item.price}}</text>
</div>
<text class="bottom-line">{{$item.brief}}</text>
</div>
<image class="img" src="{{$item.img}}"></image>
</list-item>
</block>
<!-- 加载更多的list-item,type属性自定义命名为loadMore -->
<list-item type="loadMore" class="load-more">
<progress type="circular"></progress>
<text>加载更多</text>
</list-item>
</list>
</template>