angular懒加载模块me-lazyload.js使用方法详解

来源:互联网 发布:oracle update sql语句 编辑:程序博客网 时间:2024/06/07 05:26
angular框架使用起来是非常方便的,是典型的mvc框架。而me-lazyload.js是为了angular而开发的一款图片懒加载模块。
me-lazyload的原理是通过自定义的指令,生成一个属性类的自定义指令,在img标签上加入这个自定义指令获取到绑定的图片链接地址。然后,监听容器的滚动事件,当承载自定义属性的标签进入视窗时,将会自动往img标签上添加src属性并赋值。这样就实现了懒加载性质。使用起来非常方便,不过第一次用的时候也是碰到了很多问题。

其中,最令人费解的问题是当我做SPA(单页面webapp)时,切换路由,懒加载会失效。多页面没有这个问题。

下面,我会在讲解使用方法的过程中叙述产生原因和解决办法。
首先,我们需要引入me-lazyload.js文件(不管是通过script引入还是require引入都可以),然后在angular.module()的依赖里面写入‘me-lazyload’的依赖名。如下面的例子:这个是reqirue的写法。


01define(['uiRouter','jquery','speColumn','lazyload'], function() {
02    var categoryApp = angular.module('categoryModule', ['ui.router','speColumnModule','me-lazyload'])
03        .config(function($stateProvider, $urlRouterProvider) {
04            $stateProvider.state('category', {
05                url: '/category',
06                templateUrl: 'component/wrap/category/category.html',
07                css: 'component/wrap/category/category.css',
08                controller: 'categoryCtrl'
09            });
10        })

接着要在html文件中,需要懒加载的图片上使用 lazy-src 替代 原有的src属性

1<div class="clear">
2                <a href="" class="fl" ng-repeat="value in categoryList" ng-click="jump2column(value)">
3                <img lazy-src="{{value.image}}"alt="" />
4                <p>{{value.title}}</p>
5                </a>
6            </div>

最后还要在me-lazyload.js文件中加入需要监听的DOM元素。

1angular.element(document.querySelectorAll('.lazyLoadContainer')).bind('scroll', checkImage);

这里我要重点说下DOM元素滚动事件绑定。
在me-lazyload.js里面本身是自带window的滚动和resize事件监听的,但是我们在SPA中一般都是没办法触发这个事件的。
所以只能自己手动绑定目标元素的滚动事件。比如,你的SPA路由里的顶级父元素。
还有,上面绑定监听事件中使用的angular.element()方法是angular自带的jqLite方法,可以将DOM元素转变成jquery对象,但是只能使用jquery的部分方法比如绑定事件的bind()。
另外,绑定的checkImage函数,是me-lazyload.js封装好的函数,目的是检测懒加载目标与窗口的位置关系,并实现src的赋值。

document.querySelectorAll()这个方法就不用多说了,是JS原生的通过选择器获取DOM对象的方法。
现在,我要分享一下前面说道的SPA过程中,切换路由懒加载失效的原理和解决方案。
一般在PC项目中,我们习惯将最后一步,给DOM对象绑定事件放在return前面。
例如:

1angular.element(document.querySelectorAll('.lazyLoadContainer')).bind('scroll', checkImage);
2  return {
3      restrict: 'A',
4      scope: {
5          lazySrc: '@',
6          animateVisible: '@',
7          animateSpeed: '@'
8      },
9      link: function($scope, iElement){

这样当,JS文件引入后,自定义指令就会自动执行。事件就已经绑定在了目标元素身上。
在PC页面,也就是多页面时,每次切换页面都会重新加载JS文件,自定义指令都会重新执行,这样目标元素都会很自然的被绑定事件。
但是,在SPA也就是单页面应用中,是无法实现的。因为,不管怎么引入JS文件,由于是单页面的缘故,JS里的自定义指令只能执行一次。也就是当JS文件引入时,这个滚动事件只能绑定到当前页面上的指定元素上,当我们切换路由之后,当前的DOM被取代,就算都有同样的类名,依然无法促发me-lazyload.js的执行,因为js文件没有第二次执行。所以,这就是非常尴尬的事情。JS不执行,那么无法重新获取对象绑定事件,懒加载就无法实现。另外,当我切换回原来的路由之后,依然无法触发懒加载,这又是什么原因呢?我想原因是,虽然切换之前,目标元素已经被获取并绑定了事件。但是当我们切换出去后,该DOM元素是被destroy了,所以它的所有属性和事件都被移除掉了。而当我们重新切换回来后,他并没有再次促发绑定事件,也就没有办法执行懒加载了。

解决办法其实也很简单,只需要将绑定事件的位置换个地方就可以了。

01return {
02        restrict: 'A',
03        scope: {
04            lazySrc: '@',
05            animateVisible: '@',
06            animateSpeed: '@'
07        },
08        link: function($scope, iElement){
09           angular.element(document.querySelectorAll('.lazyLoadContainer'))
10             .bind('scroll', checkImage);
11            iElement.bind('load', onLoad);

也就是在link里面对目标元素进行事件绑定
这里的link是当自定义指令加载后,这里自定义的是属性,所以,可以理解为,当带有自定义属性‘lazy-src’的DOM元素加载时,就会自动执行link里的函数。试想,我们每次切换路由,是不是DOM都是重新加载?这样link里的函数也会反复被执行。这样每次切换都会重新获取目标元素,并为其绑定滚动事件了。
阅读全文
0 0
原创粉丝点击