天猫首页迷思之-jquery实现整个div的懒加载(2)-插件面向对象化-闭包和原型的实例

前文有简单的实现了一个制作懒加载的方法,但其实以方法的形式做插件扩展性不强。那么本文就来用面向对象的方法将其制作成一个真正的插件:

我想要的最终的调用效果是:

1 $(".loading").lazyLoadDiv_cc({
2      //自定义效果,可不填
3     "beginHeight":400,
4     "loadingBgClass":"loading",
5     "whenToLoad":"someIn"
6 });

分析一下,需要扩展jquery的实例如:$(".loading")的方法。插件肯定要用到$这个方法。所以初步原型是:

1 ;(function($){
2     $.fn.lazyLoad=function(this,options){
3          //处理代码
4     };
5   })(jQuery);

你可能会问的问题:

  • 为什么前面加封号? 答:防止该插件之前的代码忘记加封号。影响代码解析;
  • 为什么使用匿名函数?答:写js的一个原则是尽量不要污染全局变量。插件如果足够庞大,肯定把所有属性和方法都暴露给全局。由于js中没有语句的块级作用域,所以这里使用立即执行的匿名函数。将不需要暴露给全局,但是插件的逻辑要用到得部分代码放到函数的局部作用域中。这样就不会和其他的插件命名冲突啦。
  • 为什么参数要传jQuery?答:这里其实不传也不会报错,但是为了保证代码的独立性,传一下其实更保险。类似window,document这种都可以传进来。

tips:这里见缝插针,说下jquery和jquery的原型。

  1.$是什么?

  从jquery源码开始分析:

      第一次出现jQuery:

  

  由图得知,jquery是一个函数。函数的入参是selector和context,返回一个实例。

  So,$("#div2")是一个实例,拥有很多方法,方法大部分在jQuery原型里面。

 

  暴露给全局变量:

        

  可知$和jQuery其实是同一个函数。

  

  2.$.fn是什么?

  源码中:

jQuery.fn = jQuery.prototype=$.fn

  所以它是jQuery和$对象的原型。在它里面添加方法相当于$的实例(如$("#div1"))都能调用到。

---------------------------------------------我是一个分割线-------------------------------------------

言归正传,初步的模型并没有用到面向对象的特性。当插件越来越庞大时,面向过程就会变得逻辑混乱,难于管理,难于扩展。so。咱们再改一下

 1 ;(function($){
 2     var lazyloadPlugin=function(ele,opt){
 3         this.elements=ele?ele:$(".loading"),//若没有第一个参数,默认获取class为loading的元素
 4         this.defaults={
 5             //参数的默认值
 6             "beginHeight":0,
 7             "howToLoad":"fadeIn",
 8             "loadingBgClass":"loading",//定义未加载前背景图片的类名
 9             "whenToLoad":"allIn"//默认为div全部在可视窗口内开始加载;其他值:“someIn”
10         },
11         this.options=$.extend({},this.defaults,opt)
12     };
13     lazyloadPlugin.prototype={
14         bindLazy:function(){
15          //实现代码
16         }
17     };
18     //以上相当于MVC中的模型层,不需要关心逻辑怎么串起来
19     $.fn.lazyLoadDiv_cc=function(options){
20                //相当于MVC中的业务逻辑层,需要组织逻辑
21         var llp=new lazyloadPlugin(this,options);
22         return llp.bindLazy();
23     };
24 })(jQuery);
lazyloadPlugin是定义在匿名函数中的对象,除了调用lazyLoadDiv_cc方法,并没有其他方式可以使用它。因此它的各种属性和方法都很安全。特别是它的原型,因为实例没有办法改变原型,所以原型中的方法是不可修改的,很安全。
通过这一层封装,我们只暴露出来了一个看似简单的方法。却实现了可扩展、独立性强、保证性能的方法。
1.可扩展性。
  通过options入参,可以实现不同用户的需求。例如options中的whenToLoad字段,可以通过定义不同的值,让插件在不同的位置触发懒加载。
同时,options在构造函数中定义了默认值。更健壮。
2.独立性强
  将大部分属性封装起来,通过匿名函数+闭包,让代码更简洁安全
3.保证性能
  根据共享的放在原型中,不共享的放在构造函数中这一原则。将默认值都放在对象的构造函数中,而方法的实现放在原型中。方法部分的内存共享,提高性能。

只是一个简单的例子,就用到了原型、闭包、this、匿名函数等多个知识点,多多实践比只看书真的好多啦。
实现逻辑之后,网上有在线压缩工具。所谓压缩,只是把变量语义化的名字名字改为更短的,多行也改为了一行,文件体积确实是压缩了,但是逻辑一点也没少哦。
本次插件地址:
压缩后-https://github.com/HappyBangs/bang_plugins/blob/master/plugin_TmallLazyLoad/version2.0/lazyload_pcc.min.js
   压缩前-https://github.com/HappyBangs/bang_plugins/blob/master/plugin_TmallLazyLoad/version2.0/lazyload_pcc.js

 

posted @ 2015-08-17 01:47  石沉溪涧  阅读(2314)  评论(3编辑  收藏  举报