前端如何封裝一個組件?怎麼造輪子?手寫js封裝一個dialog彈窗組件。

一、現在要你完成一個Dialog組件,說說你設計的思路?它應該有什麼功能?

以前沒有嘗試過封裝組件,其實也沒有嚴格意義的去籠統的學習過封裝組件,最近使用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文件

三、樣式Css文件

/*index.css*/
*{
   
   
  margin:0;
  padding:0;
}
/* a標籤去除下劃線改變顏色 */
a{
   
   
  text-decoration: none;
  color: black;
}
/* 彈窗容器 */
.keyui-dialog-box{
   
   
  width: 100vw;
  height: 100vh;
  position: fixed;
  top: 0;
  bottom: 0;
  left: 0;
  right: 0;
  z-index: 100000;
}
/* 遮罩層樣式 */
.keyui-masking-layer{
   
   
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, .3);
}
/* 彈窗默認樣式 */
.keyui-dialog{
   
   
  width:50vw;
  height:50vh;
  background-color: white;
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%,-50%);
}
/* 頭部設置固定高度 */
.keyui-dialog-head{
   
   
  width: 100%;
  height: 40px;
  line-height: 40px;
  padding: 0 20px;
  box-sizing: border-box;
  background-color: #f8f8f8;
  border-bottom: 1px solid #eeeeee;
  position: relative;
}
/* 右上角關閉圖標 */
.keyui-rightUp-close{
   
   
  position: absolute;
  right: 20px;
}
/* 彈窗內容區域 */
.keyui-dialog-content{
   
   
  height: calc(100% - 40px);
  padding: 20px;
  box-sizing: border-box;
  overflow-y: auto;  /* 爲什麼要設置auto,因爲內容區域有時會超出彈窗大小 */
}
/* btn按鈕樣式 */
.keyui-btn {
   
   
  display: inline-block;
  line-height: 1;
  white-space: nowrap;
  cursor: pointer;
  background: #FFF;
  border: 1px solid #DCDFE6;
  color: #606266;
  -webkit-appearance: none;
  text-align: center;
  box-sizing: border-box;
  outline: 0;
  margin: 0;
  -webkit-transition: .1s;
  transition: .1s;
  font-weight: 500;
  padding: 12px 20px;
  font-size: 14px;
  border-radius: 4px; 
}
/* 鼠標移入按鈕效果 */
.keyui-btn:hover {
   
   
  color: #409eff;
  border-color: #c6e2ff;
  background-color: #ecf5ff;
}
/* 確認按鈕 */
.keyui-btn-primary {
   
   
  color: #FFF;
  background-color: #409EFF;
  border-color: #409EFF;
}
/* 確認按鈕鼠標移入效果 */
.keyui-btn-primary:hover {
   
   
  background: #66b1ff;
  border-color: #fff;
  color: #fff;
}
/* 確認按鈕mini樣式 */
.keyui-btn-mini {
   
   
  font-size: 12px;
  border-radius: 3px;
  padding: 7px 15px;
}
/* 確認按鈕small樣式 */
.keyui-btn-small {
   
   
  padding: 9px 15px;
  font-size: 12px;
  border-radius: 3px;
}
/* 下框按鈕區域居中,來一些邊距樣式 */
.dialog-bottom{
   
   
  padding:5px;
  background-color: #fff;
  text-align: center;
}

四、模擬調用場景index.html文件

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>彈窗組件封裝</title>
    <!-- 引入css樣式 -->
    <link rel="stylesheet" href="./index.css" />
  </head>
  <body>
    <!-- 彈窗按鈕,用於調用點擊事件的彈窗 -->
    <button id="btn">彈窗組件</button>

    <!-- 指定content內容,在這裏採用id,並默認將其設置爲隱藏 -->
    <div id="content" style="display:none;">我是一個小天才</div>
  </body>
</html>
<!-- 引入jquery,因爲我們js中的很多調用方法都是基於jquery的所以我們需要在index.js的上方就要引入jquery -->
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.js"></script>
<!-- 引入我們的keyui組件庫 -->
<script src="./index.js"></script>

<script>
  $('#btn').click(function () {
    
    
    // 配置參數  index對應我們返還的節點
    var index = keyui.dialog({
    
    
      title:'彈窗',// title左上角標題
      content: '#content',// content 指定對應內容指向哪一個標籤
      btn: ['確認', '取消'],// 下bottom按鈕
      area:['200px','200px'],// 彈窗寬高大小
      yes: function () {
    
     //點擊確認按鈕事件
        console.log(index) //對應上方的index變量,傳遞給close參數,用於關閉彈窗
        keyui.close(index) //關閉彈窗
      },
      no:function(){
    
     //點擊取消按鈕事件
        keyui.close(index) //關閉彈窗
      }
    })
  })
</script>

五、dialog彈窗js組件


// 點擊刪除方法
function rightclose(box) {
   
   
  $('#'+box).remove()
}
// dom節點轉換爲字符串方法
function toInnerHTML(obj){
   
   
  // 創建一個節點
  const div = document.createElement("div")
  // 將節點插入進去
  div.appendChild(obj);
  // 將傳遞進來的dom設置爲顯示  因爲是複製的上方節點嘛
  obj.style.display="block"
  // 獲取噹噹前的dom節點字符串
  var a=div.innerHTML;
  // return出去
  return a;
}
var yes1= function(){
   
   
}
var no1 = function(){
   
   
}
var keyui = {
   
   
  // 彈窗方法  外部可直接使用keyui.dialog調用
  dialog: function (obj) {
   
   
    // 設置默認值等等
    var {
   
   title='彈窗',content='',btn=[],yes,no,area=['50%','50%']} = obj
    // 創建一個時間戳當層級id
    var date = new Date().getTime()
    // 判斷是不是真的傳遞了yes或者no 如果傳遞了yes或者no纔會讓對應的方法賦予上方的全局方法,供與回調
    if(typeof yes === "function"){
   
   
      yes1 = yes
    }
    if(typeof no === "function"){
   
   
      no1 = no
    }
    // 判斷當前有沒有btn這個數組
    var dialog_bottom=''
    //有btn並且btn的長度不爲0那麼說明傳遞了按鈕
    if(btn&&btn.length){
   
   
      // 拼接
      dialog_bottom+= `<div class="dialog-bottom">`
      // 循環傳遞進來的數組
    btn.forEach((element,index) => {
   
   
      // 我們在這裏只考慮傳遞兩個按鈕第一個相當於確認,第二個相當於取消,同時掛載點擊方法,也就對應了我們上方的yes1,no1
      dialog_bottom +=  `<div class="keyui-btn keyui-btn-mini ${
     
     index==0?'keyui-btn-primary':''}" οnclick="${
     
     index==0?'yes1()':'no1()'}">${
     
     element}</div>`
     });
     dialog_bottom+= `</div>`
    }
    // 拼接一個dom節點,其實原理上我們還是使用的插入節點的方式。
    var box = $(`<div id="keyui-${
     
     date}" class="keyui-dialog-box">
                <div class="keyui-masking-layer">
                  <div class="keyui-dialog" style="width:${
     
     area[0]};height:${
     
     area[1]}">
                    <div class="keyui-dialog-head">
                    <span>${
     
     title}</span>
                      <a href="javascript:;" class="keyui-rightUp-close" οnclick="rightclose('keyui-${
     
     date}')">X</a>
                    </div>
                    <div class="keyui-dialog-content">
                      ${
     
     content?toInnerHTML($(content).clone(true)[0]):''}
                    </div>
                      ${
     
     dialog_bottom}
                  </div>
                </div>
              </div>`)
    // 分別說一下上方對應變量的意思
    /**
     * @param date 時間戳,主要是爲了彈窗之中在彈彈窗,用於區分當前究竟是哪一個彈窗
     * @param area[] 0:寬度,1高度
     * @param title 標題
     * @param toInnerHTML($(content).clone(true)[0]) 完全克隆一個dom節點並作爲參數傳遞給toInnerHTML用於拿到dom字符串
     * @param dialog_bottom bottom內容,如果傳遞的按鈕是空的,那麼就不會渲染,如果不是就會渲染
     */

    //  將數據插入到對應的body頁面中  當然層級我們肯定要設置很高,防止被其他內容蓋住
    $('body').append(box)

    // 返回我們拼接的id值  用於關閉這個彈窗
    return $('#keyui-'+date)[0]
  },
  // 關閉彈窗方法,index其實對應的是一個dom節點也就是上方彈窗返還的節點
  close: function (index) {
   
   
    //  取當前節點  直接清除
    index.remove();
  }
}

最終效果

在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章