我们在做web的时候都会用到很多jQuery插件,这些插件可以很方便的使用。但对于初学者来说想要修改插件中的一些功能,或者想要自定义插件却不是容易的事情。自己也刚好在学习这部分的知识,这里用一个案例来介绍jQuery插件的使用和写法。

就拿单页导航这个插件来举例吧,one-page-nav写的比较规范代码也比较短。其他jQuery插件大同小异,学会结构和规范之后自己也可以自定义插件,后面也会讲解对该插件功能的改写,从 会使用-》看懂-》改写-》自定义插件有一个循序渐进的过程。

地址:github:https://github.com/davist11/jQuery-One-Page-Nav

原插件内容:

;(function($, window, document, undefined){// our plugin constructorvar OnePageNav = function(elem, options){this.elem = elem;this.$elem = $(elem);this.options = options;this.metadata = this.$elem.data('plugin-options');this.$win = $(window);this.sections = {};this.didScroll = false;this.$doc = $(document);this.docHeight = this.$doc.height();};// the plugin prototypeOnePageNav.prototype = {defaults: {navItems: 'a',currentClass: 'current',changeHash: false,easing: 'swing',filter: '',scrollSpeed: 750,scrollThreshold: 0.5,begin: false,end: false,scrollChange: false},init: function() {// Introduce defaults that can be extended either// globally or using an object literal.this.config = $.extend({}, this.defaults, this.options, this.metadata);this.$nav = this.$elem.find(this.config.navItems);//Filter any links out of the navif(this.config.filter !== '') {this.$nav = this.$nav.filter(this.config.filter);}//Handle clicks on the navthis.$nav.on('click.onePageNav', $.proxy(this.handleClick, this));//Get the section positionsthis.getPositions();//Handle scroll changesthis.bindInterval();//Update the positions on resize toothis.$win.on('resize.onePageNav', $.proxy(this.getPositions, this));return this;},adjustNav: function(self, $parent) {self.$elem.find('.' + self.config.currentClass).removeClass(self.config.currentClass);$parent.addClass(self.config.currentClass);},bindInterval: function() {var self = this;var docHeight;self.$win.on('scroll.onePageNav', function() {self.didScroll = true;});self.t = setInterval(function() {docHeight = self.$doc.height();//If it was scrolledif(self.didScroll) {self.didScroll = false;self.scrollChange();}//If the document height changesif(docHeight !== self.docHeight) {self.docHeight = docHeight;self.getPositions();}}, 250);},getHash: function($link) {return $link.attr('href').split('#')[1];},getPositions: function() {var self = this;var linkHref;var topPos;var $target;self.$nav.each(function() {linkHref = self.getHash($(this));$target = $('#' + linkHref);if($target.length) {topPos = $target.offset().top;self.sections[linkHref] = Math.round(topPos);}});},getSection: function(windowPos) {var returnValue = null;var windowHeight = Math.round(this.$win.height() * this.config.scrollThreshold);for(var section in this.sections) {if((this.sections[section] - windowHeight) < windowPos) {returnValue = section;}}return returnValue;},handleClick: function(e) {var self = this;var $link = $(e.currentTarget);var $parent = $link.parent();var newLoc = '#' + self.getHash($link);if(!$parent.hasClass(self.config.currentClass)) {//Start callbackif(self.config.begin) {self.config.begin();}//Change the highlighted nav itemself.adjustNav(self, $parent);//Removing the auto-adjust on scrollself.unbindInterval();//Scroll to the correct positionself.scrollTo(newLoc, function() {//Do we need to change the hash?if(self.config.changeHash) {window.location.hash = newLoc;}//Add the auto-adjust on scroll back inself.bindInterval();//End callbackif(self.config.end) {self.config.end();}});}e.preventDefault();},scrollChange: function() {var windowTop = this.$win.scrollTop();var position = this.getSection(windowTop);var $parent;//If the position is setif(position !== null) {$parent = this.$elem.find('a[href$="#' + position + '"]').parent();//If it's not already the current sectionif(!$parent.hasClass(this.config.currentClass)) {//Change the highlighted nav itemthis.adjustNav(this, $parent);//If there is a scrollChange callbackif(this.config.scrollChange) {this.config.scrollChange($parent);}}}},scrollTo: function(target, callback) {var offset = $(target).offset().top;$('html, body').animate({scrollTop: offset}, this.config.scrollSpeed, this.config.easing, callback);},unbindInterval: function() {clearInterval(this.t);this.$win.unbind('scroll.onePageNav');}};OnePageNav.defaults = OnePageNav.prototype.defaults;$.fn.onePageNav = function(options) {return this.each(function() {new OnePageNav(this, options).init();});};})( jQuery, window , document );

先来看该插件实现的功能有,接下来再讲它是如何实现的。

1:点击导航栏的某一项,内容导航到相应项。当前项的<li>中增加class="current"。

2:鼠标滚动到相应内容时,导航栏中class="current"会切换。

3:其他功能比如说滚动速度和回调函数等。

插件的封装

我们去掉内容,只看这部分。有很多的括号和参数,最开始看的时候内心是拒绝的,完全不知道这么多括号是干什么的,慢慢学下去会发现还是很有意思的。这里是利用了闭包的特性,既可以避免内部临时变量影响全局空间,又可以在插件内部继续使用$作为jQuery的别名。
为了更好的兼容性,开始有一个分号,否则压缩的时候可能出现问题。首先定义一个匿名函数function(){},然后用括号括起来,最后通过()这个运算符来执行。js是以function为作用域,这样定义了一个自调用匿名函数,全局空间就不能访问其中定义的局部变量了。其中jQuery,window,document作为实参传递给匿名函数,插件内部就可以使用$作为jQuery的别名了。
;(function($, window, document, undefined){//这里放置代码
})( jQuery, window , document );

向jQuery的命名空间添加新的方法

jQuery.fn即$.fn是指jQuery的命名空间,所有的对象方法应当附加到就jQuery.fn对象上。这样写之后外部就可以通过这种方式调用它$('#nav').onePageNav(option)
我们遵循jQuery的规范,插件应该返回一个jQuery对象,以保证插件的可链式操作。假设$('.nav')可能是一个数组,可以通过this.each来遍历所有的元素。这种情况可以用于一个页面有多个导航的时候。
    $.fn.onePageNav = function(options) {return this.each(function() {new OnePageNav(this, options).init();});};

定义OnePageNav对象

这里定义一个对象OnePageNav,在调用插件的时候用new可以创建一个原对象的实例对象。我们注意到参数加了$符号的表示的是jQuery对象,没有加$符号表示的是DOM对象,这是一个 很好的习惯,在使用它们的时候就不需要做DOM对象和jQuery对象之间的转换。

    var OnePageNav = function(elem, options){this.elem = elem;this.$elem = $(elem);this.options = options;this.metadata = this.$elem.data('plugin-options');this.$win = $(window);this.sections = {};this.didScroll = false;this.$doc = $(document);this.docHeight = this.$doc.height();};
 

设置默认参数

所有的插件几乎都会有自己的默认参数,所以在调用的时候即使不传递option也可以,在OnePageNav 的原型中的默认参数如下。
        defaults: {navItems: 'a',               //默认<a>标签currentClass: 'current',     //默认当前标签的样式名changeHash: false,           easing: 'swing',filter: '',                  //标签过滤scrollSpeed: 750,            //速度scrollThreshold: 0.5,        //占面积比begin: false,                //开始回调函数end: false,                  //结束回调函数scrollChange: false          //市场改变的回调函数},

初始化

注意到 $.fn.onePageNav方法中的这句话new OnePageNav(this, options).init(); 调用了OnePageNav的init方法进行初始化,现在来看看初始化都做了什么工作。可以概括为这几部分1、extend 函数用于将一个或多个对象的内容合并到目标对象,把默认设置和自定义设置合并起来。2、将标签进行 过滤 ,比如像下面这样我们要过滤掉最后一个标签,可以在option中加入  filter: ':not(.exception)', 3、给过滤后的标签绑定click方法,点击click可以scroll到对应的内容 。4、获取标签对应内容的位置,并都放在this.sections中 。5、添加一个间隔性触发定时器,目的是为了在滑动鼠标滚轮的时候根据当前显示内容,更改导航标签的class=current。
6、每次窗体大小改变时重新获取标签对应内容的位置。
 <ul id="nav">           <li><a href="#nr">内容一</a></li>           <li><a href="#nt">内容二</a></li>           <li><a href="#ny">内容三</a></li>           <li><a href="#nu">内容四</a></li>           <li><a class="exception" href="#top">返回顶部</a></li>           </ul>
      init: function() {this.config = $.extend({}, this.defaults, this.options, this.metadata);this.$nav = this.$elem.find(this.config.navItems);if(this.config.filter !== '') {this.$nav = this.$nav.filter(this.config.filter);}this.$nav.on('click.onePageNav', $.proxy(this.handleClick, this));this.getPositions();this.bindInterval();this.$win.on('resize.onePageNav', $.proxy(this.getPositions, this));return this;},

功能的实现

其他的方法都是添加到OnePageNav.prototype上的,比较好理解,可以自己看代码。这里特别说一下回调函数。比如说下面这句话,默认值是 begin: false, 
如果调用的时候option设置了
begin: function() {
        //I get fired when the animation is starting
    },
每次单击导航标签的时候就会调用这个方法。如果没有设置begin,自然也不会出问题。
                         if(self.config.begin) {self.config.begin();}

用一个案例介绍jQuery插件的使用和写法相关推荐

  1. 介绍一个不错的jquery插件-cluetip

    有时,要实现对于一篇文章的关键词部分的提示,想实现的效果比如是,当鼠标移动到这个关键词时,弹出相关的一段文字或图片的介绍,这个可以 用jquery的一个插件cluetip, 地址下载是:plugins ...

  2. 一个简单的jQuery插件ajaxfileupload实现ajax上传文件例子

    页面代码: <html>     <!-- 引入相关的js文件,相对路径  -->     <script type="text/javascript" ...

  3. 所谓 jQuery 插件,怎样开发一个 jQuery 插件

    简单来说,所谓 jQuery 插件就是扩展在 jQuery 原型对象上的一个方法.通过扩展 jQuery 对象,每次调用 jQuery 对象的时候,对象里面都包含了我们自己所添加的那个方法. 一般插件 ...

  4. jquery插件介绍(六)

    jQuery Popup Bubble利用jQuery实现当鼠标移到链接上时弹出一个气泡提示框. 查看详细  标签:jQuery jTwitterjTwitter(jQuery Twitter API ...

  5. 50个jQuery插件可将你的网站带到另一个高度

    Web领域一直在发生变化并且其边界在过去的每一天都在发生变化(甚至不能以小时为计),随着其边界的扩展取得了许多新发展.在这些进步之中,开发者的不断工作创造了更大和更好的脚本,这些脚本以插件方式带来更好 ...

  6. stickUp 一个 jQuery 插件

    这是一个简单的jQuery插件,它能让页面目标元素 "固定" 在浏览器窗口的顶部,即便页面在滚动,目标元素仍然能出现在设定的位置.此插件可以在多页面的网站上工作,也能在单页面上面实 ...

  7. 教你开发jQuery插件(转)

    教你开发jQuery插件(转) 阅读目录 基本方法 支持链式调用 让插件接收参数 面向对象的插件开发 关于命名空间 关于变量定义及命名 压缩的好处 工具 GitHub Service Hook 原文: ...

  8. 100个优秀jQuery插件精选

    100个优秀jQuery插件精选 在2012年里出现了很多很棒的jQuery插件,如结合CSS3的jQuery动画.强大的支持多设备浏览的响应性布局设计.使用视频作为网页设计背景.jQuery图像幻灯 ...

  9. 自己动手丰衣足食之征服jQuery插件编写

    原文地址:http://www.cnblogs.com/Wayou/p/jquery_plugin_tutorial.html 要说jQuery 最成功的地方,我认为是它的可扩展性吸引了众多开发者为其 ...

最新文章

  1. C++程序设计(第二版)谭浩强----程序题课后习题答案第二章
  2. 常见的一些功能测试用例
  3. linux 用户创建、管理、权限分配
  4. 论文浅尝 | BERT:Pre-training of Deep Bidirectional Transformers
  5. 多项新政催生本年度购房最佳“窗口期”
  6. 全面解析Linux 内核 3.10.x - 如何开始
  7. c++文件内容与输入内容进行比较_使用位运算对数据或文件内容进行加密
  8. Linux平台安装Clion
  9. 中国焦磷酸四钾市场趋势报告、技术动态创新及市场预测
  10. 使用vs2008搭建php扩展环境
  11. winform 等待窗口
  12. Unity MRTK(一)
  13. AD9(Altium Designer)电源铜块和整板铺铜设定不同规则,满足不同间距
  14. matlab进行多项式展开
  15. Java SE java基础 求营业额
  16. 华为云空间联系人是不是机主_联系人丢失找回—华为云空间数据安全功能关键时刻出绝招...
  17. Mac每次打开PPT都会出现End窗口
  18. JavaScript-PC端网页特效
  19. react 渲染table数据
  20. SpringBoot使用hutool生成图片二维码

热门文章

  1. poj1163 数字三角形 (动态规划)
  2. expected an indented block
  3. 《中国人工智能学会通讯》——2.35 敏捷和灵巧精细动作技能(Agile and Dexterous Fine Motor Skills)...
  4. [转]Insert, Update, and Delete Destination table with SSIS
  5. 操作系统(5)-进程调度算法
  6. 删除office2016专业版多余组件
  7. mysql启动redis_docker一系列mysql,redis,centos啥的启动参数记个笔记
  8. 算法学习之路|最小生成树——prime算法
  9. NIOS2随笔——BMP解码与VGA显示
  10. linux基础-第十六单元 yum管理RPM包