【JavaScript】前端性能优化-图片懒加载(附源码)
一、效果图如下
上面的效果图,效果需求如下
1、还没加载图片的时候,默认显示加载图片背景图
2、刚开始进入页面,自动加载第一屏幕的图片
3、下拉界面,当一张图片容器完全显露出屏幕,即刻加载图片,替换背景图
4、加载图片的时候,有渐进显示图片效果
二、难点
1)如何Ajax请求数据
2)如何动态将json数据绑定到html中。
3)如何通过对图片的定位计算,触发图片懒加载机制
4)加分项,显示图片时有渐现的过渡动画
三、前期知识点
1)Ajax相关知识,XMLHttpRequest对象,所有现代的浏览器都支持此对象。
2)innerHTML,数据绑定使用字符串拼接的方式
3)HTML DOM getAttribute() 方法,返回自定属性名的属性值(主要是用于返回自定义属性的属性值)
4)图片的 onload事件,当图片的src属性的属性值为正确(即能成功加载图片),才能触发图片的onload事件
四、难点逐一攻破
1)如何Ajax请求数据
分四步走
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 1)首先创建一个Ajax对象
var xhr = new XMLHttpRequest;
// 2)打开我们需要请求的数据的那个文件地址
// URL地址后面加随机数目的:清除每一次请求数据时候(get请求)产生的缓存
// 因为每次访问的地址不一样,样浏览器就不会尝试缓存来自服务器的响应,读取本地缓存的数据。
xhr.open('get', 'json/newsList.txt?' + Math.random(), false); // false代表同步
// 3)监听请求的状态
xhr.onreadystatechange = function () {
if (xhr.readyState === 4 && /^2\d{2}$/.test(xhr.status)) {
var val = xhr.responseText;
jsonData = utils.jsonParse(val);
}
}
// 4)发送请求
xhr.send(null);
2)如何动态将json数据绑定到html中。
字符串拼接的方式(数据绑定中最常用的方式),即通过使用innerHTML,对页面元素进行字符串拼接,再重新渲染到页面中
1
2
3
4
5
6
7
8
9
10
11
12
13
var str = "";
if (jsonData) {
for (var i = 0, len = jsonData.length; i < len; i++) {
var curData = jsonData[i];
str += '';
str += '
';
str += '';
str += '
';
}
news.innerHTML += str;
}
优势:数据绑定最常用的方式,因为浏览器只需要渲染一次(所有模板引擎数据绑定的原理就是字符串拼接,vue、angular、jade、kTemplate.js等等)
事先把内容拼接好,最后统一添加到页面中,只引发一次回流
弊端:我们把新凭借的字符串添加到#ul1中,原有的三个li的鼠标滑过效果都消失了(原来标签绑定的事件都消失了)
原来,oUl.innerHTML的作用是把原来的标签以字符串的方式取出,原来作为标签的时候,对应事件绑定的东西已经没有了,然后进行字符串拼接,
但是,拼接完成之后,还是字符串!最后再把字符串统一添加到页面中,浏览器还需要把字符串渲染成为对应的标签
3)如何通过对图片的定位计算,触发图片懒加载机制(最关键点)
思路:
A:代表图片距离屏幕顶部的距离
1
2
//这里使用了utils工具类中的offset方法,具体实现看下面源码
var A = utils.offset(curImgPar).offsetTop + curImgPar.offsetHeight;
B:代表一屏幕距离+滚动条滚动距离
1
2
//这里使用了utils工具类中的win方法,具体实现看下面源码
var B = utils.win("clientHeight") + utils.win("scrollTop");
当A < B的时候,此时懒加载的默认图片才能完整显示出来,这个时候就需要触发图片懒加载
4)加载图片的时候,有渐进显示图片效果
思路,利用window.setInterval 方法,通过对当前图片的透明度属性(curImg.style.opacity) 从透明0开始到透明度1,变化总时间为500ms即可
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// ->实现渐现效果
function fadeIn(curImg) {
var duration = 500, // 总时间
interval = 10, //10ms走一次
target = 1; //总距离是1
var step = (target / duration) * interval; //每一步的步长
var timer = window.setInterval(function () {
var curOp = utils.getCss2SS(curImg, "opacity");
if (curOp >= 1) {
curImg.style.opacity = 1;
window.clearInterval(timer);
return
}
curOp += step;
curImg.style.opacity = curOp;
}, interval);
}
五、完整代码
实现懒加载只需要下面3个文件即可,需要请自行拷贝
1)main.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
' + curData["title"] + '
'; str += '' + curData["desc"] + '
'; str += '