赞
踩
由于常用的getBoundingClientRect()会导致页面重排和滚动事件频发触发,所以本文介绍的是使用IntersectionObserver对象实现图片懒加载效果;并在显示图片前增加骨架屏来提高体验。
Tips:
骨架屏是页面的一个空白版本,通常会在页面完全渲染之前,通过一些灰色的区块大致勾勒出轮廓,待数据加载完成后,再替换成真实的内容;
懒加载简单说就是在渲染页面时,不在视图范围内的不加载,只有元素出现在视图范围内了再渲染。
效果如下:
一、懒加载功能
1. 文件imgsList.wxml和imgsList.wxss代码如下,这一块比较简单,可自行查看,不做过多分析;
- <view class="imgs-box">
- <block wx:for="{{imgs}}" wx:key="id">
- <image class="img-{{index}}" src="{{item.showState? item.src: ''}}"></image>
- </block>
- </view>
- .imgs-box image {
- width: 100%;
- height: 500rpx;
- }
2. 文件imgsList.js存放所有功能的逻辑代码,代码实现如下:
页面加载时(onLoad),遍历所有图片数据(imgs),只要intersectionRatio大于0(即该图片元素出现在视图中),就局部setData该图片数据显示。
- Page({
- /**
- * 页面的初始数据
- */
- data: {
- imgs: [{
- id: 0,
- src: '../../upload/1.jpg',
- showState: false
- },
- {
- id: 1,
- src: '../../upload/2.jpg',
- showState: false
- },
- {
- id: 2,
- src: '../../upload/3.jpg',
- showState: false
- },
- {
- id: 3,
- src: '../../upload/4.jpg',
- showState: false
- },
- {
- id: 4,
- src: '../../upload/5.jpg',
- showState: false
- },
- {
- id: 5,
- src: '../../upload/6.jpg',
- showState: false
- },
- {
- id: 6,
- src: '../../upload/7.jpg',
- showState: false
- },
- {
- id: 7,
- src: '../../upload/8.jpg',
- showState: false
- },
- {
- id: 8,
- src: '../../upload/9.jpg',
- showState: false
- },
- {
- id: 9,
- src: '../../upload/10.jpg',
- showState: false
- }
- ]
- },
-
- /**
- * 生命周期函数--监听页面加载
- */
- onLoad: function (options) {
- let data = this.data.imgs;
- let that = this;
- data.forEach((item, index) => {
- const viewPort = wx.createIntersectionObserver().relativeToViewport();
- viewPort.observe(`.img-${index}`,res=>{
- if (res.intersectionRatio > 0){
- let keyStr = `imgs[${index}].showState`;
- that.setData({
- [keyStr]: true
- })
- }
- })
- })
- }
- })
二、骨架屏
利用微信小程序开发工具自动生成骨架屏代码的能力来实现功能。
1)如上图,点击模拟器面板右下角三点处;
2)点击生成骨架屏,将有弹窗提示是否允许插入骨架屏代码。确定后将在当前页面同级目录下生成imgsList.skeleton.wxml
和 imgsList.skeleton.wxss
两个文件,分别为骨架屏代码的模板和样式;
3)imgsList.wxml引入骨架屏模板,并增加hideContainer判断内容的隐藏和显示;
- <!-- 引入骨架屏 -->
- <import src="imgsList.skeleton.wxml"/>
- <template is="skeleton" wx-if="{{loading}}" data="{{hideContainer}}" />
-
- <view class="imgs-box" data-skeleton-hide="hideContainer" hidden="{{!hideContainer}}">
- <block wx:for="{{imgs}}" wx:key="id">
- <image class="img-{{index}}" src="{{item.showState? item.src: ''}}"></image>
- </block>
- </view>
4)imgsList.wxss引入骨架屏样式;
- @import "./imgsList.skeleton.wxss";
-
- .imgs-box image {
- width: 100%;
- height: 500rpx;
- }
5)imgsList.js增加参数loading和hideContainer;
- Page({
- /**
- * 页面的初始数据
- */
- data: {
- loading: true,
- hideContainer: false,
- imgs: [{
- id: 0,
- src: '../../upload/1.jpg',
- showState: false
- },
- {
- id: 1,
- src: '../../upload/2.jpg',
- showState: false
- },
- {
- id: 2,
- src: '../../upload/3.jpg',
- showState: false
- },
- {
- id: 3,
- src: '../../upload/4.jpg',
- showState: false
- },
- {
- id: 4,
- src: '../../upload/5.jpg',
- showState: false
- },
- {
- id: 5,
- src: '../../upload/6.jpg',
- showState: false
- },
- {
- id: 6,
- src: '../../upload/7.jpg',
- showState: false
- },
- {
- id: 7,
- src: '../../upload/8.jpg',
- showState: false
- },
- {
- id: 8,
- src: '../../upload/9.jpg',
- showState: false
- },
- {
- id: 9,
- src: '../../upload/10.jpg',
- showState: false
- }
- ]
- },
-
- /**
- * 生命周期函数--监听页面加载
- */
- onLoad: function (options) {
- let data = this.data.imgs;
- let that = this;
- data.forEach((item, index) => {
- const viewPort = wx.createIntersectionObserver().relativeToViewport();
- viewPort.observe(`.img-${index}`,res=>{
- if (res.intersectionRatio > 0){
- let keyStr = `imgs[${index}].showState`;
- that.setData({
- [keyStr]: true,
- loading: false,
- hideContainer: true
- })
- }
- })
- })
- }
- })
6)生成的imgsList.skeleton.wxml添加hidden="{{hideContainer}}",用来判断骨架屏的显示和隐藏;
- <!--
- 使用方法:
- 在 pages\imgsList\imgsList.wxml 引入模板
- ```
- <import src="imgsList.skeleton.wxml"/>
- <template is="skeleton" wx-if="{{loading}}" />
- ```
- 在 pages\imgsList\imgsList.wxss 中引入样式
- ```
- @import "./imgsList.skeleton.wxss";
- ```
- 更多详细信息可以参考文档:https://developers.weixin.qq.com/miniprogram/dev/devtools/skeleton.html
- -->
- <template name="skeleton">
- <view class="sk-container" hidden="{{hideContainer}}">
- <view class="imgs-box">
- <image class="img-0 sk-image">
- </image>
- <image class="img-1 sk-image">
- </image>
- <image class="img-2 sk-image">
- </image>
- </view>
- <view class="sk-loading-spinner">
- <view class="circular">
- </view>
- </view>
- </view>
- </template>
7)生成的imgsList.skeleton.wxss样式如下:
- /*
- 在 pages\imgsList\imgsList.wxss 中引入样式
- ```
- @import "./imgsList.skeleton.wxss";
- ```
- 更多详细信息可以参考文档:https://developers.weixin.qq.com/miniprogram/dev/devtools/skeleton.html
- */
- .sk-image {
- background: #EFEFEF !important;
- }
- .sk-container {
- background-color: transparent;
- }
-
- @keyframes loading-rotate {
- 100% {
- transform: rotate(360deg);
- }
- }
-
- .sk-loading-spinner {
- position: absolute;
- top: 50%;
- margin-top: -0.5rem;
- width: 100%;
- text-align: center;
- }
-
- .sk-loading-spinner .circular {
- border-radius: 50%;
- width: 1rem;
- height: 1rem;
- display: inline-block;
- box-sizing: border-box;
- border-top: solid 2px #409eff;
- border-right: solid 2px #409eff;
- border-bottom: solid 2px #409eff;
- border-left: solid 2px transparent;
- animation: loading-rotate 1s linear infinite;
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。