微信小程序实现图片预加载组件


Posted in Javascript onJanuary 18, 2017

网页中的图片预加载

图片预加载对图片画廊及图片占据很大比例的网站来说十分有利,它保证了图片快速、无缝地发布,也可帮助用户在浏览你网站内容时获得更好的用户体验。我们知道在 Web 页面中实现图片的预加载其实很简单,通常的做法是在 JS 中使用 Image 对象即可,代码大致如下

var image = new Image()
image.onload = function() {
 console.log('图片加载完成')
}
image.src = 'http://misc.360buyimg.com/lib/img/e/logo-201305.png'

下面推荐几篇网页中实现图片预加载的文章:

     1、jquery 图片预加载 自动等比例缩放插件

     2、JS实现图片预加载无需等待

     3、jQuery简单实现图片预加载

然而在微信小程序(以下简称小程序)里要实现图片的预加载要更麻烦一些,因为小程序里并没有提供类似 Image 这样的 JS 对象。。

小程序必知必会

在进入正题前,需要了解以下小程序相关的知识(当然最好还是完整的学习一下官方文档):

  1. 小程序框架的核心是一个响应的数据绑定系统,整个系统分为视图层和逻辑层两块,视图层即页面模板(后缀为 .wxml 的文件),逻辑层即页面 JS 文件
  2. 小程序的页面模板由一系列的基础组件组合而成,如 view、text、button 等
  3. 页面内容的更新基于数据的单向绑定来进行,通过 JS 调用 Page 对象的 setData 方法来更新模板中绑定的数据
  4. 视图层到逻辑层的通信是通过事件完成的,在组件中声明事件的回调,JS 端可监听到界面交互的发生、组件状态的变化等
  5. 在 WXML 文件中,可通过 template 进行模板的复用,若 template 是在不同文件里定义的,需要先通过 import 语句进行引入

这里有个官方的简单例子可以用来帮助理解

<!-- 模板文件 foo.wxml -->
<view> Hello {{name}}! </view>
<button bindtap="changeName"> Click me! </button>
//脚本文件 foo.js
Page({
 data: {
 name: 'WeChat'
 },
 changeName: function(e) {
 this.setData({
 name: 'MINA'
 })
 }
})

运行这个页面会看到一行 Hello WeChat! 的文字及一个按钮,点击按钮后文字会变成 Hello MINA!

在小程序中加载图片

小程序提供一个 image 组件(类似于 HTML 中的 img 标签),可以设置 src 及加载成功或失败的回调,使用起来很简单

<!-- 模板文件 bar.wxml -->
<image src="http://misc.360buyimg.com/lib/img/e/logo-201305.png" bindload="imageOnLoad" binderror="imageOnLoadError" />
//脚本文件 bar.js
Page({
 imageOnLoad(ev) {
 console.log(`图片加载成功,width: ${ev.detail.width}; height: ${ev.detail.height}`)
 },
 imageOnLoadError() {
 console.log('图片加载失败')
 }
})

运行以上代码,顺利的话页面上会显示出一张图片,同时控制台会打印出带图片宽高的日志信息

将功能抽离成公用组件

接下来我们考虑实现这么一个功能,在页面上载入一张尺寸和 K 数都很大的图片,由于图片很大,下载需要一定的时间,而在这段时间内,用户看到的是空白或是不完整的图片,体验显然不好。

一种常用的优化手段是先加载一张缩略图,该缩略图通过样式设置为和原图一样的宽高,这样用户首先能很快速地看到一张模糊的图片,此时再去对原图做预加载,加载完成之后对缩略图进行替换,因为此时图片已经下载过了,所以界面上能无缝地切换为原图显示,效果如下:

微信小程序实现图片预加载组件

单张图片预加载

完成这个优化操作的关键就在于需要一个公共的图片预加载组件的支持,接下来我们分步骤来看看如何实现

  1. 新建 demo 页面及组件相关的文件 img-loader.js 和 img-loader.wxml,组件需要和页面一样有个模板文件,是因为小程序里无法动态地插入模板结构。然后在 demo.wxml 里通过 import 语句引用组件模板,在 demo.js 里通过 require 语句将组件脚本进行引入
  2. 在页面中通过 template 调用组件模板并传入数据,这里我们传递一个名为 imgLoadList 的图片数组过去
  3. 在页面脚本中的 onLoad 方法中对组件进行初始化,并将 this 对象传入,因为组件内必须通过 Page 对象的 setData 来更新模板里的内容
  4. 在组件的 img-loader.js 中定义一个 load 方法用来创建一个图片的加载,将传入的 src 添加到加载队列中,并使用 setData 方法更新队列数据
  5. 接下来在组件 img-loader.wxml 中通过接收到的图片队列数据,用 wx:for 指令去生成 image 组件来对图片进行加载,同时将成功及失败的回调绑定到 img-loader.js 中的方法中,最终再回调回 Page 对象中

微信小程序实现图片预加载组件

可以看出,由于小程序里无法动态地插入模板结构,所以相对于普通网页端的组件调用,这里多出了在 WXML 文件中引入及使用模板这个步骤,而其他部分对于调用方(即Demo 页面)来说则是相似的,下面是完整的 Demo 页面的代码

<!-- demo.wxml -->
<view class="img_wrap">
 <image wx:if="{{ imgUrl }}" src="{{ imgUrl }}" />
</view>
<button bindtap="loadImage">Click To Load Image</button>
<view class="msg">{{ msg }}</view>
<!-- 引入图片预加载组件 -->
<import src="../../img-loader/img-loader.wxml"/>
<template is="img-loader" data="{{ imgLoadList }}"></template>
// ------ demo.js ------
//引入图片预加载组件
const ImgLoader = require('../../img-loader/img-loader.js')
//缩略图 80x50 3KB
const imgUrlThumbnail = 'http://storage.360buyimg.com/mtd/home/lion1483683731203.jpg'
//原图 3200x2000 1.6MB
const imgUrlOriginal = 'http://storage.360buyimg.com/mtd/home/lion1483624894660.jpg'
Page({
 data: {
 msg: '',
 imgUrl: ''
 },
 onLoad() {
 //初始化图片预加载组件
 this.imgLoader = new ImgLoader(this)
 },
 loadImage() {
 //加载缩略图
 this.setData({
 msg: '大图正拼命加载..',
 imgUrl: imgUrlThumbnail
 })
 //同时对原图进行预加载,加载成功后再替换
 this.imgLoader.load(imgUrlOriginal, (err, data) => {
 console.log('图片加载完成', err, data.src)
 this.setData({ msg: '大图加载完成~' })
 if (!err)
 this.setData({ imgUrl: data.src })
 })
 }
})

如果把图片加载完成的回调统一指定成 Page 对象中的方法,则可以很方便地处理多张图片的加载,这里也写了个例子,效果如下:

微信小程序实现图片预加载组件

多张图片预加载

总的来说调用起来还算方便吧,img-loader 的组件代码略多这里就不贴出来啦,有兴趣的同学可以前往 Github 项目页面 查看,目前此组件已应用在京东购物小程序版中。

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流。

Javascript 相关文章推荐
在jQuery1.5中使用deferred对象 着放大镜看Promise
Mar 12 Javascript
jQuery 在光标定位的地方插入文字的插件
May 10 Javascript
jquery中使用循环下拉菜单示例代码
Sep 24 Javascript
举例讲解如何判断JavaScript中对象的类型
Apr 22 Javascript
javascript实现粘贴qq截图功能(clipboardData)
May 29 Javascript
使用prop解决一个checkbox选中后再次选中失效的问题
Jul 05 Javascript
Vue之Watcher源码解析(1)
Jul 19 Javascript
javascript 作用于作用域链的详解
Sep 27 Javascript
JS实现十字坐标跟随鼠标效果
Dec 25 Javascript
angular4中引入echarts的方法示例
Jan 29 Javascript
vue中uni-app 实现小程序登录注册功能
Oct 12 Javascript
详解JavaScript匿名函数和闭包
Jul 10 Javascript
JavaScript原生节点操作小结
Jan 17 #Javascript
Javascript 两种刷新方法以及区别和适用范围
Jan 17 #Javascript
easyUI combobox实现联动效果
Jan 17 #Javascript
Angularjs实现搜索关键字高亮显示效果
Jan 17 #Javascript
React Router基础使用
Jan 17 #Javascript
JavaScript自定义分页样式
Jan 17 #Javascript
javascript实现页面滚屏效果
Jan 17 #Javascript
You might like
php5 apache 2.2 webservice 创建与配置(java)
2011/01/27 PHP
php微信高级接口群发 多客服
2016/06/23 PHP
highchart数据源纵轴json内的值必须是int(详解)
2017/02/20 PHP
PHP命名空间与自动加载类详解
2018/09/04 PHP
php使用curl模拟浏览器表单上传文件或者图片的方法
2018/11/10 PHP
PHP rsa加密解密算法原理解析
2020/12/09 PHP
javascript与CSS复习(《精通javascript》)
2010/06/29 Javascript
jQuery操作元素css样式的三种方法
2014/06/04 Javascript
JavaScript中各种引用类型的常用操作方法小结
2016/05/05 Javascript
基于BootStrap Metronic开发框架经验小结【一】框架总览及菜单模块的处理
2016/05/12 Javascript
jquery 遍历数组 each 方法详解
2016/05/25 Javascript
解决jQuery ajax请求在IE6中莫名中断的问题
2016/06/20 Javascript
详谈JS中实现种子随机数及作用
2016/07/19 Javascript
JS简单实现tab切换效果的多窗口显示功能
2016/09/07 Javascript
用js控件div的滚动条,让它在内容更新时自动滚到底部的实现方法
2016/10/27 Javascript
jQuery实现的简单排序功能示例【冒泡排序】
2017/01/13 Javascript
jQuery Mobile漏洞会有跨站脚本攻击风险
2017/02/12 Javascript
AngularJS实现的JSONP跨域访问数据传输功能详解
2017/07/20 Javascript
vue中使用带隐藏文本信息的图片、图片水印的方法
2020/04/24 Javascript
微信小程序实现上传照片代码实例解析
2020/08/04 Javascript
使用jquery实现轮播图效果
2021/01/02 jQuery
[38:21]2014 DOTA2国际邀请赛中国区预选赛5.21 TongFu VS LGD-CDEC
2014/05/22 DOTA
使用C语言来扩展Python程序和Zope服务器的教程
2015/04/14 Python
详解字典树Trie结构及其Python代码实现
2016/06/03 Python
Python函数装饰器实现方法详解
2018/12/22 Python
python3使用print打印带颜色的字符串代码实例
2019/08/22 Python
Python爬取微信小程序通用方法代码实例详解
2020/09/29 Python
String这个类型的class为何定义成final?
2012/11/13 面试题
团结演讲稿范文
2014/05/23 职场文书
二手车转让协议书
2015/01/29 职场文书
2015年房产经纪人工作总结
2015/05/15 职场文书
军训后的感想
2015/08/07 职场文书
2019财务管理制度最新范本!
2019/07/09 职场文书
使用Vue3+Vant组件实现App搜索历史记录功能(示例代码)
2021/06/09 Vue.js
MySQL中一条update语句是如何执行的
2022/03/16 MySQL
Python实现提取PDF简历信息并存入Excel
2022/04/02 Python