[js插件开发教程]一步步开发一个可以定制配置的隔行变色小插件

隔行变色功能,不用js,直接用css伪类就可以做,这个实例可以作为js插件开发很好的入门级实例。本文实现的隔行变色包括以下功能:

1,支持2种常用结构共存( div元素 和 表格类型 )

2,一个页面内支持不同模块隔行变色,分别管理

3,可以定制的配置有:

奇/偶数行的背景颜色

特定的模块加上隔行变色

当前激活行的颜色

隔行变色的元素类型定制

{
'activeClass' : 'active',
'evenClass' : 'even-color',
'oddClass' : 'odd-color',
'ele' : 'div',
'context' : document
}; 
4,可以扩展其他插件
 
点击run code按钮预览效果

<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>隔行变色插件开发 - by ghostwu</title>
<style>
table {
border-collapse: collapse;
width: 100%;
}

th,
td {
padding: 10px 30px;
border: 1px solid #ccc;
}

.even-color {
background: #ccc;
}

.odd-color {
background: #eee;
}

.even-color2 {
background: #000;
}

.odd-color2 {
background: #666;
}

.current {
background: yellow;
}

.active {
background: #09f;
}

#box div,
#box2 div {
margin: 10px;
padding: 10px;
border: 1px solid #ccc;
}
</style>
</style>
<script>
(function () {
/*
隔行变色
选项卡
全选不选反选
*/
var ghostwu = {};

/***************隔行变色开始***************/
ghostwu.BgColor = {
Bg: function (option) {
return new ghostwu.BgColor.init(option);
}
};
ghostwu.BgColor.init = function (option) {
this.oldColor = null;
this.opt = {
'activeClass': 'active',
'evenClass': 'even-color',
'oddClass': 'odd-color',
'ele': 'div',
'context': document
}; //存储默认配置
for (var key in option) {
this.opt[key] = option[key];
}
if (this.opt.ele == 'div') {
var curCxt = this.opt.context;
if (typeof this.opt['context'] === 'string') {
curCxt = document.querySelector(this.opt['context']);
}
this.elements = curCxt.querySelectorAll(this.opt.ele);
} else {
this.elements = this.opt.context.querySelectorAll(this.opt.ele + ' tr');
for (var i = 0; i < this.elements.length; i++) {
if (this.elements[i].children[0].nodeName.toLowerCase() == 'th') {
this.elements = [].slice.call(this.elements);
this.elements.splice(i, 1);
}
}
}
}
ghostwu.BgColor.init.prototype.setBgColor = function () {
for (var i = 0; i < this.elements.length; i++) {
if (i % 2 == 0) {
this.elements[i].className = this.opt['evenClass'];
} else {
this.elements[i].className = this.opt['oddClass'];
}
}
}
ghostwu.BgColor.init.prototype.hover = function () {
var that = this;
for (var i = 0; i < this.elements.length; i++) {
this.elements[i].onmouseover = function () {
that.addBg(this);
};
this.elements[i].onmouseout = function () {
that.removeBg(this);
}
}
}
ghostwu.BgColor.init.prototype.addBg = function (curObj) {
this.oldColor = curObj.className;
curObj.className = this.opt['activeClass'];
}
ghostwu.BgColor.init.prototype.removeBg = function (curObj) {
curObj.className = this.oldColor;
}
/***************隔行变色结束***************/

window.g = ghostwu;
})();
</script>
<script>
window.onload = function () {
var oBg = g.BgColor.Bg({
'activeClass': 'current',
'ele': 'table'
});
oBg.setBgColor();
oBg.hover();

var oBg2 = g.BgColor.Bg({
'activeClass': 'active',
'ele': 'div',
'context': '#box'
});
oBg2.setBgColor();
oBg2.hover();

var oBg3 = g.BgColor.Bg({
'activeClass': 'current',
'ele': 'div',
'evenClass': 'even-color2',
'oddClass': 'odd-color2',
'context': '#box2'
});
oBg3.setBgColor();
oBg3.hover();
}
</script>
</head>

<body>
<div id="box">
<div></div>
<div></div>
<div></div>
<div></div>
</div>
<div id="box2">
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
</div>
<table>
<tr>
<th>姓名</th>
<th>性别</th>
<th>年龄</th>
</tr>
<tr>
<td>张三</td>
<td>man</td>
<td>20</td>
</tr>
<tr>
<td>张三</td>
<td>man</td>
<td>20</td>
</tr>
<tr>
<td>张三</td>
<td>man</td>
<td>20</td>
</tr>
<tr>
<td>张三</td>
<td>man</td>
<td>20</td>
</tr>
<tr>
<td>张三</td>
<td>man</td>
<td>20</td>
</tr>
<tr>
<td>张三</td>
<td>man</td>
<td>20</td>
</tr>
<tr>
<td>张三</td>
<td>man</td>
<td>20</td>
</tr>
</table>
</body>

</html>
run code

 
我们要实现的是多个插件功能【选项卡,全选,不选,反选,轮播,弹窗,分页等常用插件】,所以第一步,要做一个简单的模块架构,这里,我采用的是字面量单例模式+命名空间
 (function(){
/*
隔行变色
选项卡
全选不选反选
*/
var ghostwu = {};
/***************隔行变色开始***************/
ghostwu.BgColor = {
};
ghostwu.BgColor.init = function(){
}
ghostwu.BgColor.setBgColor = function(){
}
ghostwu.BgColor.hover = function(){
}
ghostwu.BgColor.addBg = function(){
}
ghostwu.BgColor.removeBg = function(){
}
/***************隔行变色结束***************/ /***************选项卡开始***************/
ghostwu.Tab = {
};
ghostwu.Tab.init = function(){
}
ghostwu.Tab.bindEvent = function(){
}
ghostwu.BgColor.switchTab = function(){
}
/***************选项卡结束***************/ window.g = ghostwu;
})();

一、首先定义一个一级的命名空间 ghostwu = {},然后通过window对象 暴露这个对象 给外部使用

接下来开发的插件,只要加在我的一级命名空间中即可,如:

ghostwu.BgColor

ghostwu.Tab

ghostwu.Page

ghostwu.Module

........等等

插件的具体方法,在二级命名空间继续增加,如:

ghostwu.BgColor.init

为隔行变色插件( BgColor ) 添加一个初始化方法( init )

二、实现一个不能定制配置的隔行变色功能

demo.js代码

 var ghostwu = {};
/***************隔行变色开始***************/
ghostwu.BgColor = {
oldColor : null
};
ghostwu.BgColor.init = function(){
this.aDiv = document.querySelectorAll( "div" );
}
ghostwu.BgColor.setBgColor = function(){
for( var i = 0; i < this.aDiv.length; i++ ){
if ( i % 2 == 0 ){
this.aDiv[i].className = 'even-color';
}else {
this.aDiv[i].className = 'odd-color';
}
}
}
ghostwu.BgColor.hover = function(){
var that = this;
for( var i = 0 ; i < this.aDiv.length; i++ ){
this.aDiv[i].onmouseover = function(){
that.addBg( this );
}
this.aDiv[i].onmouseout = function(){
that.removeBg( this );
}
}
}
ghostwu.BgColor.addBg = function( curObj ){
this.oldColor = curObj.className;
curObj.className = 'active';
}
ghostwu.BgColor.removeBg = function( curObj ){
curObj.className = this.oldColor;
}
/***************隔行变色结束***************/

html页面布局代码

 <!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>隔行变色 - by ghostwu</title>
<style>
div{
margin:10px;
padding:20px;
border:1px solid #ccc;
}
.even-color {
background:#ccc;
}
.odd-color {
background: #eee;
}
.active {
background:yellow;
}
</style>
<script src="./lib/demo.js"></script>
<script>
window.onload = function(){
var oBg = g.BgColor;
oBg.init();
oBg.setBgColor();
oBg.hover();
}
</script>
</head>
<body>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
</body>
</html>

至此,一个简单的隔行变色功能就完成了,但是不能称之为插件,因为这个功能现在是写死的

三、把可能变化的部分抽象出来变成配置
可能变化的部分有:
1,元素,这里我们的布局是div,隔行变色也有可能是表格
2,class样式,这里是even-color,odd-color, active,我们要支持class定制
接下来,我们添加一个json配置,设置一些默认配置,然后允许初始化的时候 定制样式名称和元素
 var ghostwu = {};
/***************隔行变色开始***************/
ghostwu.BgColor = {
oldColor : null,
opt : {
'activeClass' : 'active',
'oddClass' : 'odd-color',
'evenClass' : 'even-color',
'ele' : 'div'
}
};
ghostwu.BgColor.init = function(){
this.elements = document.querySelectorAll( this.opt['ele'] );
}
ghostwu.BgColor.setBgColor = function(){
for( var i = 0; i < this.elements.length; i++ ){
if ( i % 2 == 0 ){
this.elements[i].className = this.opt['evenClass'];
}else {
this.elements[i].className = this.opt['oddClass'];
}
}
}
ghostwu.BgColor.hover = function(){
var that = this;
for( var i = 0 ; i < this.elements.length; i++ ){
this.elements[i].onmouseover = function(){
that.addBg( this );
}
this.elements[i].onmouseout = function(){
that.removeBg( this );
}
}
}
ghostwu.BgColor.addBg = function( curObj ){
this.oldColor = curObj.className;
curObj.className = this.opt['activeClass'];
}
ghostwu.BgColor.removeBg = function( curObj ){
curObj.className = this.oldColor;
}
/***************隔行变色结束***************/

经过修改之后,我们就可以通过 opt这个json 配置样式和元素结构了, 接下来,我们就得增加参数配置了

四、参数配置

只需要在demo.js代码中,加入一个for循环,把参数的配置复制给opt即可

 ghostwu.BgColor.init = function( option ){
for( var key in option ){
this.opt[key] = option[key];
}
this.elements = document.querySelectorAll( this.opt['ele'] );
}

html测试页面修改如下:

 <style>
div{
margin:10px;
padding:20px;
border:1px solid #ccc;
}
.even-color2 {
background:#000;
}
.odd-color2 {
background: #666;
}
.current {
background:#08f;
}
</style>
<script src="./lib/demo.js"></script>
<script>
window.onload = function(){
var oBg = g.BgColor;
oBg.init({
'activeClass' : 'current',
'evenClass' : 'even-color2',
'oddClass' : 'odd-color2'
});
oBg.setBgColor();
oBg.hover();
}
</script>

五、完善元素的配置

在第四步中,class都可以定制了,但是ele还不能定制,这个ele就是控制隔行变色的结构

修改init函数如下:

 ghostwu.BgColor.init = function( option ){
for( var key in option ){
this.opt[key] = option[key];
}
if ( this.opt['ele'] == 'div' ) {
this.elements = document.querySelectorAll( this.opt['ele'] );
}else{
this.elements = document.querySelectorAll( this.opt['ele'] + " tr" );
this.elements = [].slice.call( this.elements );
for( var i = 0 ; i < this.elements.length; i++ ){
if ( this.elements[i].children[0].nodeName.toLowerCase() == 'th' ) {
this.elements.splice( i, 1 );
}
}
}
}

测试页面的代码修改如下:

 <!DOCTYPE html>
<html lang="en"> <head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>隔行变色 - by ghostwu</title>
<style>
table {
border-collapse: collapse;
width: 100%;
} th,
td {
padding: 10px 30px;
border: 1px solid #ccc;
}
div {
margin: 10px;
padding: 20px;
border: 1px solid #ccc;
} .even-color2 {
background: #000;
} .odd-color2 {
background: #666;
} .current {
background: #08f;
}
</style>
<script src="./lib/demo.js"></script>
<script>
window.onload = function () {
var oBg = g.BgColor;
oBg.init({
'activeClass': 'current',
'evenClass': 'even-color2',
'oddClass': 'odd-color2'
});
oBg.setBgColor();
oBg.hover(); var oBg2 = g.BgColor;
oBg2.init({
'activeClass': 'current',
'evenClass': 'even-color2',
'oddClass': 'odd-color2',
'ele' : 'table'
});
oBg2.setBgColor();
oBg2.hover();
} </script>
</head> <body>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<table>
<tr>
<th>姓名</th>
<th>性别</th>
<th>年龄</th>
</tr>
<tr>
<td>ghostwu</td>
<td>man</td>
<td>20</td>
</tr>
<tr>
<td>ghostwu</td>
<td>man</td>
<td>20</td>
</tr>
<tr>
<td>ghostwu</td>
<td>man</td>
<td>20</td>
</tr>
<tr>
<td>ghostwu</td>
<td>man</td>
<td>20</td>
</tr>
<tr>
<td>ghostwu</td>
<td>man</td>
<td>20</td>
</tr>
<tr>
<td>ghostwu</td>
<td>man</td>
<td>20</td>
</tr>
<tr>
<td>ghostwu</td>
<td>man</td>
<td>20</td>
</tr>
</table>
</body> </html>

至此,我们开发的功能,勉强算个插件了,但是,不能按区域控制,比如页面上有10个div, 分成2部分,一部分有5个div,另外一部分也是5个,我想其中一部分div加上隔行变色效果。另外一部分不加.

六、分块控制

其实很简单,就是不要用document去获取元素,document获取到的元素是所有的元素,所以我们在配置中加一个上下文的配置,可以限定获取某部分满足条件的节点.
修改demo.js对应部分的代码如下:
 ghostwu.BgColor = {
oldColor : null,
opt : {
'activeClass' : 'active',
'oddClass' : 'odd-color',
'evenClass' : 'even-color',
'ele' : 'div',
'context' : document
}
};
ghostwu.BgColor.init = function( option ){
for( var key in option ){
this.opt[key] = option[key];
}
var cxt = this.opt['context'];
if ( typeof cxt === 'string' ){
cxt = document.querySelector( this.opt['context'] );
}
if ( this.opt['ele'] == 'div' ) {
this.elements = cxt.querySelectorAll( this.opt['ele'] );
}else{
this.elements = cxt.querySelectorAll( this.opt['ele'] + " tr" );
this.elements = [].slice.call( this.elements );
for( var i = 0 ; i < this.elements.length; i++ ){
if ( this.elements[i].children[0].nodeName.toLowerCase() == 'th' ) {
this.elements.splice( i, 1 );
}
}
}
}

修改html页面代码如下:

 <!DOCTYPE html>
<html lang="en"> <head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>隔行变色 - by ghostwu</title>
<style>
table {
border-collapse: collapse;
width: 100%;
} th,
td {
padding: 10px 30px;
border: 1px solid #ccc;
} .even-color {
background: #ccc;
} .odd-color {
background: #eee;
} .even-color2 {
background: #000;
} .odd-color2 {
background: #666;
} .current {
background: yellow;
} .active {
background: #09f;
} #box div,
#box2 div {
margin: 10px;
padding: 10px;
border: 1px solid #ccc;
}
</style>
<script src="./lib/demo.js"></script>
<script>
window.onload = function () {
var oBg = g.BgColor;
oBg.init({
'activeClass': 'current',
'evenClass': 'even-color2',
'oddClass': 'odd-color2',
'context' : '#box'
});
oBg.setBgColor();
oBg.hover(); var oBg3 = g.BgColor;
oBg3.init({
'activeClass': 'active',
'evenClass': 'even-color',
'oddClass': 'odd-color',
'context' : '#box2'
});
oBg3.setBgColor();
oBg3.hover(); var oBg2 = g.BgColor;
oBg2.init({
'activeClass': 'current',
'evenClass': 'even-color2',
'oddClass': 'odd-color2',
'ele': 'table',
'context' : document
});
oBg2.setBgColor();
oBg2.hover();
}
</script>
</head> <body>
<div id="box">
<div></div>
<div></div>
<div></div>
<div></div>
</div>
<div id="box2">
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
</div>
<table>
<tr>
<th>姓名</th>
<th>性别</th>
<th>年龄</th>
</tr>
<tr>
<td>ghostwu</td>
<td>man</td>
<td>20</td>
</tr>
<tr>
<td>ghostwu</td>
<td>man</td>
<td>20</td>
</tr>
<tr>
<td>ghostwu</td>
<td>man</td>
<td>20</td>
</tr>
<tr>
<td>ghostwu</td>
<td>man</td>
<td>20</td>
</tr>
<tr>
<td>ghostwu</td>
<td>man</td>
<td>20</td>
</tr>
<tr>
<td>ghostwu</td>
<td>man</td>
<td>20</td>
</tr>
<tr>
<td>ghostwu</td>
<td>man</td>
<td>20</td>
</tr>
</table>
</body> </html>

这样我们就可以达到分块控制的目的,但是,如果你仔细一点,应该能发现一个问题,activeClass设置的样式产生了覆盖,3个区域不能定制activeClass。这个就是单例模式无法解决的问题,我们可以通过构造函数解决

七、构造函数解决属性配置覆盖的问题

最终版demo.js文件
 (function(){
/*
隔行变色
选项卡
全选不选反选
*/
var ghostwu = {}; /***************隔行变色开始***************/
ghostwu.BgColor = {
Bg : function( option ){
return new ghostwu.BgColor.init( option );
}
};
ghostwu.BgColor.init = function( option ){
this.oldColor = null;
this.opt = {
'activeClass' : 'active',
'evenClass' : 'even-color',
'oddClass' : 'odd-color',
'ele' : 'div',
'context' : document
}; //存储默认配置
for( var key in option ){
this.opt[key] = option[key];
}
if ( this.opt.ele == 'div' ){
var curCxt = this.opt.context;
if ( typeof this.opt['context'] === 'string' ) {
curCxt = document.querySelector( this.opt['context'] );
}
this.elements = curCxt.querySelectorAll( this.opt.ele );
}else {
this.elements = this.opt.context.querySelectorAll( this.opt.ele + ' tr' );
for( var i = 0; i < this.elements.length; i++ ){
if( this.elements[i].children[0].nodeName.toLowerCase() == 'th'){
this.elements = [].slice.call( this.elements );
this.elements.splice( i, 1 );
}
}
}
}
ghostwu.BgColor.init.prototype.setBgColor = function(){
for( var i = 0 ; i < this.elements.length; i++ ){
if ( i % 2 == 0 ) {
this.elements[i].className = this.opt['evenClass'];
}else {
this.elements[i].className = this.opt['oddClass'];
}
}
}
ghostwu.BgColor.init.prototype.hover = function(){
var that = this;
for( var i = 0 ; i < this.elements.length; i++ ){
this.elements[i].onmouseover = function(){
that.addBg( this );
};
this.elements[i].onmouseout = function(){
that.removeBg( this );
}
}
}
ghostwu.BgColor.init.prototype.addBg = function( curObj ){
this.oldColor = curObj.className;
curObj.className = this.opt['activeClass'];
}
ghostwu.BgColor.init.prototype.removeBg = function( curObj ){
curObj.className = this.oldColor;
}
/***************隔行变色结束***************/ window.g = ghostwu;
})();

页面测试代码:

 <!DOCTYPE html>
<html lang="en"> <head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>隔行变色插件开发 - by ghostwu</title>
<style>
table {
border-collapse: collapse;
width: 100%;
} th,
td {
padding: 10px 30px;
border: 1px solid #ccc;
} .even-color {
background: #ccc;
} .odd-color {
background: #eee;
} .even-color2 {
background: #000;
} .odd-color2 {
background: #666;
} .current {
background: yellow;
} .active {
background: #09f;
} #box div,
#box2 div {
margin: 10px;
padding: 10px;
border: 1px solid #ccc;
}
</style>
<script src="./lib/common2.js"></script>
<script>
window.onload = function () {
var oBg = g.BgColor.Bg({
'activeClass': 'current',
'ele': 'table'
});
oBg.setBgColor();
oBg.hover(); var oBg2 = g.BgColor.Bg({
'activeClass': 'active',
'ele': 'div',
'context': '#box'
});
oBg2.setBgColor();
oBg2.hover(); var oBg3 = g.BgColor.Bg({
'activeClass': 'current',
'ele': 'div',
'evenClass': 'even-color2',
'oddClass': 'odd-color2',
'context': '#box2'
});
oBg3.setBgColor();
oBg3.hover();
}
</script>
</head> <body>
<div id="box">
<div></div>
<div></div>
<div></div>
<div></div>
</div>
<div id="box2">
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
</div>
<table>
<tr>
<th>姓名</th>
<th>性别</th>
<th>年龄</th>
</tr>
<tr>
<td>张三</td>
<td>man</td>
<td>20</td>
</tr>
<tr>
<td>张三</td>
<td>man</td>
<td>20</td>
</tr>
<tr>
<td>张三</td>
<td>man</td>
<td>20</td>
</tr>
<tr>
<td>张三</td>
<td>man</td>
<td>20</td>
</tr>
<tr>
<td>张三</td>
<td>man</td>
<td>20</td>
</tr>
<tr>
<td>张三</td>
<td>man</td>
<td>20</td>
</tr>
<tr>
<td>张三</td>
<td>man</td>
<td>20</td>
</tr>
</table>
</body> </html>
上一篇:LCIS hdu3308 (线段树 区间合并)


下一篇:【前端 · 面试 】HTTP 总结(八)—— HTTP 强缓存