眼中杀气

文章 评论 浏览 27

眼中杀气 2022-05-04 13:54:33

实现的方法很多,都可以随意扩展,随便写写。需要注意的地方:

  1. 使用事件代理挂在document下,这样子防止拖得快的时候滑手
  2. 如果需要动画打开关闭,则不可以马上删除元素了,应该要切换样式来实现或者延迟一阵删元素。antd的modal是默认切样式,加上destroyonclose会等动画播完再删元素
  3. 使用的时候不要反复new,一个实例应该要做到无数次复用
展开查看全部代码
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>dialog</title>
    <style>
      body {
        height: 100vh;
      }
      .dlg-warpper {
        background-color: rgba(0, 0, 0, .8);
        position: fixed;
        top: 0;
        left: 0;
        right: 0;
        bottom: 0;
        z-index: 1;
      }
      .x-dialog {
        position: absolute;
        z-index: 2;
        background-color: #fff;
        left: 50%;
        top: 50%;
        width: 200px;
        text-align: center;
        border-radius: 8px;
        border: 1px solid #000;
        padding: 16px;
        user-select: none;
      }
      .x-dialog header {
        font-weight: bolder;
      }
      .x-dialog footer {
        display: flex;
        justify-content: space-around;
      }
    </style>
  </head>
  <body></body>
  <script>
    class Dialog {
      constructor(opts = {}) {
        this.onCancel = opts.onCancel || (() => {});
        this.onOk = opts.onOk || (() => {});
        this.title = opts.title || "please enter title";
        this.body = opts.body || "please enter body";
        this.footer = opts.footer || [
          {
            title: "cancel"
          },
          {
            title: "ok"
          }
        ];
        this.warpper();
        this.init();
        this.drag();
        this.warp.appendChild(this.dom)
      }

      init() {
        const dom = document.createElement("aside");
        dom.className = "x-dialog";
        dom.innerHTML = `
      <header>${this.title}</header>
      <section>${this.body}</section>
    `;
        this.dom = dom;
        Object.defineProperty(this, "_dom", {
          get() {
            return this.dom;
          },
          set(val) {
            val
              ? val.appendChild(this.warp)
              : this.warp.parentNode &&
                this.warp.parentNode.removeChild(this.warp);
          }
        });
        this.renderFooter();
      }

      open(mountNode = document.body) {
        this._dom = mountNode;
      }

      close() {
        this._dom = null;
      }

      warpper() {
        const warp = document.createElement('div');
        warp.className = 'dlg-warpper'
        this.warp = warp;
      }

      renderFooter() {
        if (this.footer) {
          const footer = document.createElement("footer");
          const btns = this.footer.map(({ title = "unknown" }, index) => {
            const btn = document.createElement("button");
            btn.dataset.midIndex = index;
            btn.innerText = title;
            footer.appendChild(btn);
            return btn;
          });
          footer.addEventListener("click", e => {
            const currentIndex = e.target.dataset.midIndex;
            (this.footer[currentIndex].cb || (() => {})).call(btns[currentIndex],e);
            this.close();
          });
          this.dom.appendChild(footer);
        }
      }

      drag() {
        let diffX = 0;
        let diffY = 0;
        const handleDrag = e => {
          const { x, y } = this.dom.getBoundingClientRect();
          this.dom.style.left = x + e.clientX - diffX + "px";
          this.dom.style.top = y + e.clientY - diffY + "px";
          diffX = e.clientX;
          diffY = e.clientY;
        };
        document.addEventListener("mousedown", e => {
          if (e.path.includes(this.dom)) {
            const { x, y } = this.dom.getBoundingClientRect();
            diffX = e.clientX;
            diffY = e.clientY;
            document.addEventListener("mousemove", handleDrag);
          } else {
            e.preventDefault();
          }
        });
        document.addEventListener("mouseup", e => {
          diffX = 0;
          diffY = 0;
          document.removeEventListener("mousemove", handleDrag);
        });
      }
    }
    const instance = new Dialog();
    instance.open();
  </script>
</html>

第 132 题:实现一个 Dialog 类,Dialog 可以创建 dialog 对话框,对话框支持可拖拽

眼中杀气 2022-05-04 11:54:52

@FrontToEnd 哈哈,谢谢提醒,补一下我的回答 怎样系统地自学前端?,其实这几个系列就是按照这样的思路去写的~

underscore 系列之链式调用

更多

推荐作者

櫻之舞

文章 0 评论 0

弥枳

文章 0 评论 0

m2429

文章 0 评论 0

野却迷人

文章 0 评论 0

我怀念的。

文章 0 评论 0

    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文