jQuery 插件开发基础篇

在前端框架漫天飞舞的时代,作为一个刚入前端坑不久的小白来说真的无所适从啊。。当然自己也在项目里尝试使用了MVVM类的框架,因为感觉数据驱动可以让我少些很多DOM操作的代码,效率提高很大(其实就是我DOM操作用的不熟哈哈哈)。。。嗯嗯偏题了,关于我眼中的前端,会在另一篇好好总结下,这篇主要来学习一下jQuery插件。

很多人都会说用原生js牛逼,用jQuery的多low,然而我并不同意,我觉得应该是js基础很重要,jQuery也是应该好好学习的,并不是一定要用自己造的轮子,jQuery是好好的轮子放在那里让我们学习和使用,不仅提高我们效率也让我们从中学习到很多处理问题的思路和想法,何乐而不为?还有最近很多jQuery要死,MVVM永生的论调我也是不同意的,在原生js没有提供很好的DOM操作标准之前,jQuery还是将长期存在的,MVVM减少了我们的DOM操作并不代表我们不需要DOM操作(MVVM主要减少的是数据类的DOM操作,其他表现类的操作还是它不擅长的,所以两者结合起来有何不可,虽然有人说不伦不类,但是新事物不一定非要替代旧事物,而应该是各取所长嘛。。个人之见咯)好啦。。又扯淡多了。。切入正题。

为什么突然想到研读一下这个问题呢,因为我还真没写过插件。。可能写过也不算不上哈哈哈。。确定目标后然后我就开始百度谷歌的一通乱搞,发现每个人都有每个人的写法和理由,一时间脑子里乱乱的,哎~突然想到与其太混乱还不如去官网看看官方推荐的写法应该是靠谱的哈哈,写法先了解一种嘛,体会个中思想才是重要的。

jQuery Object Method
$("a").css("color", "red");

先来了解一个概念,用$选择的元素都会返回一个jq的对象,这个对象会包含所有的你经常用的方法(例如.css()啊 .click*)()啊什么的)。在jq内部jq对象是通过$.fn对象去得到这些方法的,所以呢如果想要我们自己写的方法能在jq对象上使用,恩啊,让我们把方法添加到==$.fn==对象上呗。

基础插件编写

一个简单的让链接变绿色的插件,看起来挺简单,是不是没什么特别的,恩不着急一点一点往下优化。

$.fn.greenify = function() {
    this.css( "color", "green" );
    console.log(this instanceof jQuery);//true
};
//使用插件
$( "a" ).greenify();

注意这里用的this不是$(this), 因为.greenif()和.css()都是相同jq对象的属性。看那个log呗。对于这点儿我还有点儿疑问,就是我用$(this).css()也是可以的感觉没啥区别,为啥呢。。如果我$($(this))呢?也是可以的。。找不到答案,第一次去看jquery源码有些紧张。。哈哈哈

首先

window.jQuery = window.$ = jQuery; 

这句是jq导入到全局变量的一句,所有我们就拥有了$这种能力。然后去找它的构造函数去

jQuery = function( selector, context ) {
  return new jQuery.fn.init(selector, context);
}

//有大段大段的Sizzle。。。表示压力很大

//终于找到这句
jQuery.fn.init = function(selector, context, root) {
   // 处理: $(""), $(null), $(undefined), $(false)
   if ( !selector ) {return this;}
   //处理html string
   if ( typeof selector === "string" ) {}
   // 处理$(DOMElement)
   } else if ( selector.nodeType ) {}
   // 处理$(function)
   else if ( jQuery.isFunction( selector ) ) {}
   
   //这几个都不是。。。。会走到这里面啊
   if (selector.selector !== undefined) {
	this.selector = selector.selector;
        this.context = selector.context;
   }
   return jQuery.makeArray(selector, this);
}

结论就是其实不论你嵌套多少层,造出的jq对象都会和最里层选择的是一样的,因为每次都赋值了一样的值。。。在这里this $(this) $($(this))这些都是对方的copy而已, 内存地址不同,内存里存的东西是一样的....服了自己了不知道说清没。。看它makeArray的实现就知道了吧..就追到这里了。。。

// results is for internal usage only
makeArray: function( arr, results ) {
    var ret = results || [];
        if ( arr != null ) {
	    if ( isArrayLike( Object( arr ) ) ) {
		 jQuery.merge( ret,typeof arr === "string" ? [ arr ] : arr);
	} else {
	    push.call( ret, arr );
        }
    }
    return ret;
},

擦啊。。。又扯远了。。。回来回来。。。

给插件加上链式调用

不多说,代码很常见

$.fn.greenify = function() {
    this.css( "color", "green" );
    return this;
}
$( "a" ).greenify().addClass( "greenified" );

#######给插件添加$保护,防止命名冲突 + 私有变量

(function ( $ ) {
 
    var shade = "#556b2f"; //私有变量外面是访问不到的哦
 
    $.fn.greenify = function() {
        this.css( "color", shade );
        return this;
    };
 
}( jQuery ));
最小化插件插槽

不好的例子

(function( $ ) {
 
    $.fn.openPopup = function() {
        // Open popup code.
    };
 
    $.fn.closePopup = function() {
        // Close popup code.
    };
 
}( jQuery ));

好的例子

(function( $ ) {
 
    $.fn.popup = function( action ) {
 
        if ( action === "open") {
            // Open popup code.
        }
 
        if ( action === "close" ) {
            // Close popup code.
        }
 
    };
 
}( jQuery ));

意思就是说尽量只在$.fn中暴露尽量少的入口,这样可以大大减少你的插件和别人的插件互相覆盖的几率。

用each()方法给插件添加批量处理
$.fn.myNewPlugin = function() {
 
    return this.each(function() {
        // Do something to each element here.
    });
 
};

jq对象包含了很多DOM对象,可以用each方法对它们每个进行特定的处理。

接收options
(function ( $ ) {
 
    $.fn.greenify = function( options ) {
        var settings = $.extend({
            // These are the defaults.
            color: "#556b2f",
            backgroundColor: "white"
        }, options );

        return this.css({
            color: settings.color,
            backgroundColor: settings.backgroundColor
        });
    };

}( jQuery ));

$( "div" ).greenify({
    color: "orange"
});

给你的插件自定义化的能力,这里注意$.extend的用法,合并defaults和options的键值对,options的键值对优先。


这是jq的基本插件官方推荐开发方式,后面还有一篇高级优化开发方式,恩。。。等我下次总结吧(最近新很浮躁,看别人又是react又是rn又是node的,其实不知所措的时候看些基础的东西还是挺好的额。。。毕竟自己基础呵呵哒。。也希望本文虽说是翻译为主,但还是希望能帮到一些人,大家一起进步:))