此文转载自:https://blog.csdn.net/clli_Chain/article/details/112307521#commentBox

以前没有尝试过封装组件,其实也没有严格意义的去笼统的学习过封装组件,最近使用layui满频繁的,想要封装一个dialog,尝试一下自己去动手封装一个组件,锻炼一下自己的动手能力,当然在这里也是分享给大家。

回到上方我们其实可以回想一下大体的功能,如果是一个弹窗的话,我们应该怎样去调用?应该怎么去使用呢?是使用js api来调用,还是说放置一个已经写好的html模板,让其设置display:none? js 手动将其显示?

其实上面的问题,我们可以参照一下layui和bootstrap

首先我们可以先看一下bootstrap的弹窗组件
在这里插入图片描述

在这里插入图片描述

我们其实可以明显的看出在bootstrap中其实也就是手动的将html标签语句放置在了body体内,而layui其实就是将对应的弹窗封装成了一个js文件,当调用时,去调用这个js文件的方法,然后采用插入节点的方式,将弹窗呈现。

那么我们应该去采用哪种方式来封装这个弹窗呢?在这里的话我们就将其手动的写入到js文件当中,让其使用js api的方式,让弹窗跳出,从而实现效果。

  • 该组件需要提供hook指定渲染位置,默认渲染在body下面。
  • 然后改组件可以指定外层样式,如宽度等
  • 组件外层还需要一层mask来遮住底层内容,点击mask可以执行传进来的onCancel函数关闭Dialog。
  • 另外组件是可控的,需要外层传入visible表示是否可见。
  • 然后Dialog可能需要自定义头head和底部footer,默认有头部和底部,底部有一个确认按钮和取消按钮,确认按钮会执行外部传进来的onOk事件,然后取消按钮会执行外部传进来的onCancel事件。
  • 组件高度可能大于页面高度,组件内部需要滚动条。

我略微的删减掉了几个功能,因为我们采用的是像layui 式js的跳出方式,所以我们不需要 对应的变量去控制对应的展示还是隐藏,所以我们的dialog需要实现的就是上方的几个功能。

在这里插入图片描述
我们大体需要3个文件,一个css、一个html、一个js文件

  1. /*index.css*/
  2. *{
  3. margin:0;
  4. padding:0;
  5. }
  6. /* a标签去除下划线改变颜色 */
  7. a{
  8. text-decoration: none;
  9. color: black;
  10. }
  11. /* 弹窗容器 */
  12. .keyui-dialog-box{
  13. width: 100vw;
  14. height: 100vh;
  15. position: fixed;
  16. top: 0;
  17. bottom: 0;
  18. left: 0;
  19. right: 0;
  20. z-index: 100000;
  21. }
  22. /* 遮罩层样式 */
  23. .keyui-masking-layer{
  24. width: 100%;
  25. height: 100%;
  26. background-color: rgba(0, 0, 0, .3);
  27. }
  28. /* 弹窗默认样式 */
  29. .keyui-dialog{
  30. width:50vw;
  31. height:50vh;
  32. background-color: white;
  33. position: absolute;
  34. left: 50%;
  35. top: 50%;
  36. transform: translate(-50%,-50%);
  37. }
  38. /* 头部设置固定高度 */
  39. .keyui-dialog-head{
  40. width: 100%;
  41. height: 40px;
  42. line-height: 40px;
  43. padding: 0 20px;
  44. box-sizing: border-box;
  45. background-color: #f8f8f8;
  46. border-bottom: 1px solid #eeeeee;
  47. position: relative;
  48. }
  49. /* 右上角关闭图标 */
  50. .keyui-rightUp-close{
  51. position: absolute;
  52. right: 20px;
  53. }
  54. /* 弹窗内容区域 */
  55. .keyui-dialog-content{
  56. height: calc(100% - 40px);
  57. padding: 20px;
  58. box-sizing: border-box;
  59. overflow-y: auto; /* 为什么要设置auto,因为内容区域有时会超出弹窗大小 */
  60. }
  61. /* btn按钮样式 */
  62. .keyui-btn {
  63. display: inline-block;
  64. line-height: 1;
  65. white-space: nowrap;
  66. cursor: pointer;
  67. background: #FFF;
  68. border: 1px solid #DCDFE6;
  69. color: #606266;
  70. -webkit-appearance: none;
  71. text-align: center;
  72. box-sizing: border-box;
  73. outline: 0;
  74. margin: 0;
  75. -webkit-transition: .1s;
  76. transition: .1s;
  77. font-weight: 500;
  78. padding: 12px 20px;
  79. font-size: 14px;
  80. border-radius: 4px;
  81. }
  82. /* 鼠标移入按钮效果 */
  83. .keyui-btn:hover {
  84. color: #409eff;
  85. border-color: #c6e2ff;
  86. background-color: #ecf5ff;
  87. }
  88. /* 确认按钮 */
  89. .keyui-btn-primary {
  90. color: #FFF;
  91. background-color: #409EFF;
  92. border-color: #409EFF;
  93. }
  94. /* 确认按钮鼠标移入效果 */
  95. .keyui-btn-primary:hover {
  96. background: #66b1ff;
  97. border-color: #fff;
  98. color: #fff;
  99. }
  100. /* 确认按钮mini样式 */
  101. .keyui-btn-mini {
  102. font-size: 12px;
  103. border-radius: 3px;
  104. padding: 7px 15px;
  105. }
  106. /* 确认按钮small样式 */
  107. .keyui-btn-small {
  108. padding: 9px 15px;
  109. font-size: 12px;
  110. border-radius: 3px;
  111. }
  112. /* 下框按钮区域居中,来一些边距样式 */
  113. .dialog-bottom{
  114. padding:5px;
  115. background-color: #fff;
  116. text-align: center;
  117. }

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8" />
  5. <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  6. <title>弹窗组件封装</title>
  7. <!-- 引入css样式 -->
  8. <link rel="stylesheet" href="./index.css" />
  9. </head>
  10. <body>
  11. <!-- 弹窗按钮,用于调用点击事件的弹窗 -->
  12. <button id="btn">弹窗组件</button>
  13. <!-- 指定content内容,在这里采用id,并默认将其设置为隐藏 -->
  14. <div id="content" style="display:none;">我是一个小天才</div>
  15. </body>
  16. </html>
  17. <!-- 引入jquery,因为我们js中的很多调用方法都是基于jquery的所以我们需要在index.js的上方就要引入jquery -->
  18. <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.js"></script>
  19. <!-- 引入我们的keyui组件库 -->
  20. <script src="./index.js"></script>
  21. <script>
  22. $(\'#btn\').click(function () {
  23. // 配置参数 index对应我们返还的节点
  24. var index = keyui.dialog({
  25. title:\'弹窗\',// title左上角标题
  26. content: \'#content\',// content 指定对应内容指向哪一个标签
  27. btn: [\'确认\', \'取消\'],// 下bottom按钮
  28. area:[\'200px\',\'200px\'],// 弹窗宽高大小
  29. yes: function () { //点击确认按钮事件
  30. console.log(index) //对应上方的index变量,传递给close参数,用于关闭弹窗
  31. keyui.close(index) //关闭弹窗
  32. },
  33. no:function(){ //点击取消按钮事件
  34. keyui.close(index) //关闭弹窗
  35. }
  36. })
  37. })
  38. </script>

  1. // 点击删除方法
  2. function rightclose(box) {
  3. $(\'#\'+box).remove()
  4. }
  5. // dom节点转换为字符串方法
  6. function toInnerHTML(obj){
  7. // 创建一个节点
  8. const div = document.createElement("div")
  9. // 将节点插入进去
  10. div.appendChild(obj);
  11. // 将传递进来的dom设置为显示 因为是复制的上方节点嘛
  12. obj.style.display="block"
  13. // 获取当当前的dom节点字符串
  14. var a=div.innerHTML;
  15. // return出去
  16. return a;
  17. }
  18. var yes1= function(){
  19. }
  20. var no1 = function(){
  21. }
  22. var keyui = {
  23. // 弹窗方法 外部可直接使用keyui.dialog调用
  24. dialog: function (obj) {
  25. // 设置默认值等等
  26. var {title=\'弹窗\',content=\'\',btn=[],yes,no,area=[\'50%\',\'50%\']} = obj
  27. // 创建一个时间戳当层级id
  28. var date = new Date().getTime()
  29. // 判断是不是真的传递了yes或者no 如果传递了yes或者no才会让对应的方法赋予上方的全局方法,供与回调
  30. if(typeof yes === "function"){
  31. yes1 = yes
  32. }
  33. if(typeof no === "function"){
  34. no1 = no
  35. }
  36. // 判断当前有没有btn这个数组
  37. var dialog_bottom=\'\'
  38. //有btn并且btn的长度不为0那么说明传递了按钮
  39. if(btn&&btn.length){
  40. // 拼接
  41. dialog_bottom+= `<div class="dialog-bottom">`
  42. // 循环传递进来的数组
  43. btn.forEach((element,index) => {
  44. // 我们在这里只考虑传递两个按钮第一个相当于确认,第二个相当于取消,同时挂载点击方法,也就对应了我们上方的yes1,no1
  45. dialog_bottom += `<div class="keyui-btn keyui-btn-mini ${index==0?\'keyui-btn-primary\':\'\'}" οnclick="${index==0?\'yes1()\':\'no1()\'}">${element}</div>`
  46. });
  47. dialog_bottom+= `</div>`
  48. }
  49. // 拼接一个dom节点,其实原理上我们还是使用的插入节点的方式。
  50. var box = $(`<div id="keyui-${date}" class="keyui-dialog-box">
  51. <div class="keyui-masking-layer">
  52. <div class="keyui-dialog" style="width:${area[0]};height:${area[1]}">
  53. <div class="keyui-dialog-head">
  54. <span>${title}</span>
  55. <a href="javascript:;" class="keyui-rightUp-close" οnclick="rightclose(\'keyui-${date}\')">X</a>
  56. </div>
  57. <div class="keyui-dialog-content">
  58. ${content?toInnerHTML($(content).clone(true)[0]):\'\'}
  59. </div>
  60. ${dialog_bottom}
  61. </div>
  62. </div>
  63. </div>`)
  64. // 分别说一下上方对应变量的意思
  65. /**
  66. * @param date 时间戳,主要是为了弹窗之中在弹弹窗,用于区分当前究竟是哪一个弹窗
  67. * @param area[] 0:宽度,1高度
  68. * @param title 标题
  69. * @param toInnerHTML($(content).clone(true)[0]) 完全克隆一个dom节点并作为参数传递给toInnerHTML用于拿到dom字符串
  70. * @param dialog_bottom bottom内容,如果传递的按钮是空的,那么就不会渲染,如果不是就会渲染
  71. */
  72. // 将数据插入到对应的body页面中 当然层级我们肯定要设置很高,防止被其他内容盖住
  73. $(\'body\').append(box)
  74. // 返回我们拼接的id值 用于关闭这个弹窗
  75. return $(\'#keyui-\'+date)[0]
  76. },
  77. // 关闭弹窗方法,index其实对应的是一个dom节点也就是上方弹窗返还的节点
  78. close: function (index) {
  79. // 取当前节点 直接清除
  80. index.remove();
  81. }
  82. }

在这里插入图片描述

版权声明:本文为phyger原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/phyger/p/14252049.html