[js插件开发教程]一步步开发一个可以定制配置的隔行变色小插件
隔行变色功能,不用js,直接用css伪类就可以做,这个实例可以作为js插件开发很好的入门级实例。本文实现的隔行变色包括以下功能:
1,支持2种常用结构共存( div元素 和 表格类型 )
2,一个页面内支持不同模块隔行变色,分别管理
3,可以定制的配置有:
奇/偶数行的背景颜色
特定的模块加上隔行变色
当前激活行的颜色
隔行变色的元素类型定制
1 (function(){ 2 /* 3 隔行变色 4 选项卡 5 全选不选反选 6 */ 7 var ghostwu = {}; 8 /***************隔行变色开始***************/ 9 ghostwu.BgColor = { 10 }; 11 ghostwu.BgColor.init = function(){ 12 } 13 ghostwu.BgColor.setBgColor = function(){ 14 } 15 ghostwu.BgColor.hover = function(){ 16 } 17 ghostwu.BgColor.addBg = function(){ 18 } 19 ghostwu.BgColor.removeBg = function(){ 20 } 21 /***************隔行变色结束***************/ 22 23 /***************选项卡开始***************/ 24 ghostwu.Tab = { 25 }; 26 ghostwu.Tab.init = function(){ 27 } 28 ghostwu.Tab.bindEvent = function(){ 29 } 30 ghostwu.BgColor.switchTab = function(){ 31 } 32 /***************选项卡结束***************/ 33 34 window.g = ghostwu; 35 })();
一、首先定义一个一级的命名空间 ghostwu = {},然后通过window对象 暴露这个对象 给外部使用
接下来开发的插件,只要加在我的一级命名空间中即可,如:
ghostwu.BgColor
ghostwu.Tab
ghostwu.Page
ghostwu.Module
........等等
插件的具体方法,在二级命名空间继续增加,如:
ghostwu.BgColor.init
为隔行变色插件( BgColor ) 添加一个初始化方法( init )
二、实现一个不能定制配置的隔行变色功能
demo.js代码
1 var ghostwu = {}; 2 /***************隔行变色开始***************/ 3 ghostwu.BgColor = { 4 oldColor : null 5 }; 6 ghostwu.BgColor.init = function(){ 7 this.aDiv = document.querySelectorAll( "div" ); 8 } 9 ghostwu.BgColor.setBgColor = function(){ 10 for( var i = 0; i < this.aDiv.length; i++ ){ 11 if ( i % 2 == 0 ){ 12 this.aDiv[i].className = 'even-color'; 13 }else { 14 this.aDiv[i].className = 'odd-color'; 15 } 16 } 17 } 18 ghostwu.BgColor.hover = function(){ 19 var that = this; 20 for( var i = 0 ; i < this.aDiv.length; i++ ){ 21 this.aDiv[i].onmouseover = function(){ 22 that.addBg( this ); 23 } 24 this.aDiv[i].onmouseout = function(){ 25 that.removeBg( this ); 26 } 27 } 28 } 29 ghostwu.BgColor.addBg = function( curObj ){ 30 this.oldColor = curObj.className; 31 curObj.className = 'active'; 32 } 33 ghostwu.BgColor.removeBg = function( curObj ){ 34 curObj.className = this.oldColor; 35 } 36 /***************隔行变色结束***************/
html页面布局代码
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <meta name="viewport" content="width=device-width, initial-scale=1.0"> 6 <meta http-equiv="X-UA-Compatible" content="ie=edge"> 7 <title>隔行变色 - by ghostwu</title> 8 <style> 9 div{ 10 margin:10px; 11 padding:20px; 12 border:1px solid #ccc; 13 } 14 .even-color { 15 background:#ccc; 16 } 17 .odd-color { 18 background: #eee; 19 } 20 .active { 21 background:yellow; 22 } 23 </style> 24 <script src="./lib/demo.js"></script> 25 <script> 26 window.onload = function(){ 27 var oBg = g.BgColor; 28 oBg.init(); 29 oBg.setBgColor(); 30 oBg.hover(); 31 } 32 </script> 33 </head> 34 <body> 35 <div></div> 36 <div></div> 37 <div></div> 38 <div></div> 39 <div></div> 40 <div></div> 41 </body> 42 </html>
至此,一个简单的隔行变色功能就完成了,但是不能称之为插件,因为这个功能现在是写死的
1 var ghostwu = {}; 2 /***************隔行变色开始***************/ 3 ghostwu.BgColor = { 4 oldColor : null, 5 opt : { 6 'activeClass' : 'active', 7 'oddClass' : 'odd-color', 8 'evenClass' : 'even-color', 9 'ele' : 'div' 10 } 11 }; 12 ghostwu.BgColor.init = function(){ 13 this.elements = document.querySelectorAll( this.opt['ele'] ); 14 } 15 ghostwu.BgColor.setBgColor = function(){ 16 for( var i = 0; i < this.elements.length; i++ ){ 17 if ( i % 2 == 0 ){ 18 this.elements[i].className = this.opt['evenClass']; 19 }else { 20 this.elements[i].className = this.opt['oddClass']; 21 } 22 } 23 } 24 ghostwu.BgColor.hover = function(){ 25 var that = this; 26 for( var i = 0 ; i < this.elements.length; i++ ){ 27 this.elements[i].onmouseover = function(){ 28 that.addBg( this ); 29 } 30 this.elements[i].onmouseout = function(){ 31 that.removeBg( this ); 32 } 33 } 34 } 35 ghostwu.BgColor.addBg = function( curObj ){ 36 this.oldColor = curObj.className; 37 curObj.className = this.opt['activeClass']; 38 } 39 ghostwu.BgColor.removeBg = function( curObj ){ 40 curObj.className = this.oldColor; 41 } 42 /***************隔行变色结束***************/
经过修改之后,我们就可以通过 opt这个json 配置样式和元素结构了, 接下来,我们就得增加参数配置了
四、参数配置
只需要在demo.js代码中,加入一个for循环,把参数的配置复制给opt即可
1 ghostwu.BgColor.init = function( option ){ 2 for( var key in option ){ 3 this.opt[key] = option[key]; 4 } 5 this.elements = document.querySelectorAll( this.opt['ele'] ); 6 }
html测试页面修改如下:
1 <style> 2 div{ 3 margin:10px; 4 padding:20px; 5 border:1px solid #ccc; 6 } 7 .even-color2 { 8 background:#000; 9 } 10 .odd-color2 { 11 background: #666; 12 } 13 .current { 14 background:#08f; 15 } 16 </style> 17 <script src="./lib/demo.js"></script> 18 <script> 19 window.onload = function(){ 20 var oBg = g.BgColor; 21 oBg.init({ 22 'activeClass' : 'current', 23 'evenClass' : 'even-color2', 24 'oddClass' : 'odd-color2' 25 }); 26 oBg.setBgColor(); 27 oBg.hover(); 28 } 29 </script>
五、完善元素的配置
在第四步中,class都可以定制了,但是ele还不能定制,这个ele就是控制隔行变色的结构
修改init函数如下:
1 ghostwu.BgColor.init = function( option ){ 2 for( var key in option ){ 3 this.opt[key] = option[key]; 4 } 5 if ( this.opt['ele'] == 'div' ) { 6 this.elements = document.querySelectorAll( this.opt['ele'] ); 7 }else{ 8 this.elements = document.querySelectorAll( this.opt['ele'] + " tr" ); 9 this.elements = [].slice.call( this.elements ); 10 for( var i = 0 ; i < this.elements.length; i++ ){ 11 if ( this.elements[i].children[0].nodeName.toLowerCase() == 'th' ) { 12 this.elements.splice( i, 1 ); 13 } 14 } 15 } 16 }
测试页面的代码修改如下:
1 <!DOCTYPE html> 2 <html lang="en"> 3 4 <head> 5 <meta charset="UTF-8"> 6 <meta name="viewport" content="width=device-width, initial-scale=1.0"> 7 <meta http-equiv="X-UA-Compatible" content="ie=edge"> 8 <title>隔行变色 - by ghostwu</title> 9 <style> 10 table { 11 border-collapse: collapse; 12 width: 100%; 13 } 14 15 th, 16 td { 17 padding: 10px 30px; 18 border: 1px solid #ccc; 19 } 20 div { 21 margin: 10px; 22 padding: 20px; 23 border: 1px solid #ccc; 24 } 25 26 .even-color2 { 27 background: #000; 28 } 29 30 .odd-color2 { 31 background: #666; 32 } 33 34 .current { 35 background: #08f; 36 } 37 </style> 38 <script src="./lib/demo.js"></script> 39 <script> 40 window.onload = function () { 41 var oBg = g.BgColor; 42 oBg.init({ 43 'activeClass': 'current', 44 'evenClass': 'even-color2', 45 'oddClass': 'odd-color2' 46 }); 47 oBg.setBgColor(); 48 oBg.hover(); 49 50 var oBg2 = g.BgColor; 51 oBg2.init({ 52 'activeClass': 'current', 53 'evenClass': 'even-color2', 54 'oddClass': 'odd-color2', 55 'ele' : 'table' 56 }); 57 oBg2.setBgColor(); 58 oBg2.hover(); 59 } 60 61 </script> 62 </head> 63 64 <body> 65 <div></div> 66 <div></div> 67 <div></div> 68 <div></div> 69 <div></div> 70 <div></div> 71 <table> 72 <tr> 73 <th>姓名</th> 74 <th>性别</th> 75 <th>年龄</th> 76 </tr> 77 <tr> 78 <td>ghostwu</td> 79 <td>man</td> 80 <td>20</td> 81 </tr> 82 <tr> 83 <td>ghostwu</td> 84 <td>man</td> 85 <td>20</td> 86 </tr> 87 <tr> 88 <td>ghostwu</td> 89 <td>man</td> 90 <td>20</td> 91 </tr> 92 <tr> 93 <td>ghostwu</td> 94 <td>man</td> 95 <td>20</td> 96 </tr> 97 <tr> 98 <td>ghostwu</td> 99 <td>man</td> 100 <td>20</td> 101 </tr> 102 <tr> 103 <td>ghostwu</td> 104 <td>man</td> 105 <td>20</td> 106 </tr> 107 <tr> 108 <td>ghostwu</td> 109 <td>man</td> 110 <td>20</td> 111 </tr> 112 </table> 113 </body> 114 115 </html>
至此,我们开发的功能,勉强算个插件了,但是,不能按区域控制,比如页面上有10个div, 分成2部分,一部分有5个div,另外一部分也是5个,我想其中一部分div加上隔行变色效果。另外一部分不加.
六、分块控制
1 ghostwu.BgColor = { 2 oldColor : null, 3 opt : { 4 'activeClass' : 'active', 5 'oddClass' : 'odd-color', 6 'evenClass' : 'even-color', 7 'ele' : 'div', 8 'context' : document 9 } 10 }; 11 ghostwu.BgColor.init = function( option ){ 12 for( var key in option ){ 13 this.opt[key] = option[key]; 14 } 15 var cxt = this.opt['context']; 16 if ( typeof cxt === 'string' ){ 17 cxt = document.querySelector( this.opt['context'] ); 18 } 19 if ( this.opt['ele'] == 'div' ) { 20 this.elements = cxt.querySelectorAll( this.opt['ele'] ); 21 }else{ 22 this.elements = cxt.querySelectorAll( this.opt['ele'] + " tr" ); 23 this.elements = [].slice.call( this.elements ); 24 for( var i = 0 ; i < this.elements.length; i++ ){ 25 if ( this.elements[i].children[0].nodeName.toLowerCase() == 'th' ) { 26 this.elements.splice( i, 1 ); 27 } 28 } 29 } 30 }
修改html页面代码如下:
1 <!DOCTYPE html> 2 <html lang="en"> 3 4 <head> 5 <meta charset="UTF-8"> 6 <meta name="viewport" content="width=device-width, initial-scale=1.0"> 7 <meta http-equiv="X-UA-Compatible" content="ie=edge"> 8 <title>隔行变色 - by ghostwu</title> 9 <style> 10 table { 11 border-collapse: collapse; 12 width: 100%; 13 } 14 15 th, 16 td { 17 padding: 10px 30px; 18 border: 1px solid #ccc; 19 } 20 21 .even-color { 22 background: #ccc; 23 } 24 25 .odd-color { 26 background: #eee; 27 } 28 29 .even-color2 { 30 background: #000; 31 } 32 33 .odd-color2 { 34 background: #666; 35 } 36 37 .current { 38 background: yellow; 39 } 40 41 .active { 42 background: #09f; 43 } 44 45 #box div, 46 #box2 div { 47 margin: 10px; 48 padding: 10px; 49 border: 1px solid #ccc; 50 } 51 </style> 52 <script src="./lib/demo.js"></script> 53 <script> 54 window.onload = function () { 55 var oBg = g.BgColor; 56 oBg.init({ 57 'activeClass': 'current', 58 'evenClass': 'even-color2', 59 'oddClass': 'odd-color2', 60 'context' : '#box' 61 }); 62 oBg.setBgColor(); 63 oBg.hover(); 64 65 var oBg3 = g.BgColor; 66 oBg3.init({ 67 'activeClass': 'active', 68 'evenClass': 'even-color', 69 'oddClass': 'odd-color', 70 'context' : '#box2' 71 }); 72 oBg3.setBgColor(); 73 oBg3.hover(); 74 75 var oBg2 = g.BgColor; 76 oBg2.init({ 77 'activeClass': 'current', 78 'evenClass': 'even-color2', 79 'oddClass': 'odd-color2', 80 'ele': 'table', 81 'context' : document 82 }); 83 oBg2.setBgColor(); 84 oBg2.hover(); 85 } 86 </script> 87 </head> 88 89 <body> 90 <div id="box"> 91 <div></div> 92 <div></div> 93 <div></div> 94 <div></div> 95 </div> 96 <div id="box2"> 97 <div></div> 98 <div></div> 99 <div></div> 100 <div></div> 101 <div></div> 102 <div></div> 103 </div> 104 <table> 105 <tr> 106 <th>姓名</th> 107 <th>性别</th> 108 <th>年龄</th> 109 </tr> 110 <tr> 111 <td>ghostwu</td> 112 <td>man</td> 113 <td>20</td> 114 </tr> 115 <tr> 116 <td>ghostwu</td> 117 <td>man</td> 118 <td>20</td> 119 </tr> 120 <tr> 121 <td>ghostwu</td> 122 <td>man</td> 123 <td>20</td> 124 </tr> 125 <tr> 126 <td>ghostwu</td> 127 <td>man</td> 128 <td>20</td> 129 </tr> 130 <tr> 131 <td>ghostwu</td> 132 <td>man</td> 133 <td>20</td> 134 </tr> 135 <tr> 136 <td>ghostwu</td> 137 <td>man</td> 138 <td>20</td> 139 </tr> 140 <tr> 141 <td>ghostwu</td> 142 <td>man</td> 143 <td>20</td> 144 </tr> 145 </table> 146 </body> 147 148 </html>
这样我们就可以达到分块控制的目的,但是,如果你仔细一点,应该能发现一个问题,activeClass设置的样式产生了覆盖,3个区域不能定制activeClass。这个就是单例模式无法解决的问题,我们可以通过构造函数解决
七、构造函数解决属性配置覆盖的问题
1 (function(){ 2 /* 3 隔行变色 4 选项卡 5 全选不选反选 6 */ 7 var ghostwu = {}; 8 9 /***************隔行变色开始***************/ 10 ghostwu.BgColor = { 11 Bg : function( option ){ 12 return new ghostwu.BgColor.init( option ); 13 } 14 }; 15 ghostwu.BgColor.init = function( option ){ 16 this.oldColor = null; 17 this.opt = { 18 'activeClass' : 'active', 19 'evenClass' : 'even-color', 20 'oddClass' : 'odd-color', 21 'ele' : 'div', 22 'context' : document 23 }; //存储默认配置 24 for( var key in option ){ 25 this.opt[key] = option[key]; 26 } 27 if ( this.opt.ele == 'div' ){ 28 var curCxt = this.opt.context; 29 if ( typeof this.opt['context'] === 'string' ) { 30 curCxt = document.querySelector( this.opt['context'] ); 31 } 32 this.elements = curCxt.querySelectorAll( this.opt.ele ); 33 }else { 34 this.elements = this.opt.context.querySelectorAll( this.opt.ele + ' tr' ); 35 for( var i = 0; i < this.elements.length; i++ ){ 36 if( this.elements[i].children[0].nodeName.toLowerCase() == 'th'){ 37 this.elements = [].slice.call( this.elements ); 38 this.elements.splice( i, 1 ); 39 } 40 } 41 } 42 } 43 ghostwu.BgColor.init.prototype.setBgColor = function(){ 44 for( var i = 0 ; i < this.elements.length; i++ ){ 45 if ( i % 2 == 0 ) { 46 this.elements[i].className = this.opt['evenClass']; 47 }else { 48 this.elements[i].className = this.opt['oddClass']; 49 } 50 } 51 } 52 ghostwu.BgColor.init.prototype.hover = function(){ 53 var that = this; 54 for( var i = 0 ; i < this.elements.length; i++ ){ 55 this.elements[i].onmouseover = function(){ 56 that.addBg( this ); 57 }; 58 this.elements[i].onmouseout = function(){ 59 that.removeBg( this ); 60 } 61 } 62 } 63 ghostwu.BgColor.init.prototype.addBg = function( curObj ){ 64 this.oldColor = curObj.className; 65 curObj.className = this.opt['activeClass']; 66 } 67 ghostwu.BgColor.init.prototype.removeBg = function( curObj ){ 68 curObj.className = this.oldColor; 69 } 70 /***************隔行变色结束***************/ 71 72 73 74 75 window.g = ghostwu; 76 })();
页面测试代码:
1 <!DOCTYPE html> 2 <html lang="en"> 3 4 <head> 5 <meta charset="UTF-8"> 6 <meta name="viewport" content="width=device-width, initial-scale=1.0"> 7 <meta http-equiv="X-UA-Compatible" content="ie=edge"> 8 <title>隔行变色插件开发 - by ghostwu</title> 9 <style> 10 table { 11 border-collapse: collapse; 12 width: 100%; 13 } 14 15 th, 16 td { 17 padding: 10px 30px; 18 border: 1px solid #ccc; 19 } 20 21 .even-color { 22 background: #ccc; 23 } 24 25 .odd-color { 26 background: #eee; 27 } 28 29 .even-color2 { 30 background: #000; 31 } 32 33 .odd-color2 { 34 background: #666; 35 } 36 37 .current { 38 background: yellow; 39 } 40 41 .active { 42 background: #09f; 43 } 44 45 #box div, 46 #box2 div { 47 margin: 10px; 48 padding: 10px; 49 border: 1px solid #ccc; 50 } 51 </style> 52 <script src="./lib/common2.js"></script> 53 <script> 54 window.onload = function () { 55 var oBg = g.BgColor.Bg({ 56 'activeClass': 'current', 57 'ele': 'table' 58 }); 59 oBg.setBgColor(); 60 oBg.hover(); 61 62 var oBg2 = g.BgColor.Bg({ 63 'activeClass': 'active', 64 'ele': 'div', 65 'context': '#box' 66 }); 67 oBg2.setBgColor(); 68 oBg2.hover(); 69 70 var oBg3 = g.BgColor.Bg({ 71 'activeClass': 'current', 72 'ele': 'div', 73 'evenClass': 'even-color2', 74 'oddClass': 'odd-color2', 75 'context': '#box2' 76 }); 77 oBg3.setBgColor(); 78 oBg3.hover(); 79 } 80 </script> 81 </head> 82 83 <body> 84 <div id="box"> 85 <div></div> 86 <div></div> 87 <div></div> 88 <div></div> 89 </div> 90 <div id="box2"> 91 <div></div> 92 <div></div> 93 <div></div> 94 <div></div> 95 <div></div> 96 <div></div> 97 </div> 98 <table> 99 <tr> 100 <th>姓名</th> 101 <th>性别</th> 102 <th>年龄</th> 103 </tr> 104 <tr> 105 <td>张三</td> 106 <td>man</td> 107 <td>20</td> 108 </tr> 109 <tr> 110 <td>张三</td> 111 <td>man</td> 112 <td>20</td> 113 </tr> 114 <tr> 115 <td>张三</td> 116 <td>man</td> 117 <td>20</td> 118 </tr> 119 <tr> 120 <td>张三</td> 121 <td>man</td> 122 <td>20</td> 123 </tr> 124 <tr> 125 <td>张三</td> 126 <td>man</td> 127 <td>20</td> 128 </tr> 129 <tr> 130 <td>张三</td> 131 <td>man</td> 132 <td>20</td> 133 </tr> 134 <tr> 135 <td>张三</td> 136 <td>man</td> 137 <td>20</td> 138 </tr> 139 </table> 140 </body> 141 142 </html>