UniApp跨端开发进阶:高性能瀑布流列表优化全攻略
一、瀑布流核心实现方案
多端兼容的高性能瀑布流布局方案:
// 核心数据结构
data() {
return {
loading: false,
pageSize: 10,
columns: [[], []], // 两列数据
columnHeights: [0, 0], // 列高度记录
itemWidth: 0
}
},
// 计算布局
methods: {
async loadData() {
if (this.loading) return;
this.loading = true;
const res = await this.$http.get('/api/items', {
page: this.currentPage,
size: this.pageSize
});
// 动态计算布局
this.calculateLayout(res.data);
this.currentPage++;
this.loading = false;
},
calculateLayout(items) {
items.forEach(item => {
// 计算图片宽高比
const ratio = item.height / item.width;
const itemHeight = this.itemWidth * ratio;
// 找到高度较小的列
const colIndex = this.columnHeights[0] <= this.columnHeights[1] ? 0 : 1;
this.columns[colIndex].push({
...item,
itemHeight
});
// 更新列高度
this.columnHeights[colIndex] += itemHeight + 10; // 10为间距
});
}
}
核心优势:跨端兼容、动态计算、内存优化、流畅滚动
二、高级优化技巧
1. 虚拟列表优化
// 使用uni.$on/uni.$off实现简易虚拟列表
data() {
return {
visibleData: [],
scrollTop: 0,
viewportHeight: 0,
itemHeights: []
}
},
mounted() {
this.viewportHeight = uni.getSystemInfoSync().windowHeight;
uni.$on('pageScroll', this.handleScroll);
},
methods: {
handleScroll(e) {
this.scrollTop = e.scrollTop;
this.updateVisibleData();
},
updateVisibleData() {
const startIdx = this.findStartIndex();
const endIdx = Math.min(
startIdx + Math.ceil(this.viewportHeight / this.avgItemHeight) + 5,
this.list.length
);
this.visibleData = this.list.slice(startIdx, endIdx);
},
findStartIndex() {
// 二分查找优化性能
let low = 0, high = this.itemHeights.length - 1;
while (low <= high) {
const mid = Math.floor((low + high) / 2);
if (this.itemHeights[mid] < this.scrollTop) {
low = mid + 1;
} else {
high = mid - 1;
}
}
return high;
}
}
2. 图片懒加载优化
// 基于IntersectionObserver的懒加载
methods: {
initObserver() {
this.observer = uni.createIntersectionObserver(this);
this.observer.relativeToViewport({
top: this.viewportHeight,
bottom: this.viewportHeight
}).observe('.lazy-img', res => {
if (res.intersectionRatio > 0) {
const index = res.dataset.index;
this.$set(this.list[index], 'loaded', true);
}
});
}
},
// template中使用
<image
v-for="(item,index) in visibleData"
:src="item.loaded ? item.imgUrl : '/placeholder.png'"
:class="['lazy-img', {loaded: item.loaded}]"
:data-index="index"
/>
三、电商应用实战案例
1. 商品瀑布流列表
// 商品卡片组件优化
components: {
'goods-card': {
props: ['goods'],
template: `
<view class="goods-card">
<image
:src="goods.loaded ? goods.image : '/static/placeholder.png'"
mode="widthFix"
@load="imageLoaded"
/>
<view class="info">
<text class="title">{{goods.title}}</text>
<text class="price">¥{{goods.price}}</text>
</view>
</view>
`,
methods: {
imageLoaded() {
this.$emit('loaded');
}
}
}
},
// 使用动态高度缓存
methods: {
handleImageLoaded(index, colIndex) {
const query = uni.createSelectorQuery().in(this);
query.select(`#item-${index}`).boundingClientRect(res => {
this.$set(this.heightCache, index, res.height);
}).exec();
}
}
四、多端适配最佳实践
- 条件编译:针对不同平台优化布局
- 性能监控:使用uni.reportPerformance记录关键指标
- 内存管理:及时清除不用的观察器
- 图片优化:使用WebP格式和CDN加速
- 调试技巧:使用自定义基座真机调试