dialog组件的封装

428 阅读2分钟

使用规范

正常封装一个组件要从组件的使用说起,当调用message(options)时就会在页面中显示一个

当调用dialog(options)就会在页面显示一个
也就是使用时只需调用相应的方法并传入options,在页面中就会显示相应的结构

实现步骤分析

一般都会把实现放到一个闭包内,window.xxx,把全局要用到的方法暴漏到window中,每个方法中new 一个Dialog实例并传入options,一般组件的封装就要定义一个类每一个组件都是一个实例有自己的私有属性,又有公有属性,还可以在共有方法中使用私有属性,所以最核心的就是如何书写Dialog类

代码

    let mesBut = document.querySelector(".messageBut")
    let diaBut = document.querySelector(".dialogBut");

    (function() {

        let mesBut = document.querySelector(".messageBut")
        let diaBut = document.querySelector(".dialogBut");



    (function() {

      class Dialog {
          constructor(options = {}) {
          
          //如果显示dialog,template传入的内容是字符串就要把他转成dom节点
          //方便对template的统一操作
              let tem = options.template
              if (tem && typeof tem === "string") {
                  let frag = document.createElement("div")
                  frag.innerHTML = tem
                  options.template = frag
              }
              //把options挂载在实例上
              this.options = options
              //对于全局要使用的添加到实例上
              this._myMessage = null
              this._diaBox = null
              //初始化
              this.init()
              options.oninit.call(this, this)
          }
          init() {
          //先创建相应的页面结构放入body中,之后为元素绑定事件
              let {
                  status
              } = this.options
              if (status === "message") {
                  this.create()
                  this.bindEvent()
                  this.open()
              } else {
                  this.create()
                  this.bindEvent()
                  this.open()
              }
          }
          create() {
               let {
                   status,
                   type,
                   message,
                   title,
                   click,
                   template,
               } = this.options
               if (status === "message") {
                   let fragment = document.createElement("div")
                   fragment.innerHTML = `<div class="message-box message-${type}">
                       <span>${message}</span>
                        <i>x</i>
                           </div>`
                    //存储dom到当前对象方便之后使用
                   this._myMessage = fragment
                   document.body.appendChild(fragment)
               } else {
                   let mask = document.querySelector(".mask")
                   let oldbox = document.querySelector(".dialog-box")
                   let box = oldbox
                   if (!box) {
                       box = document.createElement("div")
                       box.className = "dialog-box"
                   }
                   this._diaBox = box
                   box.innerHTML = `<div class="dialog-header">
                       <h3>${title}</h3>
                       <i>x</i></div>
                          <div class="dialog-content"></div>
              ${click&&click.length>0?`<div class="dialog-footer">
                  ${click.map(item=>{
                      return `<button text=${item.text}>${item.text}</button>`
                  }).join("")}</div>`:""}`

              if (!mask) {
                  mask = document.createElement("div")
                  mask.className = "mask"
                  document.body.appendChild(mask)
              }
              this._mask = mask
              oldbox?null:document.body.appendChild(box)
              this._diaBox.querySelector(".dialog-content").appendChild(template)
              
          }
          
      }
      bindEvent(){
          let {
                  status,
                  click
              } = this.options
              if (status === "message") {
                  let beyI=this._myMessage.querySelector("i")
                  beyI.addEventListener("click",(ev)=>{
                      this.close()
                  })
              } else {
                this._diaBox.addEventListener("click",(ev)=>{
                    //获取dialog点击的元素
                    let target=ev.target
                    //得到点击元素的标签名
                    let tagName=target.tagName
                    //如果是i直接关闭
                    if(tagName==="I"&&target.parentNode.className==="dialog-header"){
                        this.close()
                        //如果点击的是按钮,要知道是按钮的text
                    }else if(tagName==="BUTTON"&&target.parentNode.className==="dialog-footer"){
                        let text=target.getAttribute("text")
                        let now=click.find(item=>{
                            return item.text===text
                        })
                        now.func.call(this,this)
                        this.close()
                    }
                })
              }
      }
      open(){
          let {
              status,
              onopen
          } = this.options
          if (status === "message") {
              this.moveMessage()
              onopen.call(this,this)
          } else {
              this._diaBox.style.display="block"
              this._mask.style.display="block"
              this._diaBox.offsetTop
              this._diaBox.style.opacity=1
              this._mask.style.opacity=1
              onopen.call(this,this)
          }
      }
      moveMessage(){
          let messages=document.querySelectorAll(".message-box")
              messages=[].slice.call(messages)
              messages[0]&&messages[0].offsetTop
              messages.forEach((item,index)=>{
                  item.style.top=index===0?"20px":20+50*index+"px"
              })
      }
      close(){
          let {
              status,
              onclose
          } = this.options
          if (status === "message") {
              let messageBox=this._myMessage.querySelector(".message-box")
              messageBox.style.top="-200px"
              messageBox.ontransitionend=()=>{
                  messageBox.ontransitionend=null
                  document.body.removeChild(this._myMessage)
                  this.moveMessage()
                  onclose.call(this,this)
              }
          } else {
              this._diaBox.style.opacity=0
              this._mask.style.opacity=0
              this._diaBox.offsetTop
              this._diaBox.style.display="display"
              this._mask.style.display="display"
              onclose.call(this,this)
          }
          

        }
    }
        window.useMessage = function useMessage(options = {}) {
            new Dialog(options)
        }
        window.useDialog = function useDialog(options = {}) {
            new Dialog(options)

        }
    })()

    mesBut.addEventListener("click", () => useMessage({
        status: "message",
        message: "信息正确",
        type: "info",
        oninit() {},
        onopen() {},
        onclose() {},

    }))
    diaBut.addEventListener("click", () => useDialog({
        status: "dialog",
        title: "题目",
        template: "hahah",
        click: [{
            text: "确定",
            func() {}
        }, {
            text: "取消",
            func() {}
        }],
        oninit() {},
        onopen() {},
        onclose() {},

    }))