显示隐藏的模块化组件
模块化组件包括以下几个文件:
base.css 重置浏览器样式
jquery.js 包括本地引入 和 其他服务器引入 如:cdnjs.com中引入
transitionend.js transitionend动画结束后执行的代码,该方法的兼容性写法,使用js进行封装
s.js 显示隐藏的模块化组件,可以定义为下拉菜单的组件 dropdown.js ,包括三种方式:
1, 全局变量调用:就是去掉(function(){ })() 自我执行的函数套套
2,接口形式调用:使用window.mt = window.mt || {}; window.mt.showHide = showHide;
=======以下是index.html 代码:========
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>Document</title> 6 <link rel="stylesheet" href="css/base.css"> 7 <style> 8 .container { 9 width: 500px; 10 margin: 100px auto; 11 } 12 button { 13 width: 50%; 14 height: 50px; 15 } 16 .box { 17 display: none; 18 height: 450px; 19 width: 500px; 20 background: green; 21 } 22 .transition { 23 -webkit-transition: all .5s; 24 -moz-transition: all .5s; 25 -ms-transition: all .5s; 26 -o-transition: all .5s; 27 transition: all .5s; 28 } 29 /* css3.fade的类 */ 30 .fade { 31 opacity: 0; 32 visibility: visible; 33 } 34 /* css3.slideUpDown的类 */ 35 .slideUpDown { 36 height: 0; 37 padding-top: 0; 38 padding-bottom: 0; 39 } 40 /* css3.slideLeftRight的类 */ 41 .slideLeftRight { 42 width: 0; 43 padding-left: 0; 44 padding-right: 0; 45 } 46 /* css3.fadeSlideUpDown的类 */ 47 .fadeSlideUpDown { 48 opacity: 0; 49 height: 0; 50 padding-top: 0; 51 padding-bottom: 0; 52 } 53 /* css3.fadeSlideLeftRight的类 */ 54 .fadeSlideLeftRight { 55 opacity: 0; 56 width: 0; 57 padding-left: 0; 58 padding-right: 0; 59 } 60 61 </style> 62 </head> 63 <body> 64 <div class="container"> 65 <button class="show">显示</button 66 ><button class="hide">隐藏</button> 67 <div class="box"></div> 68 asdfasd 69 </div> 70 <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script> 71 <script> 72 window.jQuery || document.write('<script src="js/jquery.js"><\/script>') 73 </script> 74 <!-- transitionend.js文件必须放在 index.js 上面,因为是index.js调用transitionend.js --> 75 <script src="js/transitionend.js"></script> 76 <script src="js/s.js"></script> 77 <script> 78 //获取jquery对象 79 var $show = $('.show'), 80 $hide = $('.hide'), 81 $box = $('.box'); 82 83 84 // ========方法一:======== 85 //最初的调用方法,也是最不可取的,因为变量全部都是全局变量 86 //当s.js中的内容全部都是全局作用域的时候还可以直接调用如下: 87 /*css3.slideUpDown.init($box); 88 css3.fadeSlideLeftRight.init($box); 89 90 //给两个按钮绑定单击事件 91 $show.on('click',function(){ 92 css3.slideUpDown.show($box); 93 // js.fadeSlideLeftRight.show($box); 94 }) 95 $hide.on('click',function(){ 96 css3.slideUpDown.hide($box); 97 // js.fadeSlideLeftRight.hide($box); 98 99 }) 100 //给$box对象绑定四个事件 101 $box.on('show shown hide hidden',function(e){ 102 console.log(e.type) 103 })*/ 104 105 // ========方法二:======== 106 //这是使用接口调用的 107 /* var showHide = window.mt.showHide($box,{ 108 css:true, 109 js:true, 110 animation:'slideLeftRight' 111 }) 112 //给两个按钮绑定事件 113 $show.on('click',function(){ 114 //调用show本身要带被调用对象的参数,因为定义的时候就有一个参数。 115 //但该参数在定义 showHide接口方法时就被使用$.proxy(fn,this,$box)给代理调用了, 116 //所以这里可以省略 117 showHide.show(); 118 }) 119 $hide.on('click',function(){ 120 //调用hide本身要带被调用对象的参数,因为定义的时候就有一个参数。 121 //但该参数在定义 showHide接口方法时就被使用$.proxy(fn,this,$box)给代理调用了, 122 //所以这里可以省略 123 showHide.hide(); 124 }) 125 //给$box对象绑定事件 126 $box.on('show shown hide hidden',function(e){ 127 console.log(e.type); 128 })*/ 129 130 // ========方法三:======== 131 // 封装成插件调用 132 var a = $box.showHide({ 133 css3:true, 134 js:false, 135 animation:'slideLeftRight' 136 }); 137 //返回一个对象:k.fn.init [div.box.transition.slideUpDown, prevObject: k.fn.init(1)] 138 console.log(a); 139 140 //给两个按钮绑定单击事件 141 $show.on('click',function(){ 142 $box.showHide('show'); 143 }); 144 $hide.on('click',function(){ 145 $box.showHide('hide'); 146 }) 147 148 //给$box绑定四个事件 149 $box.on('click',function(e){ 150 console.log(e.type); 151 }) 152 </script> 153 </body> 154 </html>
=======以下是base.css代码:========
1 /*重置浏览器的默认样式css reset*/ 2 /*清除内外边距*/ 3 body, h1, h2, h3, h4, h5, h6, p, hr, /*结构元素*/ 4 ul, ol, li, dl, dt, dd, /*列表元素*/ 5 form, fieldset, legend, input, button, select, textarea, /*表单元素*/ 6 th, td, /*表格元素*/ 7 pre { 8 padding: 0; 9 margin: 0; 10 } 11 12 /*重置默认样式*/ 13 body, button, input, select, textarea { 14 /*font: 12px/1 微软雅黑, Tahoma, Helvetica, Arial, 宋体, sans-serif;*/ 15 color: #333; 16 font: 12px/1 "Microsoft YaHei", Tahoma, Helvetica, Arial, SimSun, sans-serif; 17 } 18 h1, h2, h3, h4, h5, h6 { 19 font-size: 100%; 20 font-weight: normal; 21 } 22 em, i { 23 font-style: normal; 24 } 25 26 a { 27 text-decoration: none; 28 } 29 li { 30 list-style-type: none; 31 vertical-align: top; 32 } 33 img { 34 border: none; 35 /*display: block;*/ 36 vertical-align: top; 37 } 38 textarea { 39 overflow: auto; 40 resize: none; 41 } 42 table { 43 border-spacing: 0; 44 border-collapse: collapse; 45 } 46 47 /*常用公共样式*/ 48 .fl { 49 float: left; 50 display: inline; 51 } 52 .fr { 53 float: right; 54 display: inline; 55 } 56 .cf:before, 57 .cf:after { 58 content: " "; 59 display: table; 60 61 } 62 .cf:after { 63 clear: both; 64 } 65 .cf { 66 *zoom: 1; 67 }
=======以下是 transitionend.js 代码:========
1 /*使用js外部文件编写兼容性,以下编写的是: 2 transitionend事件的兼容性写法: 3 分析: 4 1,先判断浏览器兼容什么样的过渡样式,相应的,浏览器就支持对应的过渡事件。 5 6 如何操作检验浏览器是否支持transition属性对应的transitionend事件: 7 在谷歌中检验: 8 1,在控制台输入:document.body.style 返回:CSSStyleDeclaration... 9 2,点开CSSStyleDeclaration... 查找关于支持transition的写法,找到如下: 10 transition 11 webkitTransition 12 对应过渡事件: 13 点击谷歌控制台的眼睛图标: 14 输入transitionend,就会出现关于过渡事件的所有写法: 15 推算下: 16 标准写法:transition 对应事件:transitionend 17 webkit写法:webkitTransition 对应事件:webkitTransitionEnd 18 除了标准写法:连缀写法应该跟样式的写法相同;上面都是使用驼峰命名规则。 19 */ 20 (function(){ 21 22 //使用对象存放存放键值对数据, 23 //键:存放transition是否支持该样式,样式支持才能支持该样式对应的事件 24 //值:存放支持transition该样式对应的事件 25 var transitionEventNames = { 26 webkitTransition:'webkitTransitionEnd',//chrome 27 // MozTransition:'webkittransitionend',//firefox 28 // webkitTransition:'webkittransitionend',//opera 29 transition:'transitionend' //标准,IE要么支持标准,要么就不支持 30 }; 31 32 //存放支持transition该样式对应的事件名 33 var transitionend = '', 34 isSupport = false;//默认不支持 35 36 //遍历对象,判断浏览器支持对象中的那个键名,那么就支持该键对应的事件 37 for (var a in transitionEventNames) { 38 //不存在的属性返回undefined,不存在的对象直接报错。 39 if (document.body.style[a] !== undefined) { 40 transitionend = transitionEventNames[a]; 41 isSupport = true; 42 43 //如果浏览器能支持其中一个,则直接退出,不循环了。 44 break; 45 } 46 } 47 48 //这里面全部都是局部作用域,都是局部变量。外面不可以直接访问。 49 //创建一个全局变量对象window.mt,方便其他地方调用。 50 //1,如果该对象已经存在,则直接使用 51 //2,如果该对象不存在,则创建一个空对象{} 52 window.mt || {}; 53 //给该对象两个属性 54 //name 支持transition样式对应的事件名 55 //isSupport 是否支持transition样式,默认不支持 56 //其实这里就是海外面访问的接口 57 window.mt = { 58 name:transitionend, 59 isSupport:isSupport 60 } 61 })()
=======以下是 s.js 代码:========
1 (function($){ 2 'use strict'; 3 //浏览器支持transition样式对应的事件 4 var mt = window.mt, 5 transitionend = mt.name, 6 isSupport = mt.isSupport; 7 8 //初始化对象$ele 9 //等价于: var init = function($ele,callback){...} 10 function init($ele,callback){ 11 if ($ele.is(':hidden')) { 12 $ele.data('status','hidden'); 13 //判断callback的类型一定要是函数才行,否则不执行。 14 if (typeof callback === 'function') callback(); 15 }else{ 16 $ele.data('status','shown'); 17 } 18 } 19 20 //显示 21 function show($ele,callback){ 22 if ($ele.data('status') === 'show' || $ele.data('status') === 'shown') return; 23 $ele.data('status','show').trigger('show'); 24 callback(); 25 } 26 //隐藏 27 function hide($ele,callback){ 28 if ($ele.data('status') === 'hide' || $ele.data('status') === 'hidden') return; 29 $ele.data('status','hide').trigger('hide'); 30 callback(); 31 } 32 33 //静静的显示,无动画 34 var silent = { 35 init:init, 36 show:function($ele){ 37 show($ele,function(){ 38 $ele.show(); 39 $ele.data('status','shown').trigger('shown'); 40 }); 41 }, 42 hide:function($ele){ 43 hide($ele,function(){ 44 $ele.hide(); 45 $ele.data('status','hidden').trigger('hidden'); 46 }); 47 } 48 } 49 50 var css3 = { 51 fade:{ 52 //init方法被调用时要传参数,所以一定一定记住。 53 //不论在哪里都一样 54 init:function($ele){ 55 css3._init($ele,'fade'); 56 }, 57 //show方法被调用时要传参数,所以一定一定记住。 58 //不论在哪里都一样 59 show:function($ele){ 60 css3._show($ele,'fade'); 61 }, 62 //hide方法被调用时要传参数,所以一定一定记住。 63 //不论在哪里都一样 64 hide:function($ele){ 65 css3._hide($ele,'fade'); 66 } 67 }, 68 slideUpDown:{ 69 //init方法被调用时要传参数,所以一定一定记住。 70 //不论在哪里都一样 71 init:function($ele){ 72 css3._init($ele,'slideUpDown'); 73 }, 74 //show方法被调用时要传参数,所以一定一定记住。 75 //不论在哪里都一样 76 show:function($ele){ 77 css3._show($ele,'slideUpDown'); 78 }, 79 //hide方法被调用时要传参数,所以一定一定记住。 80 //不论在哪里都一样 81 hide:function($ele){ 82 css3._hide($ele,'slideUpDown'); 83 } 84 }, 85 slideLeftRight:{ 86 //init方法被调用时要传参数,所以一定一定记住。 87 //不论在哪里都一样 88 init:function($ele){ 89 css3._init($ele,'slideLeftRight'); 90 }, 91 //show方法被调用时要传参数,所以一定一定记住。 92 //不论在哪里都一样 93 show:function($ele){ 94 css3._show($ele,'slideLeftRight'); 95 }, 96 //hide方法被调用时要传参数,所以一定一定记住。 97 //不论在哪里都一样 98 hide:function($ele){ 99 css3._hide($ele,'slideLeftRight'); 100 } 101 }, 102 fadeSlideUpDown:{ 103 //init方法被调用时要传参数,所以一定一定记住。 104 //不论在哪里都一样 105 init:function($ele){ 106 css3._init($ele,'fadeSlideUpDown'); 107 }, 108 //show方法被调用时要传参数,所以一定一定记住。 109 //不论在哪里都一样 110 show:function($ele){ 111 css3._show($ele,'fadeSlideUpDown'); 112 }, 113 //hide方法被调用时要传参数,所以一定一定记住。 114 //不论在哪里都一样 115 hide:function($ele){ 116 css3._hide($ele,'fadeSlideUpDown'); 117 } 118 }, 119 fadeSlideLeftRight:{ 120 //init方法被调用时要传参数,所以一定一定记住。 121 //不论在哪里都一样 122 init:function($ele){ 123 css3._init($ele,'fadeSlideLeftRight'); 124 }, 125 //show方法被调用时要传参数,所以一定一定记住。 126 //不论在哪里都一样 127 show:function($ele){ 128 css3._show($ele,'fadeSlideLeftRight'); 129 }, 130 //hide方法被调用时要传参数,所以一定一定记住。 131 //不论在哪里都一样 132 hide:function($ele){ 133 css3._hide($ele,'fadeSlideLeftRight'); 134 } 135 } 136 } 137 //css3 内部的 初始化对象$ele 公共部分 138 css3._init = function($ele,className){ 139 //把可能需要修改的内容尽量写在最外面一层,不需要修改都尽量写在底层 140 //给对象添加过渡属性 141 $ele.addClass('transition'); 142 init($ele,function(){ 143 $ele.addClass(className); 144 }); 145 } 146 //css3 内部的 显示的公共部分 147 css3._show = function($ele,className){ 148 show($ele,function(){ 149 $ele.off(transitionend).one(transitionend,function(){ 150 $ele.data('status','shown').trigger('shown'); 151 }); 152 $ele.show(); 153 setTimeout(function(){ 154 $ele.removeClass(className); 155 },20); 156 }); 157 } 158 //css3 内部的 隐藏的公共部分 159 css3._hide = function($ele,className){ 160 hide($ele,function(){ 161 $ele.off(transitionend).one(transitionend,function(){ 162 $ele.hide(); 163 $ele.data('status','hidden').trigger('hidden'); 164 }); 165 $ele.addClass(className); 166 }); 167 } 168 169 var js = { 170 fade:{//fadeIn() fadeOut() 淡入淡出 171 init:function($ele){ 172 js._init($ele); 173 }, 174 show:function($ele){ 175 js._show($ele,'fadeIn'); 176 }, 177 hide:function($ele){ 178 js._hide($ele,'fadeOut'); 179 } 180 }, 181 slideUpDown:{// slideDown() slideUp() 上下滚动 182 init:function($ele){ 183 js._init($ele); 184 }, 185 show:function($ele){ 186 js._show($ele,'slideDown'); 187 }, 188 hide:function($ele){ 189 js._hide($ele,'slideUp'); 190 } 191 }, 192 slideLeftRight:{ 193 init:function($ele){ 194 js._customInit($ele,{ 195 'width':'0', 196 'padding-left':'0', 197 'padding-right':'0' 198 }); 199 }, 200 show:function($ele){ 201 js._customShow($ele); 202 }, 203 hide:function($ele){ 204 js._customHide($ele,{ 205 'width':'0', 206 'padding-left':'0', 207 'padding-right':'0' 208 }); 209 } 210 }, 211 fadeSlideUpDown:{ 212 init:function($ele){ 213 js._customInit($ele,{ 214 'opacity':'0', 215 'height':'0', 216 'padding-top':'0', 217 'padding-bottom':'0' 218 }); 219 }, 220 show:function($ele){ 221 js._customShow($ele); 222 }, 223 hide:function($ele){ 224 js._customHide($ele,{ 225 'opacity':'0', 226 'height':'0', 227 'padding-top':'0', 228 'padding-bottom':'0' 229 }); 230 } 231 }, 232 fadeSlideLeftRight:{ 233 init:function($ele){ 234 js._customInit($ele,{ 235 'opacity':'0', 236 'width':'0', 237 'padding-left':'0', 238 'padding-right':'0' 239 }); 240 }, 241 show:function($ele){ 242 js._customShow($ele); 243 }, 244 hide:function($ele){ 245 js._customHide($ele,{ 246 'opacity':'0', 247 'width':'0', 248 'padding-left':'0', 249 'padding-right':'0' 250 }); 251 } 252 } 253 } 254 255 js._init = function($ele){ 256 //1,这里使用的是JS进行显示隐藏,所以就不用css代码来实现 257 //2,移除 .transition css写法的类,是为了防止进行两次动画。而出现异常 258 $ele.removeClass('transition'); 259 init($ele); 260 } 261 js._customInit = function($ele,options){ 262 //只用js进行操作,防止添加CSS .transition类名的出现异常 263 $ele.removeClass('transition'); 264 //就是页面加载的时候就获得该对象的数据 265 var styles = {}; 266 for (var p in options) { 267 styles[p] = $ele.css(p); 268 } 269 //把值放到$ele标签中进行传递 270 $ele.data('styles',styles); 271 272 init($ele,function(){ 273 $ele.css(options); 274 }); 275 }; 276 js._show = function($ele,mode){ 277 show($ele,function(){ 278 $ele.stop()[mode](function(){ 279 $ele.data('status','shown').trigger('shown'); 280 }); 281 }); 282 }; 283 js._customShow = function($ele){ 284 show($ele,function(){ 285 var styles = $ele.data('styles');//获取对象的属性 286 $ele.show(); 287 $ele.stop().animate(styles, function() { 288 $ele.data('status','shown').trigger('shown'); 289 }); 290 }); 291 }; 292 js._hide = function($ele,mode){ 293 hide($ele,function(){ 294 $ele.stop()[mode](function(){ 295 $ele.data('status','hidden').trigger('hidden'); 296 }); 297 }); 298 }; 299 js._customHide = function($ele,options){ 300 hide($ele,function(){ 301 $ele.stop().animate(options, function() { 302 $ele.hide(); 303 $ele.data('status','hidden').trigger('hidden'); 304 }); 305 }) 306 } 307 308 /* 309 //需要传的参数,及传时的默认参数 310 var defaults = { 311 css3:false, 312 js:false, 313 animation:'fade' 314 }; 315 316 function showHide($ele,options){ 317 //将两个或更多对象的内容合并到第一个对象。第一个对象中没有的内容才能添加进去。 318 options = $.extend({},defaults,options); 319 var mode = null; 320 if (options.css3 && isSupport) {//css animation 321 mode = css3[options.animation] || css3[defaults.animation]; 322 }else if (options.js){//js animation 323 mode = js[options.animation] || js[defaults.animation]; 324 }else {//no animation 325 mode = silent; 326 }; 327 328 mode.init($ele); 329 return { 330 show:mode.show, 331 hide:mode.hide 332 // show:$.proxy(mode.show,this,$ele), 333 // hide:$.proxy(mode.hide,this,$ele) 334 }; 335 // if (options.css3 && transition.isSupport) {//css animation 336 // css3[options.animation].init($ele); 337 // return { 338 // show:css3[options.animation].show, 339 // hide:css3[options.animation].hide 340 // }; 341 // }else if (options.js){//js animation 342 // js[options.animation].init($ele); 343 // return { 344 // show:js[options.animation].show, 345 // hide:js[options.animation].hide 346 // } 347 // }else {//no animation 348 // silent.init($ele); 349 // return { 350 // show:silent.show, 351 // hide:silent.hide 352 // }; 353 // } 354 } 355 356 //短路操作,如果window.mt = undefined / [空字符串],隐式转换为false。 357 //则创建一个空对象,window.mt = {}; 358 //window.mt = 对象/字符串,则就使用该对象 359 window.mt = window.mt || {}; 360 361 window.mt.showHide = showHide; 362 */ 363 364 365 //有三个对象要调用 silent,css3,js 366 //cilent [ show,hide ] 367 //css3 [ show,hidee ] 368 //js [ show,hide] 369 var defaults = { 370 css3:true, 371 js:false, 372 animation:'fade' 373 } 374 375 /** 376 * 返回一个对象,两个方法show hide 377 * @param {obj} $ele jquery对象 378 * @param {obj} options 对象三个参数,指定使用哪种方式显示 379 * @return {返回一个对象} 包括show(),hide() 380 */ 381 function showHide($ele,options){ 382 //如果参数传的不正确,则使用默认参数 383 //将两个或更多对象的内容合并到第一个对象。第一个对象中没有的内容才能添加进去。 384 // options = $.extend({},defaults,options); 385 var mode; 386 387 //判断是哪种方式为true,就选择哪种方式进行显示 388 if (options.css3 && isSupport) { 389 mode = css3[options.animation] || css3.fade; 390 }else if (options.js){ 391 mode = js[options.animation] || js.fade; 392 }else{ 393 mode = silent; 394 } 395 mode.init($ele); 396 397 return { 398 // show:mode.show, //被调用时,show函数是要传显示对象的。 399 // hide:mode.hide //被调用时,hide函数是要传隐藏对象的。 400 show:$.proxy(mode.show,this,$ele), 401 hide:$.proxy(mode.hide,this,$ele) 402 } 403 404 } 405 //创建对外可以调用的接口 406 window.mt = window.mt || {}; 407 window.mt.showHide = showHide; 408 409 410 //封装成插件,语法:$.fn.extend({name:function(){...}}) 411 $.fn.extend({ 412 //插件名称:function(){...} 413 showHide:function(option){ 414 //根据option参数不同,返回值不同 415 //1,参数为object 返回this,就是返回当前调用的对象 416 // each(...) 表示哪种类型的 this 而已 417 // 使用$box.showHide({css:true,js:flase,animation:slideUpDown}) 418 // 返回的是 另一个 样式不同的 this,对象是不变的,还是返回$box对象,这个对象可能隐藏,可能显示。 419 // 返回值:k.fn.init [div.box.transition.slideUpDown, prevObject: k.fn.init(1)] 420 return this.each(function(){ 421 var $this = $(this),//调用当前该插件的对象 422 423 //$.extend 合并多个对象的属性,返回到第一个对象中。 424 //typeof option === 'object' && option 短路操作,非常重要, 425 //解析: 426 //1,typeof option === 'object' 为true 则返回 option对象 ,option覆盖defaults,返回一个新对象 427 //2,typeof option === 'object' 为false 则返回 false 所以这里options = defaults。 428 options = $.extend({},defaults,typeof option === 'object' && option), 429 //从当前标签中获取showHide的值,该值存放的是具体的操作方式 430 mode = $this.data('showHide'); 431 //如果该操作方式的的值为空,那么就执行一次showHide获取操作方式,并存放在当前调用的标签中。 432 //这里的函数只执行一次,效率高。性能好。 433 if (!mode) { 434 $this.data('showHide',mode=showHide($this,options)); 435 } 436 437 //mode 是操作方式 mode[option]如果是show hide 就是显示隐藏,只要判断是否是函数即可 438 //当option是字符串,且该字符跟mode组合,返回是函数时,就直接执行该函数。 439 if (typeof mode[option] === 'function') { 440 mode[option](); 441 } 442 }) 443 } 444 }) 445 })(jQuery)
创建四个文件,引入两个 jquery.js 文件即可正常显示隐藏操作