显示隐藏模块封装
来源:2-11 将显示隐藏封装成模块--完善
soso_crazy
2019-04-03 18:18:55
<!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>显示与隐藏模块</title>
<link rel="stylesheet" href="../../作业素材/code/css/base.css">
<script src="../js/jquery-3.3.1.js"></script>
<script src="../js/transition.js"></script>
<script src="../js/showhide模块.js"></script>
<style>
body {
width: 400px;
margin: 0 auto;
position: relative;
}
.btn {
width: 50%;
height: 30px;
}
#box {
display: none;
position: absolute;
width: 100%;
height: 200px;
background-color: red;
overflow: hidden;
}
.transition {
transition: all 0.5s;
-webkit-transition: all 0.5s;
-moz-transition: all 0.5s;
-ms-transition: all 0.5s;
-o-transition: all 0.5s;
}
.fadeOut {
visibility: visible;
opacity: 0;
}
.slideUpDownCollapse {
/* 当移除了这个类,高度就会显示为原本高度 */
height: 0 !important;
/* id的优先级比class高,所以#box的高度会覆盖这里的类高度,加上!important使得优先级最高 */
padding-top: 0 !important;
/* 如果是靠内容和padding撑开高度,就设置padding-top和padding-bottom */
padding-bottom: 0 !important;
}
.slideLeftRightCollapse {
/* 当移除了这个类,高度就会显示为原本宽度 */
width: 0 !important;
/* id的优先级比class高,所以#box的宽度会覆盖这里的类宽度,加上!important使得优先级最高 */
padding-left: 0 !important;
/* 如果是靠内容和padding撑开宽度,就设置padding-left和padding-right */
padding-right: 0 !important;
}
</style>
</head>
<body>
<button id="btn-show" class="btn">显示</button><button id="btn-hide" class="btn">隐藏</button>
<div id="box" class=""></div>
<button class="btn">显示2</button>
<script>
console.log(window.muduoduo.transition.end);
console.log(window.muduoduo.transition.isSupport);
// var silent = {
// show: function($elem) {
// // 方法一: $elem.html('<P>我要显示了</P>'); 将函数要执行的语句放在实例化函数中执行
// // $elem.html('<P>我要显示了</P>'); 将函数要执行的语句放在实例化函数中执行
// // setTimeout(function() { 将函数要执行的语句放在实例化函数中执行
// // $elem.html($elem.html() + '<P>我已经显示了</P>');
// // }, 1000)
// // 方法二:
// // show:function($elem,showCallback,shownCallback){
// // if (typeof showCallback === 'function') { //适合发布订阅的方式,发布消息就是触发事件,订阅消息就是绑定事件
// // showCallback();
// // }
// // $elem.show(); show方法是需要jq对象元素来调用的,不能是函数调用
// // if (typeof shownCallback === 'function') {
// // shownCallback();
// // }
// // 方法三:
// $elem.trigger('show');
// $elem.show();
// $elem.trigger('shown');
// },
// hide: function($elem) {
// $elem.trigger('hide');
// $elem.hide();
// $elem.trigger('hidden');
// }
// };
// var css3 = {
// fade: {
// show: function() {},
// hide: function() {}
// },
// slideUpDown: {
// show: function() {},
// hide: function() {}
// },
// slideLeftRight: {
// show: function() {},
// hide: function() {}
// },
// fadeSlideUpDown: {
// show: function() {},
// hide: function() {}
// },
// fadeSlideLeftRight: {
// show: function() {},
// hide: function() {}
// }
// };
// var js = {
// fade: {
// show: function() {},
// hide: function() {}
// },
// slideUpDown: {
// show: function() {},
// hide: function() {}
// },
// slideLeftRight: {
// show: function() {},
// hide: function() {}
// },
// fadeSlideUpDown: {
// show: function() {},
// hide: function() {}
// },
// fadeSlideLeftRight: {
// show: function() {},
// hide: function() {}
// }
// };
var $box = $('#box');
// 方法二的调用
// $('#btn-show').on('click', function() {
// silent.show($box, function() {
// $box.html('<P>我要显示了</P>');
// }, function() {
// setTimeout(function() {
// $box.html($box.html() + '<P>我已经显示了</P>');
// }, 1000)
// });
// });
// silent.init($box); //初始化,只执行一次
// css3.fade.init($box);
// css3.slideLeftRight.init($box);
// js.slideLeftRight.init($box);
// js.fadeSlideUpDown.init($box);
// js.fadeSlideLeftRight.init($box);
// var showHide = window.muduoduo.showHide($box, {
// css3: true,
// animation: 'fade'
// });
$box.showHide({
css3: false,
js: false,
animation: 'fade'
})
// 发布:触发事件
$('#btn-show').on('click', function() {
// silent.show($box);
// css3.fade.show($box);
// css3.slideLeftRight.show($box);
// js.slideLeftRight.show($box);
// js.fadeSlideUpDown.show($box);
// js.fadeSlideLeftRight.show($box);
// showHide.show($box); //调用showHide中的show方法
// showHide.show();
$box.showHide('show');
});
$('#btn-hide').on('click', function() {
// silent.hide($box);
// css3.fade.hide($box);
// css3.slideLeftRight.hide($box);
// js.slideLeftRight.hide($box);
// js.fadeSlideUpDown.hide($box);
// js.fadeSlideLeftRight.hide($box);
// showHide.hide($box);
// showHide.hide();
$box.showHide('hide');
});
// 订阅:接收事件
$box.on('show shown hide hidden', function(e) {
// console.log(e); 打印结果是show shown hide hidden
if (e.type === 'show') {
$box.html('<P>我要显示了</P>');
} else if (e.type === 'shown') {
setTimeout(function() {
$box.html($box.html() + '<P>我已经显示了</P>');
}, 1000)
}
});
// 订阅:接收事件
$box.on('show shown hide hidden', function(e) {
if (e.type === 'show') {
$box.css('backgroundColor', 'yellow');
} else if (e.type === 'shown') {
setTimeout(function() {
$box.css('backgroundColor', '');
}, 1000)
}
});
// 以上两个接收事件改变内容互补影响,不用在各自接收事件上修改程序,方便多人协作,发布消息(触发事件),新增者只需订阅发布者的消息(绑定消息)就可以修改
</script>
</body>
</html>
(function($) { //将showhide封装成模块:放在自执行的匿名函数中
'use strict';
var transition = window.muduoduo.transition;
function init($elem, hiddenCallback) {
if ($elem.is(':hidden')) {
$elem.data('status', 'hidden');
if (typeof hiddenCallback === 'function') {
hiddenCallback();
}
$elem.addClass('fadeOut');
} else {
$elem.data('status', 'shown');
}
};
function show($elem, Callback) {
if ($elem.data('status') === 'show') return; //当已是显示状态,不再重复执行show的代码
if ($elem.data('status') === 'shown') return; //当已是显示状态,不再重复执行shown的代码
$elem.data('status', 'show').trigger('show'); // 第一次没执行状态,status是undefined,当执行完第一次之后,status是show 不再重复执行代码
Callback();
};
function hide($elem, Callback) {
if ($elem.data('status') === 'hide') return; //当已是隐藏状态,不再重复执行hide的代码
if ($elem.data('status') === 'hidden') return; //当已是隐藏状态,不再重复执行hidden的代码
$elem.data('status', 'hide').trigger('hide');
Callback();
};
var silent = {
init: init, //初始化函数名init,函数名等于函数本身
show: function($elem) {
show($elem, function() {
$elem.show();
$elem.data('status', 'shown').trigger('shown');
});
},
hide: function($elem) {
hide($elem, function() {
$elem.hide();
$elem.data('status', 'hidden').trigger('hidden');
})
}
};
var css3 = {
fade: {
init: function($elem) {
css3._init($elem, 'fadeOut');
},
show: function($elem) {
css3._show($elem, 'fadeOut');
},
hide: function($elem) {
css3._hide($elem, 'fadeOut');
}
},
slideUpDown: {
init: function($elem) {
$elem.height($elem.height()); /* 获取高度,并把获取到的高度设置给到jq元素的高度 */
/* 当$elem没有设置高度,由内容撑开时,slideUpDownCollapse将高度变为0有过渡效果 */
css3._init($elem, 'slideUpDownCollapse');
},
show: function($elem) {
css3._show($elem, 'slideUpDownCollapse');
},
hide: function($elem) {
css3._hide($elem, 'slideUpDownCollapse');
}
},
slideLeftRight: {
init: function($elem) {
$elem.width($elem.width()); /* 获取宽度,并把获取到的宽度设置给到jq元素的高度 */
/* 当$elem没有设置宽度,由内容撑开时,slideLeftRightCollapse将高度变为0有过渡效果 */
css3._init($elem, 'slideLeftRightCollapse');
},
show: function($elem) {
css3._show($elem, 'slideLeftRightCollapse');
},
hide: function($elem) {
css3._hide($elem, 'slideLeftRightCollapse');
}
},
fadeSlideUpDown: {
show: function() {},
hide: function() {}
},
fadeSlideLeftRight: {
show: function() {},
hide: function() {}
}
};
css3._init = function($elem, className) {
$elem.addClass('transition');
init($elem, function() { //传入参数为jq对象,回调函数
$elem.addClass(className); //当初始状态是隐藏时,添加class
});
};
css3._show = function($elem, className) {
show($elem, function() {
// 如果当前动画没有执行完毕,就执行另一个动画,那么之前的动画是不会停止的,会继续执行,直到结束,所以有的时候显示之后突然显示,就是之前消失的动画没有执行完毕。 为了解决这个问题,要将jq元素解绑过渡动画,再绑定一次过渡
$elem.off(transition.end).one(transition.end, function() { //transition.end是transition.js中的属性值
$elem.trigger('shown'); //执行自定义的shown方法
});
$elem.show(); //$elem.show();和$elem.css执行顺序一前一后,但是执行非常快,可以认为同步执行,不存在过渡效果,讲它们异步执行setTimeout
// transition过渡时遇到没有效果,可以考虑是否异步问题
setTimeout(function() {
$elem.removeClass(className);
}, 20);
});
};
css3._hide = function($elem, className) {
hide($elem, function() {
$elem.off(transition.end).one(transition.end, function() { //transition结束有transitionend事件
// 绑定事件在触发事件之前
// one()只绑定一次时间 之前解绑时间,即当快速按下显示和隐藏按钮时,show shown hide hidden不会按顺序执行,可能会没有shown
$elem.hide();
$elem.data('status', 'hidden').trigger('hidden');
});
$elem.addClass(className);
});
};
var js = {
fade: {
init: function($elem) {
js._init($elem);
},
show: function($elem) {
js._show($elem, 'fadeIn');
},
hide: function($elem) {
js._hide($elem, 'fadeOut');
}
},
slideUpDown: {
init: function($elem) {
js._init($elem);
},
show: function($elem) {
js._show($elem, 'slideDown');
},
hide: function($elem) {
js._hide($elem, 'slideUp');
}
},
slideLeftRight: {
init: function($elem) { //初始化时获取元素最初始的宽度
js._init($elem, {
'width': '0',
'padding-left': '0',
'padding-right': '0'
})
},
show: function($elem) {
js._customShow($elem);
},
hide: function($elem) {
js._customHide($elem, {
'width': 0,
'padding-left': 0,
'padding-right': 0
});
}
},
fadeSlideUpDown: {
init: function($elem) { //初始化时获取元素最初始的宽度
js._customInit($elem, {
'opacity': 0,
'height': 0,
'padding-top': 0,
'padding-down': 0
})
},
show: function($elem) {
js._customShow($elem);
},
hide: function($elem) {
js._customHide($elem, {
'opacity': 0,
'height': 0,
'padding-top': 0,
'padding-bottom': 0
});
}
},
fadeSlideLeftRight: {
init: function($elem) {
js._customInit($elem, {
'opacity': 0,
'width': 0,
'padding-left': 0,
'padding-right': 0
})
},
show: function($elem) {
js._customShow($elem);
},
hide: function($elem) {
js._customHide($elem, {
'opacity': 0,
'width': 0,
'padding-top': 0,
'padding-bottom': 0
});
}
}
};
js._init = function($elem, hiddenCallback) { //hiddenCallback做为参数,需要用时再传入,不需要用就不传入
$elem.removeClass('transition'); //transition的类和js争做动画效果,避免这种情况,需要移除transition的类
init($elem, hiddenCallback); //调用之前定义的init函数
};
js._customInit = function($elem, options) { //用于fadeSlideUpDown的自定义
var styles = {};
for (var p in options) {
styles[p] = $elem.css(p);
}
$elem.data('styles', styles); //设置数据styles的data值为styles,将局部的变量可以在其他函数中使用
js._init($elem, function() {
$elem.css(options);
})
};
js._show = function($elem, mode) { //mode用来接收淡入淡出等的模式 模式是字符串,而且是参数,不能用.要用[]
show($elem, function() {
$elem.stop()[mode](function() { //stop()暂停之前执行的动画,再开始新动画
$elem.data('status', 'shown').trigger('shown');
})
})
};
js._customShow = function($elem) {
show($elem, function() {
$elem.show(); //执行最上边定义的show函数
$elem.stop().animate($elem.data('styles'), function() { //动画结束后
$elem.data('status', 'shown').trigger('shown');
});
});
};
js._hide = function($elem, mode) {
hide($elem, function() {
$elem.stop()[mode](function() { //如果点击了显示按钮立刻点击隐藏按钮,stop()会立刻停止显示按钮去执行隐藏按钮
$elem.data('status', 'hidden').trigger('hidden');
});
});
};
js._customHide = function($elem, options) {
hide($elem, function() {
$elem.stop().animate(options, function() { //动画结束后
$elem.hide(); //执行最上边定义的hide函数
$elem.data('status', 'hidden').trigger('hidden');
});
});
};
// 设置默认参数,值为true时,执行相应的方法
var defaults = {
css3: false,
js: false,
animation: 'fade'
};
function showHide($elem, options) {
var mode = null;
if (options.css3 && transition.isSupport) { //options.css3为真,而且浏览器支持 css3的transition过渡
mode = css3[options.animation] || css3[defaults.animation]; //如果传错参数,没有覆盖到defaults相同的属性,就用defaults的属性
} else if (options.js) { //js的animation动画
mode = js[options.animation] || js[defaults.animation];
} else { //没有动画 no animation
mode = silent;
}
mode.init($elem);
return { //返回show和hide
// show: mode.show,
show: $.proxy(mode.show, this, $elem), //mode.show是函数 第二个参数是this的指向 this 第三个参数是传入参数$elem
hide: $.proxy(mode.hide, this, $elem)
};
}
//假设外部传了options为 {css3:true} 那么就会覆盖defaults中相同的css3属性的值,将false变为true
// // 局部对象调用到全局,运用之前的全局对象window.muduoduo
// window.muduoduo = window.muduoduo || {};
// window.muduoduo.showHide = showHide;
// 使用插件形式
$.fn.extend({
showHide: function(option) { //判断option是否是对象
return this.each(function() { //为了能连缀. .,返回this
var $this = $(this),
options = $.extend({}, defaults, typeof option === 'object' && option), //将外部传入的参数options覆盖defaults相同属性放到空对象中,将赋值后的对象给options
//&&是短路操作符,如果typeof option==='object'为真,则将option的值传入showHide,如果typeof option==='object'为假,不会执行&&后面的option,将false传入showHide
//如果把false传给showHide, option的值没有覆盖到defaults 就是不使用外部参数,使用defaults的值
mode = $this.data('showHide');
if (!mode) { //没有mode 是第一次执行
$this.data('showHide', mode = showHide($this, options));
}
if (typeof mode[option] === 'function') {
mode[option]();
}
})
}
})
})(jQuery);
(function() {
var transitionEndEventName = {
transition: 'transitionend',
MozTransition: 'transitionend',
WebkitTransition: 'WebkitTransitionEnd',
OTransition: 'oTransitionEnd otransitionend'
};
var transitionEnd = '', //在自执行的匿名函数中定义的是局部作用域
isSupport = false; //在自执行的匿名函数中定义的是局部作用域
//一般都存在body元素,如果不用body判断是否有transitionend,可以用document.create('DOM元素'),再用document.创建的DOM元素.style[name]
for (var name in transitionEndEventName) {
var ele = document.body || document.documentElement;
if (ele.style[name] !== undefined) { //存在transitionend
transitionEnd = transitionEndEventName[name];
isSupport = true;
break; //如果找到就无需继续遍历,立刻跳出
}
}
//全局作用域中暴露获得的结果
window.muduoduo = window.muduoduo || {}; //如果window存在muduoduo就用muduoduo 本身,原来不存在第一次用就是一个空对象
window.muduoduo.transition = {
end: transitionEnd,
isSupport: isSupport
};
})();
为什么将css3:false,和js:false,就出现问题?
1回答
好帮手慕星星
2019-04-03
你好,如果css3和js都设置false的话,那么执行的就是slient中的事件:
开始就先init初始化:
初始化之后就会添加上fadeOut类,这个类中设置了透明度:
点击显示按钮之后其实是显示出来的,只不过有透明度而已:
还是之前的情况,把添加的这个类删掉即可。
自己测试下,祝学习愉快!
相似问题