JavaScript Tab选项卡插件开发:从原生到jQuery的完整演进

作者:闭包旅人

时间:2026-10-29

浏览:417

本文详细介绍如何将Tab选项卡功能封装为JavaScript插件。从原生JS挂载window对象开始,分析全局变量污染问题;随后引入jQuery,分别演示类级别与对象级别的插件写法。重点讲解如何利用$.fn.extend、闭包、this上下文及$.extend配置项优化插件,解决DOM重复获取与参数冗余问题,提供完整的代码演进示例。

文章目录

原生JavaScript插件实现

今日,从最基础的步骤着手,把现有的Tab选项卡切换功能重构为JavaScript插件形式。

原生函数实现方式

将JavaScript方法转换为JS插件的最简易途径,是将其挂载至window全局对象之下。

首先查看最原始的使用函数编写的代码示例:

tab.html


<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
<meta name="renderer" content="webkit">
<title>jquery_hjb_tab插件demo</title>
<link rel="stylesheet" href="h.css"/>
</head>
<body>
<div id="tab">
<div class="tabs">
<ul>
<li><a href="#">tab1</a></li>
<li><a href="#">tab2</a></li>
<li><a href="#">tab3</a></li>
<li><a href="#">tab4</a></li>
</ul>
</div>
<div class="tabCons">
<section>内容一</section>
<section>内容二</section>
<section>内容三</section>
<section>内容四</section>
</div>
</div>
<script>
window.onload = h_tab('tab');
function h_tab(tabId){
var oLinks = document.getElementById(tabId).getElementsByTagName("a");
var oCons = document.getElementById(tabId).getElementsByTagName("section");
for(var i = 0; i<oLinks.length; i++){
oLinks[i].index = i;
oLinks[i].onclick = function () {
for(var j =0; j<oLinks.length; j++){
oLinks[j].className="";
oCons[j].style.display = "none";
}
this.className="cur";
oCons[this.index].style.display ="block";
}

}
}
</script>

h.css


@charset "utf-8";
/*
//author:hjb2722404
//description:
//date:2016/2/18
*/
.tabs ul { width: 100%; list-style-type: none;}
.tabs ul li { width: 48%; display: inline-block; margin: 0; padding: 0;}
.tabs ul li a {border-bottom: 3px solid #cccccc; width: 100%; height: 100%; display: block; text-align: center; min-height: 40px; line-height: 40px; text-decoration: none; font-family: "微软雅黑"; color: #a94442}
.tabs ul li a.cur { border-bottom: 3px solid #f26123;}
.tabCons section { display: none;}
.tabCons section:nth-child(1) { display: block;}

上述两份代码构成了基础代码,后续我们将在此基础之上逐步进行优化改进。

原生插件实现方式

接下来,我们将该方法改写为挂载在window对象下的插件:

tab.html


……
// 下面是第一次改动
<script type="text/javascript" src="h_tabs.js"></script>
<script>
H_tab("tab");
</script>
</body>
</html>

h_tabs.js


window.H_tab = function(tabId){
var oLinks = document.getElementById(tabId).getElementsByTagName("a");
var oCons = document.getElementById(tabId).getElementsByTagName("section");
for(var i = 0; i<oLinks.length; i++){
oLinks[i].index = i;
oLinks[i].onclick = function () {
for(var j =0; j<oLinks.length; j++){
oLinks[j].className="";
oCons[j].style.display = "none";
}
this.className="cur";
oCons[this.index].style.display ="block";
}
}
};

然而,我们发现这种写法虽然简单,但也存在缺陷:window作为全局对象,若将众多方法挂载其下作为插件,极易产生命名空间冲突;此外,尽管使用原生JS能减少对外部库的依赖,但代码量相对较大,写法较为繁琐。

jQuery插件开发演进

jQuery实现方式

我们尝试引入jQuery库,将此插件改写为jQuery插件。

jQuery插件主要有三种形式:类级别形式、对象级别形式以及jQuery UI组件形式。

类级别插件:全局方法挂载

jQuery类级别插件写法——单个方法

我们先来看类级别插件的形式。

第一种类级别插件的形式,直接将该方法挂载到jQuery的根命名空间下,作为一个工具方法:

tab.html


……
<script src="../jquery.js" type="text/javascript"></script>
<script type="text/javascript" src="h_tabs.js"></script>
<script>
$.h_tab('tab');
</script>
</body>
</html>

h_tabs.js


$.h_tab = function(tabId){
var oLinks = document.getElementById(tabId).getElementsByTagName("a");
var oCons = document.getElementById(tabId).getElementsByTagName("section");
for(var i = 0; i<oLinks.length; i++){
oLinks[i].index = i;
oLinks[i].onclick = function () {
for(var j =0; j<oLinks.length; j++){
oLinks[j].className="";
oCons[j].style.display = "none";
}
this.className="cur";
oCons[this.index].style.display ="block";
}
}
};

jQuery类级别插件写法——多个方法

如果你希望将多个方法绑定到jQuery根命名空间上,可以按照以下方式编写:

tab.html


……
<script src="../jquery.js" type="text/javascript"></script>
<script type="text/javascript" src="h_tabs.js"></script>
<script>
$.h_tab('tab');
$.h_hello('hjb');
</script>
</body>
</html>

h_tabs.js


$.extend({
h_tab:function(tabId){
var oLinks = document.getElementById(tabId).getElementsByTagName("a");
var oCons = document.getElementById(tabId).getElementsByTagName("section");
for(var i = 0; i<oLinks.length; i++){
oLinks[i].index = i;
oLinks[i].onclick = function () {
for(var j =0; j<oLinks.length; j++){
oLinks[j].className="";
oCons[j].style.display = "none";
}
this.className="cur";
oCons[this.index].style.display ="block";
}
}
},
h_hello :function(name){
console.log("hello,",name);
}
});

虽然使用$.extend()工具方法将功能函数直接挂载到jQuery根命名空间下,简单且省事,但不幸的是,这种方式无法利用jQuery强大的Sizzle引擎,即你选择到的DOM元素无法应用此方法。

因此,我们需要采用对象级别的插件开发方式。

对象级别插件:原型链扩展

jQuery对象级别插件写法

对象级别的插件开发方式是利用$.fn.extend()方法将自定义方法绑定到jQuery原型上,这样所有jQuery对象均可应用该方法来执行相应操作。

代码如下:

tab.html


……
<script src="../jquery.js" type="text/javascript"></script>
<script type="text/javascript" src="h_tabs.js"></script>
<script>
//对象级别的插件引用方法,注意和上面类级别插件的写法上的区分
$('#tab').h_tab('tab');
</script>
</body>
</html>

h_tabs.js


(function($){
$.fn.extend({
h_tab:function(tabId){
var oLinks = document.getElementById(tabId).getElementsByTagName('a');
var oCons = document.getElementById(tabId).getElementsByTagName('section');
for(var i = 0; i<oLinks.length; i++){
oLinks[i].index = i;
oLinks[i].onclick = function () {
for(var j =0; j<oLinks.length; j++){
oLinks[j].className="";
oCons[j].style.display = "none";
}
this.className="cur";
oCons[this.index].style.display ="block";
}
}
}
});
})(jQuery);

在此,我们利用一个闭包封装了插件,从而避免了命名空间污染。

这里还存在一些问题,即我们的方法必须传入参数才能运行,这导致调用时我们使用$('#tab')选择了id为tab的div,然后在插件内部我们又根据传入的ID重新获取了一遍该元素。

既然我们已经使用了jQuery的选择器,那么我们就可以引入this来解决重复获取元素的冗余问题。

优化:利用this简化DOM操作

jQuery对象级别插件写法——引入this

tab.html


……
<script src="../jquery.js" type="text/javascript"></script>
<script type="text/javascript" src="h_tabs.js"></script>
<script>
$('#tab').h_tab();
</script>
</body>
</html>

h_tabs.js


(function($){
$.fn.extend({
h_tab:function(){
//在这里引入this
var oLinks = this.find('a');
var oCons = this.find('section');
for(var i = 0; i<oLinks.length; i++){
oLinks[i].index = i;
oLinks[i].onclick = function () {
for(var j =0; j<oLinks.length; j++){
oLinks[j].className="";
oCons[j].style.display = "none";
}
this.className="cur";
oCons[this.index].style.display ="block";
}
}
}
});
})(jQuery);

这里需要注意的是,我们调用该插件的元素对象是$('#tab'),则此时直接使用this.find()就等价于$('#tab').find(),而不是$(this).find(),注意使用代入法来区分这两种写法的差别。

作为一款插件,它应当是可以被开发者控制的,因此还应提供给使用者一些配置接口。

进阶:配置项合并与默认值处理

jQuery对象级别插件写法——加入配置项

tab.html


……
<ul>
<!--对照文章开始的代码, 注意这里的改动 -->
<li><a href="#" class="current">tab1</a></li>
<li><a href="#">tab2</a></li>
……
<script src="../jquery.js" type="text/javascript"></script>
<script type="text/javascript" src="h_tabs.js"></script>
<script>
$('#tab').h_tab({
//使得当前选项卡标签的样式名称可自定义的配置
curName:'current'
});
</script>
</body>
</html>

我们这里把一开始的“当前选项卡标签样式类名称”由“cur”改为了“current”,并将其作为配置项传入插件。

h.css


.tabs ul { width: 100%; list-style-type: none;}
.tabs ul li { width: 48%; display: inline-block; margin: 0; padding: 0;}
.tabs ul li a {border-bottom: 3px solid #cccccc; width: 100%; height: 100%; display: block; text-align: center; min-height: 40px; line-height: 40px; text-decoration: none; font-family: "微软雅黑"; color: #a94442}
/*注意下面一行与之前的样式代码的对比变化之处*/
.tabs ul li a.current { border-bottom: 3px solid #f26123;}
.tabCons section { display: none;}
.tabCons section:nth-child(1) { display: block;}

我们在样式表中做出了相应的改动。

h_tabs.js


(function($){
$.fn.extend({
//给方法传入一个对象作为参数
h_tab:function(opts){
//定义默认的配置
var defaults ={
curName : 'cur'
};
//将传入的参数覆盖默认参数中的默认项,最终合并到一个新的参数对象上
var Opt = $.extend({},defaults,opts);
var oLinks = this.find('a');
var oCons = this.find('section');
for(var i = 0; i<oLinks.length; i++){
oLinks[i].index = i;
oLinks[i].onclick = function () {
for(var j =0; j<oLinks.length; j++){
oLinks[j].className="";
oCons[j].style.display = "none";
}
//在这里使用配置项的值
this.className = Opt['curName'];
oCons[this.index].style.display ="block";
}
}
}
});
})(jQuery);

在这里我们使用了jQuery的$.extend()方法的合并对象功能,使用用户传入的配置项覆盖默认配置项,并最终合并到一个新的配置项供后续程序使用。

以上所述是小编给大家介绍的JavaScript tab选项卡插件实例代码,希望对大家有所帮助!

实用工具推荐

电子包浆

绿化、压缩、噪点和虚拟水印,自由调节做旧程度。

使用 ›
图片压缩

选择画质和输出格式,预览压缩前后的大小。

使用 ›
相关文章