2018年6月29 最新更新
添加函数节流,解决多次点击问题,添加单例模式,提高代码性能。


1 <!DOCTYPE html>
2 <html lang="en">
3
4 <head>
5 <meta charset="UTF-8">
6 <title>自定义alert</title>
7 <style type="text/css">
8 html,
9 body {
10 padding: 0;
11 margin: 0;
12 }
13 /* //防止鼠标双击选中文字
14 */
15
16 div {
17
18 -khtml-user-select: none;
19 /*早期浏览器*/
20 user-select: none;
21 }
22 /* //来自animated.css的样式 */
23
24 .animated {
25 animation-duration: 1s;
26 animation-fill-mode: both;
27 }
28
29 @keyframes bounceInDown {
30 from,
31 60%,
32 75%,
33 90%,
34 to {
35 animation-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000);
36 }
37
38 0% {
39 opacity: 0;
40 transform: translate3d(0, -3000px, 0);
41 }
42
43 60% {
44 opacity: 1;
45 transform: translate3d(0, 25px, 0);
46 }
47
48 75% {
49 transform: translate3d(0, -10px, 0);
50 }
51
52 90% {
53 transform: translate3d(0, 5px, 0);
54 }
55
56 to {
57 transform: none;
58 display: none;
59 }
60 }
61
62 .bounceInDown {
63 animation-name: bounceInDown;
64 }
65
66 </style>
67 </head>
68
69 <body>
70 <button onclick="test" id="btn">点我测试</button>
71 <script type="text/javascript">
72 (function(win, doc) {
73 var firstTime = true,
74 startTime = 0;
75
76 function alert(txt, autoTime, top) {
77 //工具函数
78 function $(dom) {
79 return document.querySelector(dom);
80 }
81 //单利模式核心
82 var getSingle = function(fn) {
83 var result;
84 return function() {
85 return (result || (result = fn.apply(this, arguments)));
86 }
87 }
88
89 //函数节流
90 var throttle = function(fn, interval) {
91 var __self = fn; // 保存需要被延迟执行的函数引用// 是否是第一次调用
92 return function() {
93 var args = arguments,
94 __me = this;
95 if (firstTime) { // 如果是第一次调用,不需延迟执行
96 __self.apply(__me, args);
97 return firstTime = false;
98 }
99
100 var endTime = new Date() * 1; //时间大于3000秒下次执行
101 if (endTime - startTime > (autoTime || 3000)) {
102 __self.apply(__me, args);
103 }
104 };
105 };
106
107
108 //创建div代码
109 var createDiv = function() {
110
111 var div = doc.createElement("div");
112 div.style.backgroundColor = " #22b9ff";
113 div.style.color = " #fff";
114 div.style.position = " fixed";
115 div.style.zIndex = 9999999;
116 div.style.height = " 60px";
117 div.style.top = top || "10%";
118 div.style.left = "50%";
119 div.style.lineHeight = " 60px";
120 div.style.borderRadius = " 4px";
121 div.style.fontSize = " 20px";
122 div.style.textAlign = "center";
123 div.style.padding = "0 10px";
124 div.className = "animated bounceInDown";
125 div.id = "alert";
126 div.innerHTML = txt || "不能为空!";
127 return div;
128 }
129
130 var createSingleDiv = getSingle(createDiv);
131
132 return throttle(function() {
133
134 var div = createSingleDiv(); //创建div
135 startTime = new Date() * 1; //初始位置
136 $("body").appendChild(div);
137 //动态调整位置
138 var alertWidth = win.getComputedStyle($("#alert"), null).width;
139 div.style.marginLeft = -parseInt(alertWidth) / 2 + "px";
140 setTimeout(function() {
141 $("body").removeChild(div);
142 }, autoTime || 3000);
143 }).apply(this, null);
144 }
145
146 win.alert = alert; //导出
147
148 })(window, document);
149
150
151 document.getElementById('btn').onclick = function() {
152 alert("手机号不能为空!");
153 }
154
155 </script>
156 </body>
157
158 </html>
上篇文章介绍了自定义confirm的必要性,可以说alert是比confirm更为常用的浏览器自带组件了。但更因为常用,而原生组件无论是样式还是体验都不是很好,所以更加有必要自定义。
此为改造的背景。
本来第一版是自定义的第一版是没有防止提示期间,用户进行其他操作的透明层的;js代码是这样:
1 <script type="text/javascript">
2 window.alert = function(text) {
3
4 //实现alert
5 var div = document.createElement("div");
6 div.style.backgroundColor = " #22b9ff";
7 div.style.color = " #fff";
8 div.style.position = " fixed";
9 div.style.zIndex = 9999999;
10 div.style.height = " 60px";
11 div.style.top = " 10%";
12 div.style.left = "50%";
13 div.style.lineHeight = " 60px";
14 div.style.borderRadius = " 4px";
15 div.style.fontSize = " 20px";
16 div.style.textAlign = "center";
17 div.style.padding = "0 10px";
18 div.className = "animated bounceInDown";
19 div.id = "alert";
20 div.innerHTML = text;
21 document.getElementsByTagName("body")[0].appendChild(div);
22 var selfObj = document.getElementById("alert");
23 //动态调整位置
24 var alertWidth = window.getComputedStyle(selfObj, null).width;
25 div.style.marginLeft = -parseInt(alertWidth) / 2 + "px";
26 setTimeout(function() {
27 document.getElementsByTagName("body")[0].removeChild(div);
28 }, 30000);
29 }
30 alert("这是自定义的alert");
31 </script>
后来想到实际的alert效果,提示期间是无法做其它操作的,于是改造为这样
1 <script type="text/javascript">
2 window.alert = function(text) {
3 //透明遮罩层
4 var mask = document.createElement("div");
5 mask.style.position = " fixed";
6 mask.style.zIndex = 1000000;
7 mask.style.top = 0;
8 mask.style.bottom = 0;
9 mask.style.left = 0;
10 mask.style.right = 0;
11 //实现alert
12 var div = document.createElement("div");
13 div.style.backgroundColor = " #22b9ff";
14 div.style.color = " #fff";
15 div.style.position = " fixed";
16 div.style.zIndex = 9999999;
17 div.style.height = " 60px";
18 div.style.top = " 10%";
19 div.style.left = "50%";
20 div.style.lineHeight = " 60px";
21 div.style.borderRadius = " 4px";
22 div.style.fontSize = " 20px";
23 div.style.textAlign = "center";
24 div.style.padding = "0 10px";
25 div.className = "animated bounceInDown";
26 div.id = "alert";
27 div.innerHTML = text;
28 document.getElementsByTagName("body")[0].appendChild(div);
29 document.getElementsByTagName("body")[0].appendChild(mask);
30 var selfObj = document.getElementById("alert");
31 //动态调整位置
32 var alertWidth = window.getComputedStyle(selfObj, null).width;
33 div.style.marginLeft = -parseInt(alertWidth) / 2 + "px";
34 setTimeout(function() {
35 document.getElementsByTagName("body")[0].removeChild(div);
36 document.getElementsByTagName("body")[0].removeChild(mask);
37 }, 3000);
38 }
39 alert("这是自定义的alert");
40 </script>
值得一提的是动态位置的调整哪块,通过实时计算alert组件的宽度,保证组件始终处于中间位置,至于alert组件的显示时间,就自己改源代码时间吧。
整体代码如下


1 <!DOCTYPE html>
2 <html lang="en">
3
4 <head>
5 <meta charset="UTF-8">
6 <title>自定义alert</title>
7 <style type="text/css">
8 html,
9 body {
10 padding: 0;
11 margin: 0;
12 }
13 /* //防止鼠标双击选中文字
14 */
15
16 div {
17
18 -khtml-user-select: none;
19 /*早期浏览器*/
20 user-select: none;
21 }
22 /* //来自animated.css的样式 */
23
24 .animated {
25 animation-duration: 1s;
26 animation-fill-mode: both;
27 }
28
29 @keyframes bounceInDown {
30 from,
31 60%,
32 75%,
33 90%,
34 to {
35 animation-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000);
36 }
37
38 0% {
39 opacity: 0;
40 transform: translate3d(0, -3000px, 0);
41 }
42
43 60% {
44 opacity: 1;
45 transform: translate3d(0, 25px, 0);
46 }
47
48 75% {
49 transform: translate3d(0, -10px, 0);
50 }
51
52 90% {
53 transform: translate3d(0, 5px, 0);
54 }
55
56 to {
57 transform: none;
58 }
59 }
60
61 .bounceInDown {
62 animation-name: bounceInDown;
63 }
64
65 </style>
66 </head>
67
68 <body>
69 <script type="text/javascript">
70 (function(win,doc) {
71 var alert = function(text, time, top) {
72 text = text || "确定删除?",time = time || 3000,top = top || "10%";//增加默认值,增强健壮性
73 var body=doc.getElementsByTagName("body")[0];//优化dom
74 //实现alert
75 var div = doc.createElement("div");
76 div.style.backgroundColor = " #22b9ff";
77 div.style.color = " #fff";
78 div.style.position = " fixed";
79 div.style.zIndex = 9999999;
80 div.style.height = " 60px";
81 div.style.top = top;
82 div.style.left = "50%";
83 div.style.lineHeight = " 60px";
84 div.style.borderRadius = " 4px";
85 div.style.fontSize = " 20px";
86 div.style.textAlign = "center";
87 div.style.padding = "0 10px";
88 div.className = "animated bounceInDown";
89 div.id = "alert";
90 div.innerHTML = text;
91 body.appendChild(div);
92 var selfObj = doc.getElementById("alert");
93 //动态调整位置
94 var alertWidth = win.getComputedStyle(selfObj, null).width;
95 div.style.marginLeft = -parseInt(alertWidth) / 2 + "px";
96 setTimeout(function() {
97 body.removeChild(div);
98 }, time);
99 }
100 win.alert=alert;//导出
101 })(window,document);
102 alert();
103 </script>
104 </body>
105
106 </html>
2018年6月24日更新 增加参数的默认值,该少dom访问慢的问题,使用闭包包裹,alert导出覆盖window
在整体代码中,有一个用来防止双击选中文字的css样式,值得关注一下。
样式中的css动画来自知名的动画库animation.css。因此,可以根据实际业务需要更换动画类。基本就是这样。
仿京东注册web移动端提示。


1 <!DOCTYPE html>
2 <html lang="en">
3
4 <head>
5 <meta charset="UTF-8">
6 <title>自定义alert</title>
7 <meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0,user-scalable=no" name="viewport" />
8 <style type="text/css">
9 html,
10 body {
11 padding: 0;
12 margin: 0;
13 }
14 /* //防止鼠标双击选中文字
15 */
16
17 div {
18
19 -khtml-user-select: none;
20 /*早期浏览器*/
21 user-select: none;
22 }
23 /* //来自animated.css的样式 */
24
25 @-webkit-keyframes fadeIn {
26 0% {
27 opacity: .7
28 }
29 50% {
30 opacity: 1
31 }
32 100% {
33 opacity: .7
34 }
35 }
36
37 .toast {
38 -webkit-animation-name: fadeIn;
39 -webkit-animation-duration: 3s;
40 -webkit-animation-iteration-count: 1;
41 -webkit-animation-delay: 0s;
42 -webkit-transition: all .3s ease;
43 -moz-transition: all .3s ease;
44 transition: all .3s ease;
45 max-width: 80%;
46 color:#fff;
47 background: #2B2B2B;
48 padding: 8px 15px;
49 display: inline-table;
50 border-radius: 3px;
51 }
52
53 .toast-ui {
54 position: fixed;
55 top:20%;
56 color:#fff;
57 width: 100%;
58 text-align: center;
59 }
60
61 .maskfadeout {
62 display: block;
63 -webkit-animation: fadeout 3s linear;
64 animation: fadeout 3s linear;
65 -webkit-animation-iteration-count: 1;
66 animation-iteration-count: 1
67 }
68
69 @-webkit-keyframes fadeout {
70 0%,
71 80% {
72 opacity: 1
73 }
74 100% {
75 opacity: 0
76 }
77 }
78
79 @keyframes fadeout {
80 0%,
81 80% {
82 opacity: 1
83 }
84 100% {
85 opacity: 0
86 }
87 }
88 </style>
89 </head>
90
91 <body>
92 <script type="text/javascript">
93 (function(win, doc) {
94 var alert = function(text, time, top) {
95 text = text || "确定删除?", time = time || 3000, top = top || "10%"; //增加默认值,增强健壮性
96 var body = doc.getElementsByTagName("body")[0]; //优化dom
97 //实现alert
98 var div = doc.createElement("div");
99 div.className = "toast-ui maskfadeout";
100 div.id = "alert";
101 var span = doc.createElement("span");
102 span.innerHTML = text;
103 span.className = "toast";
104 div.appendChild(span);
105 body.appendChild(div);
106
107 setTimeout(function() {
108 div.style.display="none";
109 }, 3000);
110 }
111 win.alert = alert; //导出
112 })(window, document);
113 alert("是否删除这条评论?");
114 </script>
115 </body>
116
117 </html>
本文结束。
来源:oschina
链接:https://my.oschina.net/u/4385489/blog/4034303