作为一名开发者,大家应该都知道在浏览器中存在一些内置的控件:Alert,Confirm等,但是这些控件通常根据浏览器产商的不同而形态各异,视觉效果往往达不到UI设计师的要求。更重要的是,这类内置控件的风格很难与形形色色的各种风格迥异的互联网产品的设计风格统一。因此,优秀的前端开发者们各自开发自己的个性化控件来替代浏览器内置的这些控件。当然,这类组件在网络上已经有不计其数相当优秀的,写这篇文章的目的不是为了说明我开发的这个组件有多优秀,也不是为了炫耀什么,只是希望通过这种方式,与更多的开发者互相交流,互相学习,共同进步。好,废话不多说,言归正传。

功能介绍

  • 取代浏览器自带的Alert、Confirm控件
  • 自定义界面样式
  • 使用方式与内置控件基本保持一致

效果预览

1、Alert控件

2、Confirm控件

3、完整代码,在线预览(见底部,提供压缩包下载)

开发过程

1. 组件结构设计

首先,我们来看下内置组件的基本使用方法:

  1. alert("内置Alert控件");
  2. if (confirm("关闭内置Confirm控件?")) {
  3. alert("True");
  4. } else {
  5. alert("False");
  6. }

为了保证我们的组件使用方式和内置控件保持一致,所以我们必须考虑覆盖内置控件。考虑到组件开发的风格统一,易用,易维护,以及面向对象等特性,我计划将自定义的alert和confirm方法作为一个类(Winpop)的实例方法,最后用实例方法去覆盖系统内置控件的方法。为了达到目的,我的基本做法如下:

  1. var obj = new Winpop(); // 创建一个Winpop的实例对象
  2. // 覆盖alert控件
  3. window.alert = function(str) {
  4. obj.alert.call(obj, str);
  5. };
  6. // 覆盖confirm控件
  7. window.confirm = function(str, cb) {
  8. obj.confirm.call(obj, str, cb);
  9. };

需要注意的是,由于浏览器内置的控件可以阻止浏览器的其他行为,而我们自定义的组件并不能具备这种能力,为了尽可能的做到统一,正如预览图上看到的,我们在弹出自定义组件的时候使用了一个全屏半透明遮罩层。也正是由于上述原因,confirm组件的使用方式也做了一些细微的调整,由内置返回布尔值的方式,改为使用回调函数的方式,以确保可以正确的添加“确定”和“取消”的逻辑。因此,自定义组件的使用方式就变成了下面这种形式:

  1. alert("自定义Alert组件");
  2. confirm("关闭自定义Confirm组件?", function(flag){
  3. if (flag) {
  4. alert("True");
  5. } else {
  6. alert("False");
  7. }
  8. });

2. 组件代码设计

在正式介绍Winpop组件的代码之前,我们先来看一下一个Javascript组件的基本结构:

  1. function(window, undefined) {
  2. function JsClassName(cfg) {
  3. var config = cfg || {};
  4. this.get = function(n) {
  5. return config[n];
  6. }
  7. this.set = function(n, v) {
  8. config[n] = v;
  9. }
  10. this.init();
  11. }
  12. JsClassName.prototype = {
  13. init: function(){},
  14. otherMethod: function(){}
  15. };
  16. window.JsClassName = window.JsClassName || JsClassName;
  17. })(window);

使用一个自执行的匿名函数将我们的组件代码包裹起来,尽可能的减少全局污染,最后再将我们的类附到全局window对象上,这是一种比较推荐的做法。

构造函数中的get、set方法不是必须的,只是笔者的个人习惯而已,觉得这样写可以将配置参数和其他组件内部全局变量缓存和读取的调用方式统一,似乎也更具有面向对象的型。欢迎读者们说说各自的想法,说说这样写到底好不好。

接下来我们一起看下Winpop组件的完整代码:

  1. (function(window, jQuery, undefined) {
  2. var HTMLS = {
  3. ovl: '<div class="J_WinpopMask winpop-mask" id="J_WinpopMask"></div>' + '<div class="J_WinpopBox winpop-box" id="J_WinpopBox">' + '<div class="J_WinpopMain winpop-main"></div>' + '<div class="J_WinpopBtns winpop-btns"></div>' + '</div>',
  4. alert: '<input type="button" class="J_AltBtn pop-btn alert-button" value="确定">',
  5. confirm: '<input type="button" class="J_CfmFalse pop-btn confirm-false" value="取消">' + '<input type="button" class="J_CfmTrue pop-btn confirm-true" value="确定">'
  6. }
  7. function Winpop() {
  8. var config = {};
  9. this.get = function(n) {
  10. return config[n];
  11. }
  12. this.set = function(n, v) {
  13. config[n] = v;
  14. }
  15. this.init();
  16. }
  17. Winpop.prototype = {
  18. init: function() {
  19. this.createDom();
  20. this.bindEvent();
  21. },
  22. createDom: function() {
  23. var body = jQuery("body"),
  24. ovl = jQuery("#J_WinpopBox");
  25. if (ovl.length === 0) {
  26. body.append(HTMLS.ovl);
  27. }
  28. this.set("ovl", jQuery("#J_WinpopBox"));
  29. this.set("mask", jQuery("#J_WinpopMask"));
  30. },
  31. bindEvent: function() {
  32. var _this = this,
  33. ovl = _this.get("ovl"),
  34. mask = _this.get("mask");
  35. ovl.on("click", ".J_AltBtn", function(e) {
  36. _this.hide();
  37. });
  38. ovl.on("click", ".J_CfmTrue", function(e) {
  39. var cb = _this.get("confirmBack");
  40. _this.hide();
  41. cb && cb(true);
  42. });
  43. ovl.on("click", ".J_CfmFalse", function(e) {
  44. var cb = _this.get("confirmBack");
  45. _this.hide();
  46. cb && cb(false);
  47. });
  48. mask.on("click", function(e) {
  49. _this.hide();
  50. });
  51. jQuery(document).on("keyup", function(e) {
  52. var kc = e.keyCode,
  53. cb = _this.get("confirmBack");;
  54. if (kc === 27) {
  55. _this.hide();
  56. } else if (kc === 13) {
  57. _this.hide();
  58. if (_this.get("type") === "confirm") {
  59. cb && cb(true);
  60. }
  61. }
  62. });
  63. },
  64. alert: function(str, btnstr) {
  65. var str = typeof str === 'string' ? str : str.toString(),
  66. ovl = this.get("ovl");
  67. this.set("type", "alert");
  68. ovl.find(".J_WinpopMain").html(str);
  69. if (typeof btnstr == "undefined") {
  70. ovl.find(".J_WinpopBtns").html(HTMLS.alert);
  71. } else {
  72. ovl.find(".J_WinpopBtns").html(btnstr);
  73. }
  74. this.show();
  75. },
  76. confirm: function(str, callback) {
  77. var str = typeof str === 'string' ? str : str.toString(),
  78. ovl = this.get("ovl");
  79. this.set("type", "confirm");
  80. ovl.find(".J_WinpopMain").html(str);
  81. ovl.find(".J_WinpopBtns").html(HTMLS.confirm);
  82. this.set("confirmBack", (callback || function() {}));
  83. this.show();
  84. },
  85. show: function() {
  86. this.get("ovl").show();
  87. this.get("mask").show();
  88. },
  89. hide: function() {
  90. var ovl = this.get("ovl");
  91. ovl.find(".J_WinpopMain").html("");
  92. ovl.find(".J_WinpopBtns").html("");
  93. ovl.hide();
  94. this.get("mask").hide();
  95. },
  96. destory: function() {
  97. this.get("ovl").remove();
  98. this.get("mask").remove();
  99. delete window.alert;
  100. delete window.confirm;
  101. }
  102. };
  103. var obj = new Winpop();
  104. window.alert = function(str) {
  105. obj.alert.call(obj, str);
  106. };
  107. window.confirm = function(str, cb) {
  108. obj.confirm.call(obj, str, cb);
  109. };
  110. })(window, jQuery);

代码略多,关键做以下几点说明:

  • 笔者偷了懒,使用了jQuery,使用之前请先保证已经引入了jQuery
  • 自定义组件结构最终是追加到body中的,所以在引入以上js之前,请先确保文档已经加载完成
  • 组件添加了按ESC、点遮罩层隐藏组件功能
  • 注意:虽然本例中未用到 destory 方法,但读者朋友可以注意一下该方法中的 delete window.alert 和 delete window.confirm ,这样写的目的是保证在自定义组件销毁后,将Alert、Confirm控件恢复到浏览器内置效果
  • 组件最后如果加上 window.Winpop = Winpop ,就可以将对象全局化供其他类调用了

最后

作为一个前端开发工程师,个人觉得Javascript组件开发是一件很有意思的事情,其中乐趣只有自己亲自动手尝试了才会体会得到。前端组件开发往往需要Javascript、CSS和html相互配合,才能事半功倍,上面提到的Winpop也不例外,这里给大家提供一个完整的demo压缩包,有兴趣的读者朋友,欢迎传播。

来源:51CTO

如何开发一个完整的JavaScript组件相关推荐

  1. 如何开发一个完整的Helm charts应用实例

    文章目录 1. 简介 2. 条件 3. 应用 4. 基础模板 5. 命名模板 6. 版本兼容 7. 持久化 8. 定制 9. 共享 Charts 1. 简介 Helm 图表是在 Kubernetes ...

  2. php做网站步骤_新手如何用PHP开发一个完整的网站?

    1.PHPer应具备的知识 (1)PHP知识: 熟练掌握基础函数,PHP语句(条件.循环),数组(排序.读取),函数(内部 构造),运算(数学 逻辑),面向对象(继承 接口 封装 多态静态属性)等. ...

  3. 【如何快速的开发一个完整的iOS直播app】(美颜篇)

    前言 在看这篇之前,如果您还不了解直播原理,请查看这篇文章如何快速的开发一个完整的iOS直播app(原理篇) 开发一款直播app,美颜功能是很重要的,如果没有美颜功能,可能分分钟钟掉粉千万,本篇主要讲 ...

  4. 【如何快速的开发一个完整的iOS直播app】(采集篇)

    前言 在看这篇之前,如果您还不了解直播原理,请查看这篇文章如何快速的开发一个完整的iOS直播app(原理篇) 开发一款直播app,首先需要采集主播的视频和音频,然后传入流媒体服务器,本篇主要讲解如何采 ...

  5. 如何快速的开发一个完整的iOS直播app(美颜篇)

    1.前言 在看这篇之前,如果您还不了解直播原理,请查看这篇文章如何快速的开发一个完整的iOS直播app(原理篇) 开发一款直播app,美颜功能是很重要的,如果没有美颜功能,可能分分钟钟掉粉千万,本篇主 ...

  6. 开发一个完整的iOS直播app必须技能

    今年,直播行业火了,当然也诞生了一大批网红,甚至明星也开始直播了,因此现在都要搞直播了!由于第一次接触,花了很多时间了解直播,目前整理了直播的原理(因为项目汇报的需要就整理了一下),现在只是展示一下从 ...

  7. (转)【如何快速的开发一个完整的iOS直播app】(原理篇)

    原文链接:https://www.jianshu.com/p/bd42bacbe4cc [如何快速的开发一个完整的iOS直播app](原理篇) [如何快速的开发一个完整的iOS直播app](原理篇) ...

  8. 如何快速的开发一个完整的iOS直播app(原理篇)

    本文转自袁峥Seemygo的博客分享.觉得很不错.特意粘来给大家分享. 1.一个完整直播app功能(来自落影loyinglin分享) 1.聊天 私聊.聊天室.点亮.推送.黑名单等; 2.礼物 普通礼物 ...

  9. 2020抖音短视频爆火!它的背后到底是什么——如何快速的开发一个完整的直播app

    前言 今年移动直播行业的兴起,诞生了一大批网红,甚至明星也开始直播了,因此不得不跟上时代的步伐,由于第一次接触的原因,因此花了很多时间了解直播,今天我来教你从零开始搭建一个完整的直播app,希望能帮助 ...

  10. 如何快速的开发一个完整的iOS直播app(播放篇)

    前言 在看这篇之前,如果您还不了解直播原理,请查看上篇文章如何快速的开发一个完整的iOS直播app(原理篇) 开发一款直播app,集成ijkplayer成功后,就算完成直播功能一半的工程了,只要有拉流 ...

最新文章

  1. D3D中简单的截图方法 (转)
  2. 51nod1565 FFT
  3. Visual Studio 2017 第三方依赖设置,附加依赖项和附加库目录
  4. golang OOP面向对象
  5. Proteus仿真单片机:PIC18单片机的仿真
  6. python数据分布_Python中的数据分布
  7. L1-047 装睡 (10 分)—团体程序设计天梯赛
  8. #Android Studio# 模拟器开发者模式
  9. css设置背景颜色的亮度
  10. 基于keras+VGG-16的小数据集多分类图像识别(附代码数据集)
  11. sdn体系的三个平面_深入SDN(三):SDN、OpenFlow和NOS是什么?
  12. php把excel导入mysql数据库中_PHP将Excel文件导入到MySQL数据库
  13. 数据挖掘课程笔记--分类(4)朴素贝叶斯
  14. day07 pyecharts制图
  15. 2021年信创产业融资分析报告
  16. 狡猾的老鼠-循环C语言,狡猾的老鼠
  17. Acrobat_8_Pro_SC 激活老是提示你输入的授权码无效
  18. ln lg,log在c语言中的表示-----转载自yam_killer的专栏
  19. JVM内存模型学习(入门)
  20. 学习笔记:人脸检测和人脸识别

热门文章

  1. ai人工智能有哪些_进入AI有多么简单
  2. 世界第一个聊天机器人源代码_这是世界上第一个“活着”的机器人
  3. 随手记---Python字典 del用法
  4. win7服务器如何还原系统教程视频,windows7系统还愿怎么操作_win7系统还原重置方法...
  5. 编写if语句时then子句为空语句_Python入门 5——循环语句及条件判断
  6. ThinkPHP5学习笔记(6)请求和响应
  7. 什么才是成熟的爱——爱的四个层次
  8. 【linux】具体芯片MACHINE_START处理
  9. Spring 测试代码的写法以及一个c3p0的错误
  10. LeetCode_125_Python_验证回文串