手把手教你用原生Javascript封裝一個(gè)Dialog組件

下來(lái)玩玩

Dialog component by native javascript

分析

對(duì)外暴露的方法

  • show(options) 顯示dialog
    • options 參數(shù)
      • title 標(biāo)題,默認(rèn)為“”,不顯示標(biāo)題
      • content 主內(nèi)容,默認(rèn)為"兄弟,你好像忘記傳content的值了"
      • skin 皮膚,默認(rèn)為"",其實(shí)就是給dialog添加一個(gè)你的類(lèi)名,方便重置樣式
      • btns 按鈕組,默認(rèn)為['確認(rèn)'],可選['xx',‘xx’],只取前兩個(gè)作為有效值,第一個(gè)為confirm,第二個(gè)為cancel
      • confirm 點(diǎn)擊confirm按鈕的回調(diào),如確認(rèn)
      • cancel 點(diǎn)擊cancel按鈕的回調(diào),如取消
      • shadeClose 是否開(kāi)啟點(diǎn)擊遮罩關(guān)閉,默認(rèn)true
      • animation 過(guò)渡動(dòng)畫(huà),默認(rèn)為1,可選0和2,注意這里的動(dòng)畫(huà)是指內(nèi)容區(qū)的動(dòng)畫(huà),最外層是固定為0
  • hide() 關(guān)閉dialog

過(guò)渡動(dòng)畫(huà)
用css3的animation,具體看下面的css

先寫(xiě)好布局、樣式(后面會(huì)移植到Javascript生成DOM)

html

<!-- 最外層 -->
<div class="dialog-wrapper">
  <!-- 居中主要層 -->
  <div class="dialog">
    <!-- 標(biāo)題 -->
    <div class="title">消息提示</div>
    <!-- 主要內(nèi)容 -->
    <div class="content">兄弟,你好像忘記傳content的值了</div>
    <!-- 按鈕組 -->
    <div class="buttons">
      <div class="btn cancel-btn">取消</div>
      <div class="btn confirm-btn">確認(rèn)</div>
    </div>
  </div>
</div>

css

body,
html {
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
}

.dialog-wrapper {
  position: fixed;
  display: flex;
  justify-content: center;
  align-items: center;
  top: 0;
  left: 0;
  width: 100vw;
  height: 100vh;
  background-color: rgba(49, 49, 49, 0.5);
  color: #313131;
  font-size: 10px;
  -webkit-tap-highlight-color: transparent;
}

.dialog-wrapper.fadeIn {
  animation: fadeIn .2s ease;
}

.dialog-wrapper.fadeOut {
  animation: fadeOut .2s ease forwards;
}

.dialog-wrapper .dialog {
  position: relative;
  width: 85vw;
  max-width: 30em;
  border-radius: .4em;
  background-color: #fff;
  box-sizing: border-box;
  overflow: hidden;
  box-shadow: 0 0 10px 1px rgba(0, 0, 0, 0.1);
}

.dialog-wrapper .dialog.slideDown {
  animation: slideDown .2s ease;
}

.dialog-wrapper .dialog.slideUp {
  animation: slideUp .2s ease forwards;
}

.dialog-wrapper .dialog.scaleIn {
  animation: scaleIn 0.2s cubic-bezier(0.07, 0.89, 0.95, 1.4);
}

.dialog-wrapper .dialog.scaleOut {
  animation: scaleOut 0.2s cubic-bezier(0.07, 0.89, 0.95, 1.4) forwards;
}

.dialog-wrapper .dialog .btn {
  cursor: pointer;
}

.dialog-wrapper .dialog .btn:active {
  background-color: #f4f4f4;
}

.dialog-wrapper .dialog .close-btn {
  position: absolute;
  top: 0;
  right: 0;
  padding: 10px;
  font-size: 1.8em;
}

.dialog-wrapper .dialog .title {
  font-size: 1.8em;
  padding: 15px;
  text-align: center;
  background-color: #f4f4f4;
}

.dialog-wrapper .dialog .title:empty {
  display: none;
}

.dialog-wrapper .dialog .content {
  padding: 40px 20px;
  font-size: 1.6em;
  text-align: center;
}

.dialog-wrapper .dialog .buttons {
  font-size: 1.6em;
  display: flex;
  flex-flow: row-reverse;
}

.dialog-wrapper .dialog .buttons .btn {
  flex: 1;
  padding: 15px;
  text-align: center;
  border-top: 1px solid #ebebeb;
}

.dialog-wrapper .dialog .buttons .btn.confirm-btn {
  color: #f2d985;
}

.dialog-wrapper .dialog .buttons .btn.cancel-btn {
  color: #313131;
  border-right: 1px solid #ebebeb;
}

@keyframes slideDown {
  from {
    transform: translateY(-3em);
  }
  to {
    transform: translateY(0);
  }
}

@keyframes slideUp {
  from {
    transform: translateY(0);
  }
  to {
    transform: translateY(-3em);
  }
}

@keyframes fadeIn {
  from {
    opacity: .5;
  }
  to {
    opacity: 1;
  }
}

@keyframes fadeOut {
  from {
    opacity: 1;
  }
  to {
    opacity: 0;
  }
}

@keyframes scaleIn {
  from {
    transform: scale(0.8);
  }
  to {
    transform: scale(1);
  }
}

@keyframes scaleOut {
  from {
    transform: scale(1);
  }
  to {
    transform: scale(0.8);
  }
}

Javascript封裝

第一步,基本搭建
使用立即執(zhí)行函數(shù),只對(duì)外暴露兩個(gè)方法,show和hide

let dialog = (function () {

  // 節(jié)點(diǎn)類(lèi)型
  let elem, dialog, cancelBtn, confirmBtn;

  // 動(dòng)畫(huà)函數(shù)數(shù)組
  let animaArr = new Array(['fadeIn', 'fadeOut'], ['slideDown', 'slideUp'], ['scaleIn', 'scaleOut']);

  // 當(dāng)前動(dòng)畫(huà)類(lèi)型
  let currAnimation = '';

  /**
   * @method getNeedElement 獲取所需要的節(jié)點(diǎn)
   */
  let getNeedElement = function () {

  }

  /**
   * @method show 顯示dialog組件
   * @param {Object} options 一系列參數(shù)
   * @returns {Object} 當(dāng)前dialog節(jié)點(diǎn)
   */
  let show = function (options) {

  }

  /**
   * @method hide 關(guān)閉dialog組件
   */
  let hide = function (index) {

  }

  /**
   * @method bindEvent 給dialog綁定事件
   * @param {Object} confirm 確認(rèn)回調(diào)
   * @param {Object} cancel 取消回調(diào)
   */
  let bindEvent = function (confirm, cancel, shadeClose) {

  }

  return {
    show,
    hide
  }

})();

第二步,編寫(xiě)show方法

let show = function (options = {}) {

  // 默認(rèn)參數(shù)
  let {
    title = '', content = '兄弟,你好像忘記傳content值了',
      skin = '', btns = ['確定'],
      confirm = null,
      cancel = null,
      shadeClose = true,
      animation = 1
  } = options;

  // 皮膚類(lèi)名
  let skinClass = skin ? ` ${skin}` : '';

  // 給當(dāng)前動(dòng)畫(huà)類(lèi)型賦值
  currAnimation = animation;

  // 生成按鈕
  let btnTemp = '';
  btns.forEach((item, index) => {
    if (index == 2) return;
    let btnClass = index == 0 ? 'confirm-btn' : 'cancel-btn';
    let temp = `<div class="btn ${btnClass}">${item}</div>`
    btnTemp += temp
  })

  // 最終生成的HTML
  let html = `
    <div class="dialog-wrapper fadeIn">
      <div class="dialog${skinClass} ${animaArr[currAnimation][0]}">
        <div class="title">${title}</div>
        <div class="content">${content}</div>
        <div class="buttons">${btnTemp}</div>
      </div>
    </div>
  `;

  // 添加到Body
  document.body.innerHTML += html;
  // 獲取所需要的節(jié)點(diǎn)
  getNeedElement();
  // 綁定事件
  bindEvent(confirm, cancel, shadeClose);
  return elem;

}

第三步,編寫(xiě)hide方法

// 最外層加類(lèi)名hide
let hide = function () {

  // 最外層執(zhí)行顯示動(dòng)畫(huà)(固定)
  elem.classList.add('fadeOut');
  // 內(nèi)容層執(zhí)行關(guān)閉動(dòng)畫(huà)
  dialog.classList.add(`${animaArr[currAnimation][1]}`);
  // 最終移除
  setTimeout(() => {
    elem.remove();
  }, 200);

}

第四步,編寫(xiě)bindEvent方法

let bindEvent = function (confirm, cancel) {

 // confirm按鈕的回調(diào)
  confirmBtn && confirmBtn.addEventListener('click', e => {
    hide();
    confirm && confirm();
  })

  // cancel按鈕的回調(diào)
  cancelBtn && cancelBtn.addEventListener('click', e => {
    hide();
    cancel && cancel();
  })

  // 是否開(kāi)啟點(diǎn)擊遮罩關(guān)閉
  if (shadeClose) {
    elem.addEventListener('click', e => {
      let target = e.target || e.srcElement;
      if (/dialog-wrapper/.test(target.className)) {
        hide();
      }
    })
  }

}

第五步,編寫(xiě)getNeedElement方法

let getNeedElement = function () {
  
  // 一家人最重要是整整齊齊
  elem = document.querySelector('.dialog-wrapper');
  dialog = elem.querySelector('.dialog');
  cancelBtn = elem.querySelector('.cancel-btn');
  confirmBtn = elem.querySelector('.confirm-btn');

}

調(diào)用以及效果圖

  1. 無(wú)標(biāo)題


dialog.show({
  content: '抱歉,該游戲暫無(wú)Android版本'
})
  1. 自定義標(biāo)題和按鈕


dialog.show({
  title: '版本更新',
  content: '檢測(cè)到最新版本為V1.0.2,是否更新',
  btns: ['立即更新', '暫不更新']
})
  1. 動(dòng)畫(huà)效果為2時(shí)(彈性放大)


 dialog.show({
  title: '消息提示',
  content: '此操作將不可逆轉(zhuǎn),確定刪除此項(xiàng)?',
  btns: ['確定', '怕了'],
  animation: 2
})

說(shuō)明

自己可以擴(kuò)展更多自定義參數(shù),動(dòng)畫(huà)需配合css3的animation

最后

本文到此結(jié)束,希望以上內(nèi)容對(duì)你有些許幫助,如若喜歡請(qǐng)記得點(diǎn)個(gè)關(guān)注哦 ??

image

微信公眾號(hào)「前端宇宙情報(bào)局」,將不定時(shí)更新最新、實(shí)用的前端技巧/技術(shù)性文章,歡迎關(guān)注,一起學(xué)習(xí) ??

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 用到的組件 1、通過(guò)CocoaPods安裝 2、第三方類(lèi)庫(kù)安裝 3、第三方服務(wù) 友盟社會(huì)化分享組件 友盟用戶反饋 ...
    SunnyLeong閱讀 15,206評(píng)論 1 180
  • ¥開(kāi)啟¥ 【iAPP實(shí)現(xiàn)進(jìn)入界面執(zhí)行逐一顯】 〖2017-08-25 15:22:14〗 《//首先開(kāi)一個(gè)線程,因...
    小菜c閱讀 7,388評(píng)論 0 17
  • 星期天的中午一時(shí),我和媽媽在鹽湖區(qū)解放路立交橋的橋墩旁的墻上,發(fā)現(xiàn)了一排爬山虎。爬山虎是一種植物,它的生存條件是:...
    孟浩東閱讀 1,487評(píng)論 1 2
  • 簡(jiǎn)介:安福瀘水河省級(jí)濕地公園位于橫龍鎮(zhèn)石溪村何家至平都鎮(zhèn)瀘水河鐵路橋的約10公里水域及其周邊草本沼澤濕地和部分林地...
    江西安福伊伊秋水閱讀 1,382評(píng)論 0 1
  • 很多男人都有獵奇心理,美女總是耀眼的。 人都喜歡美好得事物,這沒(méi)錯(cuò),對(duì)于美女持欣賞態(tài)度,我是認(rèn)可的。畢...
    初秋淡夏閱讀 1,098評(píng)論 3 2

友情鏈接更多精彩內(nèi)容