用一个案例介绍jQuery插件的使用和写法

 2023-09-18 阅读 22 评论 0

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

       我们在做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调用方法,

版权声明:本站所有资料均为网友推荐收集整理而来,仅供学习和研究交流使用。

原文链接:https://hbdhgg.com/1/74478.html

发表评论:

本站为非赢利网站,部分文章来源或改编自互联网及其他公众平台,主要目的在于分享信息,版权归原作者所有,内容仅供读者参考,如有侵权请联系我们删除!

Copyright © 2022 匯編語言學習筆記 Inc. 保留所有权利。

底部版权信息