原生js实现自定义alert风格和实现

时间:2023-03-08 23:26:33
原生js实现自定义alert风格和实现

2018年6月29 最新更新

添加函数节流,解决多次点击问题,添加单例模式,提高代码性能。

 <!DOCTYPE html>
<html lang="en"> <head>
<meta charset="UTF-8">
<title>自定义alert</title>
<style type="text/css">
html,
body {
padding: ;
margin: ;
}
/* //防止鼠标双击选中文字
*/ div { -khtml-user-select: none;
/*早期浏览器*/
user-select: none;
}
/* //来自animated.css的样式 */ .animated {
animation-duration: 1s;
animation-fill-mode: both;
} @keyframes bounceInDown {
from,
%,
%,
%,
to {
animation-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000);
} % {
opacity: ;
transform: translate3d(, -3000px, );
} % {
opacity: ;
transform: translate3d(, 25px, );
} % {
transform: translate3d(, -10px, );
} % {
transform: translate3d(, 5px, );
} to {
transform: none;
display: none;
}
} .bounceInDown {
animation-name: bounceInDown;
} </style>
</head> <body>
<button onclick="test" id="btn">点我测试</button>
<script type="text/javascript">
(function(win, doc) {
var firstTime = true,
startTime = ; function alert(txt, autoTime, top) {
//工具函数
function $(dom) {
return document.querySelector(dom);
}
//单利模式核心
var getSingle = function(fn) {
var result;
return function() {
return (result || (result = fn.apply(this, arguments)));
}
} //函数节流
var throttle = function(fn, interval) {
var __self = fn; // 保存需要被延迟执行的函数引用// 是否是第一次调用
return function() {
var args = arguments,
__me = this;
if (firstTime) { // 如果是第一次调用,不需延迟执行
__self.apply(__me, args);
return firstTime = false;
} var endTime = new Date() * ; //时间大于3000秒下次执行
if (endTime - startTime > (autoTime || )) {
__self.apply(__me, args);
}
};
}; //创建div代码
var createDiv = function() { var div = doc.createElement("div");
div.style.backgroundColor = " #22b9ff";
div.style.color = " #fff";
div.style.position = " fixed";
div.style.zIndex = ;
div.style.height = " 60px";
div.style.top = top || "10%";
div.style.left = "50%";
div.style.lineHeight = " 60px";
div.style.borderRadius = " 4px";
div.style.fontSize = " 20px";
div.style.textAlign = "center";
div.style.padding = "0 10px";
div.className = "animated bounceInDown";
div.id = "alert";
div.innerHTML = txt || "不能为空!";
return div;
} var createSingleDiv = getSingle(createDiv); return throttle(function() { var div = createSingleDiv(); //创建div
startTime = new Date() * ; //初始位置
$("body").appendChild(div);
//动态调整位置
var alertWidth = win.getComputedStyle($("#alert"), null).width;
div.style.marginLeft = -parseInt(alertWidth) / + "px";
setTimeout(function() {
$("body").removeChild(div);
}, autoTime || );
}).apply(this, null);
} win.alert = alert; //导出 })(window, document); document.getElementById('btn').onclick = function() {
alert("手机号不能为空!");
} </script>
</body> </html>

上篇文章介绍了自定义confirm的必要性,可以说alert是比confirm更为常用的浏览器自带组件了。但更因为常用,而原生组件无论是样式还是体验都不是很好,所以更加有必要自定义。

此为改造的背景。

本来第一版是自定义的第一版是没有防止提示期间,用户进行其他操作的透明层的;js代码是这样:

  <script type="text/javascript">
window.alert = function(text) { //实现alert
var div = document.createElement("div");
div.style.backgroundColor = " #22b9ff";
div.style.color = " #fff";
div.style.position = " fixed";
div.style.zIndex = 9999999;
div.style.height = " 60px";
div.style.top = " 10%";
div.style.left = "50%";
div.style.lineHeight = " 60px";
div.style.borderRadius = " 4px";
div.style.fontSize = " 20px";
div.style.textAlign = "center";
div.style.padding = "0 10px";
div.className = "animated bounceInDown";
div.id = "alert";
div.innerHTML = text;
document.getElementsByTagName("body")[0].appendChild(div);
var selfObj = document.getElementById("alert");
//动态调整位置
var alertWidth = window.getComputedStyle(selfObj, null).width;
div.style.marginLeft = -parseInt(alertWidth) / 2 + "px";
setTimeout(function() {
document.getElementsByTagName("body")[0].removeChild(div);
}, 30000);
}
alert("这是自定义的alert");
</script>

后来想到实际的alert效果,提示期间是无法做其它操作的,于是改造为这样

 <script type="text/javascript">
window.alert = function(text) {
//透明遮罩层
var mask = document.createElement("div");
mask.style.position = " fixed";
mask.style.zIndex = 1000000;
mask.style.top = 0;
mask.style.bottom = 0;
mask.style.left = 0;
mask.style.right = 0;
//实现alert
var div = document.createElement("div");
div.style.backgroundColor = " #22b9ff";
div.style.color = " #fff";
div.style.position = " fixed";
div.style.zIndex = 9999999;
div.style.height = " 60px";
div.style.top = " 10%";
div.style.left = "50%";
div.style.lineHeight = " 60px";
div.style.borderRadius = " 4px";
div.style.fontSize = " 20px";
div.style.textAlign = "center";
div.style.padding = "0 10px";
div.className = "animated bounceInDown";
div.id = "alert";
div.innerHTML = text;
document.getElementsByTagName("body")[0].appendChild(div);
document.getElementsByTagName("body")[0].appendChild(mask);
var selfObj = document.getElementById("alert");
//动态调整位置
var alertWidth = window.getComputedStyle(selfObj, null).width;
div.style.marginLeft = -parseInt(alertWidth) / 2 + "px";
setTimeout(function() {
document.getElementsByTagName("body")[0].removeChild(div);
document.getElementsByTagName("body")[0].removeChild(mask);
}, 3000);
}
alert("这是自定义的alert");
</script>

值得一提的是动态位置的调整哪块,通过实时计算alert组件的宽度,保证组件始终处于中间位置,至于alert组件的显示时间,就自己改源代码时间吧。

整体代码如下

 <!DOCTYPE html>
<html lang="en"> <head>
<meta charset="UTF-8">
<title>自定义alert</title>
<style type="text/css">
html,
body {
padding: ;
margin: ;
}
/* //防止鼠标双击选中文字
*/ div { -khtml-user-select: none;
/*早期浏览器*/
user-select: none;
}
/* //来自animated.css的样式 */ .animated {
animation-duration: 1s;
animation-fill-mode: both;
} @keyframes bounceInDown {
from,
%,
%,
%,
to {
animation-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000);
} % {
opacity: ;
transform: translate3d(, -3000px, );
} % {
opacity: ;
transform: translate3d(, 25px, );
} % {
transform: translate3d(, -10px, );
} % {
transform: translate3d(, 5px, );
} to {
transform: none;
}
} .bounceInDown {
animation-name: bounceInDown;
} </style>
</head> <body>
<script type="text/javascript">
(function(win,doc) {
var alert = function(text, time, top) {
text = text || "确定删除?",time = time || ,top = top || "10%";//增加默认值,增强健壮性
var body=doc.getElementsByTagName("body")[];//优化dom
//实现alert
var div = doc.createElement("div");
div.style.backgroundColor = " #22b9ff";
div.style.color = " #fff";
div.style.position = " fixed";
div.style.zIndex = ;
div.style.height = " 60px";
div.style.top = top;
div.style.left = "50%";
div.style.lineHeight = " 60px";
div.style.borderRadius = " 4px";
div.style.fontSize = " 20px";
div.style.textAlign = "center";
div.style.padding = "0 10px";
div.className = "animated bounceInDown";
div.id = "alert";
div.innerHTML = text;
body.appendChild(div);
var selfObj = doc.getElementById("alert");
//动态调整位置
var alertWidth = win.getComputedStyle(selfObj, null).width;
div.style.marginLeft = -parseInt(alertWidth) / + "px";
setTimeout(function() {
body.removeChild(div);
}, time);
}
win.alert=alert;//导出
})(window,document);
alert();
</script>
</body> </html>

2018年6月24日更新  增加参数的默认值,该少dom访问慢的问题,使用闭包包裹,alert导出覆盖window

在整体代码中,有一个用来防止双击选中文字的css样式,值得关注一下。

样式中的css动画来自知名的动画库animation.css。因此,可以根据实际业务需要更换动画类。基本就是这样。

仿京东注册web移动端提示。

 <!DOCTYPE html>
<html lang="en"> <head>
<meta charset="UTF-8">
<title>自定义alert</title>
<meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0,user-scalable=no" name="viewport" />
<style type="text/css">
html,
body {
padding: ;
margin: ;
}
/* //防止鼠标双击选中文字
*/ div { -khtml-user-select: none;
/*早期浏览器*/
user-select: none;
}
/* //来自animated.css的样式 */ @-webkit-keyframes fadeIn {
% {
opacity: .
}
% {
opacity:
}
% {
opacity: .
}
} .toast {
-webkit-animation-name: fadeIn;
-webkit-animation-duration: 3s;
-webkit-animation-iteration-count: ;
-webkit-animation-delay: 0s;
-webkit-transition: all .3s ease;
-moz-transition: all .3s ease;
transition: all .3s ease;
max-width: %;
color:#fff;
background: #2B2B2B;
padding: 8px 15px;
display: inline-table;
border-radius: 3px;
} .toast-ui {
position: fixed;
top:%;
color:#fff;
width: %;
text-align: center;
} .maskfadeout {
display: block;
-webkit-animation: fadeout 3s linear;
animation: fadeout 3s linear;
-webkit-animation-iteration-count: ;
animation-iteration-count:
} @-webkit-keyframes fadeout {
%,
% {
opacity:
}
% {
opacity:
}
} @keyframes fadeout {
%,
% {
opacity:
}
% {
opacity:
}
}
</style>
</head> <body>
<script type="text/javascript">
(function(win, doc) {
var alert = function(text, time, top) {
text = text || "确定删除?", time = time || , top = top || "10%"; //增加默认值,增强健壮性
var body = doc.getElementsByTagName("body")[]; //优化dom
//实现alert
var div = doc.createElement("div");
div.className = "toast-ui maskfadeout";
div.id = "alert";
var span = doc.createElement("span");
span.innerHTML = text;
span.className = "toast";
div.appendChild(span);
body.appendChild(div); setTimeout(function() {
div.style.display="none";
}, );
}
win.alert = alert; //导出
})(window, document);
alert("是否删除这条评论?");
</script>
</body> </html>

本文结束。