Fork me on GitHub

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

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>
View Code

上篇文章介绍了自定义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>
View Code

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>
View Code

本文结束。

posted @ 2018-03-25 11:04  我站在山顶上  阅读(8293)  评论(3编辑  收藏  举报