Jquery插件编写教程完整

10.gif

描述

本人是从事前端一年的工作的小白,也想拥有自己的博客,便于自己可以记录学习的过程,同时可以把方法和技巧分享给大家,由于本人能力有限,也是一直在前端领域学习中,所以如果有不对的地方还请大家指点,与大家共进步。
最近一直想学习插件编写的方法,(注:不管是js插件编写还是jq的插件编写都需要有一定的js知识面)。从网上找了很多例子学习,但是都不是很理解插件编写的思想是什么。于是,本人意识到是我js知识还不够。于是继续读了javaScript高级程序设计这本书,学习了原型与原型链,this的作用,以及面向对象设计思想。在学习原型与原型链的时候,我从网上找了很多学习资源。本人认为原型与原型链是javaScript这本语言的精髓,同时javaScript也沿用了流行的面向程序设计。强调!!!要好好吃透。这是本人第一次写博客,如果哪里不好还请大家指正,如果大家喜欢对大家的工作或者学习有帮助请大家支持一下我,以后慢慢的也会书写更多的教程与大家一起分享。

阶段

接下来就给大家推荐一下学习Jquery插件编写的方法与过程:

阶段1.学习javaScript的原型与原型链以及面向程序设计思想

百度前端技术学院javaScript教程-------(第四十二天到第四十三天:开一家餐厅吧(一)---- 第五十天到第五十三天:开一家餐厅吧(四))
这是学习原型原型链与面向程序设计的资源,大家要可以好好研究。若大家有更好的资源可以在评论中推荐。这一阶段是给想提高js认知的朋友推荐的,如果有的人已经掌握直接看阶段2

阶段2.学习Jquery插件的编写

在这一阶段,我会一步一步的教大家如何进行插件的编写。本人自己写了一个Out.js 这个插件的效果是页面文字可以像键盘输入文字一样输 出,和按BackSpace键的效果。如下图:

2.1JQuery插件开发模式

在这一节我们先通过一些简单的例子去学习jQuery插件开发的主要三中方式:1.通过.extend()来扩展JQuery2.通过.fn向JQuery挂载方法,这种方式后期应用的时候可以直接(div).方法直接调用,3.通过.widget()应用JQuery UI的部分工厂方式创建

2.1.1.通过$.extend()方式编写

首先我们通过$.extend()方式编写,运行结果我就不截图了可以直接复制代码自己运行一下。

$.extend({

    sayBay:function(name){

        console.log('Bay,'+(name ? name : 'Dude'))

    }

});

$.sayBay();//不传参

$.sayBay('Demo');//传参

以上就是一个最简单的JQuery插件。但这种编写方式无法利用JQuery强有力的选择器带来便利,所以大多情况大家会用第二种来开发自己的插件。

2.1.2.通过$.fn向JQuery挂载方法

最简单的方法如下

$.fn.out = function(options){

    //填写自己的代码

}

这里的.fn其实就是javaScript中的原型与原型链,所以这就是上面为啥让大家去先学习原型与原型链的原因。通过上面的代码挂载到jquery的原型中后,就可以在其他地方通过(元素).out()来实现调用。

注:由于楼主目前只着重学习了第二种插件编写的方法,第三种就不做介绍了。以后有机会学习,在给大家做一个完整的demo,下面就开始自己的插件编写。

2.2 初始化一个Out类

所谓的初始化一个Out类无非就是声明一个函数名字叫Out,注这个函数是声明在$.fn.out方法之外的

可以这样声明
var Out = function(el,opt){};

有可以声明,都是javaScript中对象的声明方式

function Out(el,opt){}

这里先不说两个参数el,opt,后面用到的时候我在给大家解释

2.3 将Out类声明到$.fn.out函数中

在out中声明完之后,插件的整体架构就打好了,就可以在元素上像调用jquery本身有的方法一样去调用out方法,这样配置好之后,我们所要编写的业务逻辑代码都写在Out这个类中就可以了。
$.fn.out = function(el,opt){ new Out(el,opt);//实例化Out类}

2.4 Out类中常见的配置项

像上面图片中那样文字输出与回退。在Out类中都是有配置的

var Out = function(el,opt){

    this.$element = el;

    this.defaults = {

        //输出字符串,默认字符串

        outStr:['my name is Post-90s!','the blog is my first project based on line!','I love my blog as I like my life!'] };

};

在Out类中,this值的就是Out,所以在Out中我们可以通过this.detaults在声明一个变量在这个变量中我们给其一个默认的需要输出的字符串数组。这个this.defaults是我们自己声明的,它的作用就是在Out类初始化的时候给这个类进行一个默认值的配置。在这个类中我们可以定义很多属性,像是否无限循环的loop,输出与回退的速度。这都是后期我们可以扩展出来的。

插件既然有默认配置,那么也就可以通过调用out方法的时候给其进行动态的配置,这里通过用.extend()方法将this.defaults与opt合并到一个空对象{}中,在接下来的操作只调用this.options里面的属性就可以 ```this.options =.extend({},this.defaults,opt);```
通过三元运算符进行赋值。在其他时候,如果我们需要用到什么属性就可以直接this.属性名 = 属性值;这样运用,如果这个属性可以进行动态配置那么就可以写在defaults这个属性里面然后在进行三元算符的合并。

整理以上代码
var Out = function(el,opt){

    this.$element = el;

    this.defaults = {

        //输出字符串,默认字符串

        outStr:['my name is Post-90s!','the blog is my first project based on line!','I love my blog as I like my life!'] };

        this.options = $.extend({},this.defaults,opt);

        this.contentStr = this.options.outStr?this.options.outStr:this.defaults.outStr;

}

注:这里的el是指在外部调用out()的时候上下文

2.4 将实现的逻辑部分通过函数挂到Out类的原型上

Out.prototype = {

//初始化函数

init:function(){

}

//输出函数

outContent:function(){

}

//回退函数

backContent:function(){

}

}

在初始化的函数init()中我们可以给其进行初始化的操作,将init()方法在Out函数中通过this.init()调用这样在声明实体类的时候就自动调用了这个函数。

在outContent()与backContent()两个方法中就是实现文字回退与输出的效果,在这两个函数中,通过定时器setInterval来实现的。具体的逻辑我就不在一一多说直接上代码,然后将上面所讲的代码整理好如下

代码整理好如下

(function($,window,document,undefined){

var Out = function(el,opt){

  this.$element = el;

  this.defaults = {

      //输出字符串,默认字符串

       outStr:['my name is Post-90s!','the blog is my first project based on line!','I love my blog as I like my life!'] };

    this.options = $.extend({},this.defaults,opt);

     this.contentStr = this.options.outStr?this.options.outStr:this.defaults.outStr; 

      this.init(this.$element);

    //初始化函数 

}

Out.prototype = {

    //初始化函数

    init:function(el){

    var self = el;

    //把数组的第一组值赋值给span

    var textStr = this.defaults.outStr[0];

    //调用outContent 输出第一组的文字特效

    this.outContent(el,textStr);

    }

    //输出函数

/*** 输出文字     * @param el 调用的元素 * */

   outContent:function(){

var self = el;//初始化文字的时候进行输出//console.log(str.split(''));//将字符安转换为字符数组 var charArr = str.split('');var that = this; clearInterval(self.ouTime);self.ouTime = setInterval(function () { var text = self.text(); if(that.endFlag){ if(that.OutCount < charArr.length){ //后期改为options里面的配置 self.text(text + charArr[that.OutCount]); that.OutCount = that.OutCount + 1; }else{ clearInterval(self.ouTime); that.endFlag = false; that.OutCount = 0; that.backContent(el); } } },this.outSpeed);

    }

    //回退函数

    backContent:function(){

    //初始化

    span var self = el; 

    //保存this的指向

     var that = this; 

    clearInterval(self.timeOut);

     self.timeOut = setInterval(function(){ 

        //当第一次输出与回退文字执行完后,进行判断 做count+1 将outStr[count+1]的值赋值给outContent     

         if(self.text().length == 0){ if(that.count < that.defaults.outStr.length - 1){ //console.log(that.count); that.count = that.count+1; clearInterval(self.timeOut); that.endFlag = true; that.outContent(el,that.defaults.outStr[that.count]); } else{ //判断是否进行循环播放 if(that.loop){ that.count = 0; }else{ //如果不进行循环,则终止定时器 clearInterval(self.timeOut); } } }else{ self.text(self.text().substring(0,self.text().length- 1)); } },this.backSpeed);  



}

}

//挂载到$的原型中,初始化实体类。

 $.fn.out = function(options){ new Out(this,options); }

}(jQuery,window,document)

我们知道JavaScript中无法用花括号方便地创建作用域,但函数却可以形成一个作用域,域内的代码是无法被外界访问的。如果我们将自己的代码放入一个函数中,那么就不会污染全局命名空间,同时不会和别的代码冲突。

如上面我们定义了一个Out全局变量,它会被附到全局的window对象上,为了防止这种事情发生,你或许会说,把所有代码放到jQuery的插件定义代码里面去啊,也就是放到.fn.out里面。这样做倒也是种选择。但会让我们实际跟插件定义有关的代码变得臃肿,而在.fn.out里面我们其实应该更专注于插件的调用,以及如何与jQuery互动。

所以保持原来的代码不变,我们将所有代码用自调用匿名函数包裹。另外还有一个好处就是,自调用匿名函数里面的代码会在第一时间执行,页面准备好过后,上面的代码就将插件准备好了,以方便在后面的代码中使用插件。

目前为止似乎接近完美了。如果再考虑到其他一些因素,比如我们将这段代码放到页面后,前面别人写的代码没有用分号结尾,或者前面的代码将window, undefined等这些系统变量或者关键字修改掉了,正好我们又在自己的代码里面进行了使用,那结果也是不可预测的,这不是 我们想要的。。

将系统变量以参数形式传递到插件内部也是个不错的实践。

当我们这样做之后,window等系统变量在插件内部就有了一个局部的引用,可以提高访问速度,会有些许性能的提升

最后我们得到一个非常安全结构良好的代码,这样我们在最后在页面引入Out.js

在你选择的元素上面直接调用

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,530评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 86,403评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,120评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,770评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,758评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,649评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,021评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,675评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,931评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,659评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,751评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,410评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,004评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,969评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,042评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,493评论 2 343

推荐阅读更多精彩内容