0%

angular实现图片预加载指令

预加载图片是提高用户体验的一种很好的方法。用户不用去等待图片的记载完成,界面也不会因为图片没有加载好而显得很杂乱。

预加载图片的实现思路

当页面加载好后,用JavaScript的Image对象来加载图片,家在之前可以给个图片站位或者用友好的提示告诉用户这个图片正在加载,等图片加载好后展示给用户。

Image 对象

Image是一个浏览器的原生构造函数。返回一个HTMLImageElement对象的实例,即Image标签的实例。

Image.src属性对应<img>节点的src属性,即图像的来源。可以看到,设置Imagesrc属性的时候就已经请求对应的路径的文件了。

新生成的Image实例并不属于文档的一部分。如果需要让它显示在文档中,需要插入文档

1
2
3
var image = new Image();
image.src = 'imgurl';
document.body.append(image);

Image.complete属性返回该图片是否已经下载过并缓存在浏览器中。已下载返回false,节省资源,防止重新下载。

Image对象提供了三个事件句柄以控制图片的加载:

  • onabort 当用户放弃图像装载时调用;
  • onload 当图像装载完毕时调用;
  • onerror 在图像装载过程中发生错误时调用;

代码实现

angular代码:

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
'use strict';

angular.module('myApp').directive('imgLoading', ['$timeout', function($timeout){
return {
restrict: 'AE',
scope: {
imgList: '@',
},
link: function(scope, element, attrs) {
// 获得图片的url
console.log(scope.imgList);
var imgUrl = attrs.imgUrl;
// 创建容器进行预加载
var img = new Image();
img.src = imgUrl;
// 先判断是否已经加载过这个图片,有缓存的话,直接使用
if (img.complete) {
// 是否已经加载过了
element.css({
'background': 'url(' + imgUrl + ') no-repeat center center fixed',
});
return;
}
// 进行预加载先给个样式
element.addClass('bg-grayc');
// 加载完成时的处理
img.onload = function(data){
$timeout(function() {
// 图片加载成功,先移去预提供的样式,然后让图片显示
element.removeClass('bg-grayc');
element.css({
'background': 'url(' + imgUrl + ') no-repeat center center fixed',
});
});
};
// 加载出错时的处理
img.onerror = function(data){
console.log('error');
}
}
}
}]);

HTML中使用指令:

1
<div class='testimg' img-loading="" img-url="http://www.tcs-y.com/princess/img/lover1.jpg" img-list="[1,2,3]">test</div>

回顾angular指令

angular指令

对于指令,可以理解为在特定DOM元素上运行的函数,指令可以扩展这个元素的功能。

directive()方法来定义指令。接收两个参数:

  • name 指令的名字
  • factory_function 这个函数返回一个函数,定义了指令的全部行为。$compile服务利用这个方法返回对象,在DOM调用指令的时候来构造指令的行为。这个函数通常被称作为链接传递函数,利用它我们可以定义指令的链接(link)功能。

当angular应用启动时,它会把第一个参数当做一个字符串并以这个字符串为名来注册第二个参数返回的对象。angularJS编译器会解析主HTML的DOM中的元素、属性、注释和css类名中使用了这个名字的地方,并在这些地方引用对应的指令。当它找到某个已知的指令时,就会在页面中插入指令所对应的DOM元素。

指令的生命周期开始于$compile方法并结束于link方法。

restrict 属性

restrict (约定)是一个可选的参数。定义指令在DOM中以何种形式被声明。默认为A。可选的值:

  • E 元素,声明形式:<my-directive></my-directive>;
  • A 属性,声明形式:<div my-directive=""></div>
  • C 类名,声明形式:<div class='my-directive'></div>
  • M 注释,声明形式:<!--directive:my-directive-->

省去其他部分属性,这里关注link方法

用link函数创建可以操作DOM的指令。链接函数会在模板编译并同作用于进行链接后被调用,因此它负责设置事件监听器,监视数据变化和实时的操作DOM。

链接函数的签名:

1
2
3
link: function(scope, element, attrs) {
// 这里操作DOM
}

链接函数中的参数解析:

scope

指令用来在其内部注册监听器的作用域。用scope属性声明变量

element

element参数代表实例元素,指使用此指令的元素

attrs

attrs参数代表实例属性,是一个由定义在元素上的属性组成的标准化列表,可以在所有指令的链接函数间共享。
注意:用attrs的时候,在html中的属性应该是以下划线的形式,在attrs使用的就是驼峰形式,用scope获取到的和attrs获取到的是一样的。

码字辛苦,打赏个咖啡☕️可好?💘