04-组件样式模板——以弹窗为例

1. 组件编写原则

  • 对内:封闭
  • 对外:开放(API、配置 )

2. 封装JS

class Dialog {
    constructor(options) {
        this.opts = {
            width: "30%",
            height: "200px",
            title: "测试标题",
            content: "测试内容",
            dragable: true, //是否可拖拽
            maskable: true, //是否有遮罩
            isCancel: false, //是否有取消
        }
    }
}

3. 合并配置Object.assign(a,b)

class Dialog {
    constructor(options) {
        // 合并配置
        this.opts = Object.assign({
            width: "30%",
            height: "200px",
            title: "默认标题",
            content: "默认内容",
            dragable: true, //是否可拖拽
            maskable: true, //是否有遮罩
            isCancel: false, //是否有取消
        }, options);
        console.log(this.opts);
    }
}

let dialog1 = new Dialog({
    width: "40%",
    title: "dialog1测试标题",
    content: "dialog2测试内容",
});

>{width: "40%", height: "200px", title: "dialog1测试标题", content: "dialog2测试内容", dragable: true,}

4. 页面渲染

renderView() {
    this.dialogHTML = document.createElement("div");
    this.dialogHTML.innerHTML =
        `
        <div class="k-wrapper"></div>
        <div class="k-dialog" style="width:${this.opts.width};height:${this.opts.height}">
            <div class="k-header">
                <span class="k-title">${this.opts.title}</span><span class="k-close">X</span>
            </div>
            <div class="k-body">
                <span>${this.opts.content}</span>
            </div>
            <div class="k-footer">
                ${this.opts.isCancel?'<span class="k-cancel">取消</span>':''}
                <span class="k-primary">确定</span>
            </div>
        </div>
    `
    document.querySelector("body").appendChild(this.dialogHTML);
}

5. 功能实现-显示弹窗

open(){
    if(this.opts.maskable){
        this.dialogHTML.querySelector(".k-wrapper").style.display = "block";
    }
    this.dialogHTML.querySelector(".k-dialog").style.display = "block";
}

6. 功能实现-关闭弹窗extends EventTarget类

  • 关闭弹窗的实现语句
close() {
    if (this.opts.maskable) {
        this.dialogHTML.querySelector(".k-wrapper").style.display = "none";
    }
    this.dialogHTML.querySelector(".k-dialog").style.display = "none";
}
  • 添加事件——sucess()、cancel()
class Dialog extends EventTarget {
	constructor(options) {
	    super();
	    // 合并配置
	    this.opts = Object.assign({
	        width: "30%",
	        height: "200px",
	        title: "默认标题",
	        content: "默认内容",
	        dragable: true, //是否可拖拽
	        maskable: true, //是否有遮罩
	        isCancel: false, //是否有取消
	        success() {
	            console.log("默认点击确定了!");
	        },
	        cancel() {
	            console.log("默认点击取消了");
	        },
	    }, options);
	}
}
  • 事件绑定
let cancel = new Event("cancel");
this.addEventListener("cancel", this.opts.cancel);
let success = new Event("success");
this.addEventListener("success", this.opts.success);
  • 事件触发
// 此处必须使用箭头函数,否则this指向会不正确
this.dialogHTML.onclick = e => {
    switch (e.target.className) {
        case 'k-close':
            this.close();
            this.dispatchEvent(cancel);
            break;
        case 'k-cancel':
            this.close();
            this.dispatchEvent(cancel);
            break;
        case 'k-primary':
            this.close();
            this.dispatchEvent(success);
    }
}

7. 继承—弹窗增加对话框功能

class ExtendsDialog extends Dialog {
    constructor(options) {
        super(options);
        this.renderInput();
    }
    renderInput() {
        let myInput = document.createElement("input");
        myInput.type = "text";
        myInput.classList.add("input-inner");
        this.dialogHTML.querySelector(".k-body").appendChild(myInput);
    }
}

8. 子类将值传给父类—传递对话框中的内容confirm()

  • 子类
class ExtendsDialog extends Dialog {
    constructor(options) {
        super(options);
        this.renderInput();
    }
    renderInput() {
        let myInput = document.createElement("input");
        myInput.type = "text";
        myInput.classList.add("input-inner");
        this.dialogHTML.querySelector(".k-body").appendChild(myInput);
    }
    confirm(){
        let value = this.dialogHTML.querySelector(".input-inner").value;
        super.confirm(value);
    }
}
  • 父类
class Dialog extends EventTarget {
    constructor(options) {
        super();
        // 合并配置
        this.opts = Object.assign({
            ...
            success() {
                console.log("默认点击确定了!");
            },
            cancel() {
                console.log("默认点击取消了");
            },
        }, options);

        this.init();
    }
    init() {

        this.renderView();

        let cancel = new Event("cancel");
        this.addEventListener("cancel", this.opts.cancel);
        // let success = new Event("success");
        this.addEventListener("success", this.opts.success);

        this.dialogHTML.onclick = e => {
            switch (e.target.className) {
                case 'k-close':
                    this.close();
                    this.dispatchEvent(cancel);
                    break;
                case 'k-cancel':
                    this.close();
                    this.dispatchEvent(cancel);
                    break;
                case 'k-primary':
                    this.close();
                    this.confirm();
                    break;
            }
        }
    }
    ...
    // 获取对话框的值
    confirm(value){
        let success = new CustomEvent("success",{
            detail:value
        });
        this.dispatchEvent(success);
    }
}

9. 完整代码

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <style>
        .k-dialog {
            width: 30%;
            z-index: 2001;
            display: block;
            position: absolute;
            background: #fff;
            border-radius: 2px;
            box-shadow: 0 1px 3px rgba(0, 0, 0, .3);
            margin: 0 auto;
            top: 15vh;
            left: 30%;
            display: none;
        }

        .k-wrapper {
            position: fixed;
            left: 0px;
            top: 0px;
            bottom: 0px;
            right: 0px;
            background: black;
            opacity: 0.4;
            z-index: 2000;
            display: none;
        }

        .k-header {
            padding: 20px 20px 10px;
        }

        .k-header .k-title {
            line-height: 24px;
            font-size: 18px;
            color: #303133;
            float: left;
        }

        .k-body {
            padding: 30px 20px;
            color: #606266;
            font-size: 14px;
        }

        .k-footer {
            padding: 10px 20px 30px;
            text-align: right;
        }

        .k-close {
            color: #909399;
            font-weight: 400;
            float: right;
            cursor: pointer;
        }

        .k-cancel {
            color: #606266;
            border: 1px solid #dcdfe6;
            text-align: center;
            cursor: pointer;
            padding: 12px 20px;
            font-size: 14px;
            border-radius: 4px;
            font-weight: 500;
            margin-right: 10px;
        }

        .k-cancel:hover {
            color: #409eff;
            background: #ecf5ff;
            border-color: #c6e2ff;
        }

        .k-primary {
            border: 1px solid #dcdfe6;
            text-align: center;
            cursor: pointer;
            padding: 12px 20px;
            font-size: 14px;
            border-radius: 4px;
            font-weight: 500;
            background: #409eff;
            color: #fff;
            margin-left: 10px;
        }

        .k-primary:hover {
            background: #66b1ff;
        }

        .k-input {
            width: 100%;
            margin-left: 20px;
            margin-bottom: 20px;
        }

        .input-inner {
            -webkit-appearance: none;
            background-color: #fff;
            background-image: none;
            border-radius: 4px;
            border: 1px solid #dcdfe6;
            box-sizing: border-box;
            color: #606266;
            display: inline-block;
            font-size: inherit;
            height: 40px;
            line-height: 40px;
            outline: none;
            padding: 0 15px;
            transition: border-color .2s cubic-bezier(.645, .045, .355, 1);
            width: 100%;
            margin-top: 20px;
        }
    </style>
</head>

<body>
    <!-- <div class="k-wrapper"></div>
    <div class="k-dialog">
        <div class="k-header">
            <span class="k-title">提示</span><span class="k-close">X</span>
        </div>
        <div class="k-body">
            <span>这是一段文本</span>
            <input class="input-inner" type="text" />
        </div>
        <div class="k-footer">
            <span class="k-cancel">取消</span>
            <span class="k-primary">确定</span>
        </div>
    </div>  -->

    <button class="dialog1">点击</button>
    <button class="dialog2">点击2</button>
</body>
<script>
    // 封装JS
    class Dialog extends EventTarget {
        constructor(options) {
            super();
            // 合并配置
            this.opts = Object.assign({
                width: "30%",
                height: "200px",
                title: "默认标题",
                content: "默认内容",
                dragable: true, //是否可拖拽
                maskable: true, //是否有遮罩
                isCancel: false, //是否有取消
                success() {
                    console.log("默认点击确定了!");
                },
                cancel() {
                    console.log("默认点击取消了");
                },
            }, options);

            this.init();
        }
        init() {

            this.renderView();

            let cancel = new Event("cancel");
            this.addEventListener("cancel", this.opts.cancel);
            // let success = new Event("success");
            this.addEventListener("success", this.opts.success);

            this.dialogHTML.onclick = e => {
                switch (e.target.className) {
                    case 'k-close':
                        this.close();
                        this.dispatchEvent(cancel);
                        break;
                    case 'k-cancel':
                        this.close();
                        this.dispatchEvent(cancel);
                        break;
                    case 'k-primary':
                        this.close();
                        this.confirm();
                        break;
                }
            }
        }
        // 页面渲染
        renderView() {
            this.dialogHTML = document.createElement("div");
            this.dialogHTML.innerHTML =
                `
                <div class="k-wrapper"></div>
                <div class="k-dialog" style="width:${this.opts.width};height:${this.opts.height}">
                    <div class="k-header">
                        <span class="k-title">${this.opts.title}</span><span class="k-close">X</span>
                    </div>
                    <div class="k-body">
                        <span>${this.opts.content}</span>
                    </div>
                    <div class="k-footer">
                        ${this.opts.isCancel?'<span class="k-cancel">取消</span>':''}
                        <span class="k-primary">确定</span>
                    </div>
                </div>
            `
            document.querySelector("body").appendChild(this.dialogHTML);
        }

        // 显示对话框
        open() {
            if (this.opts.maskable) {
                this.dialogHTML.querySelector(".k-wrapper").style.display = "block";
            }
            this.dialogHTML.querySelector(".k-dialog").style.display = "block";
        }

        // 关闭对话框
        close() {
            if (this.opts.maskable) {
                this.dialogHTML.querySelector(".k-wrapper").style.display = "none";
            }
            this.dialogHTML.querySelector(".k-dialog").style.display = "none";
        }
        
        // 获取对话框的值
        confirm(value){
            let success = new CustomEvent("success",{
                detail:value
            });
            this.dispatchEvent(success);
        }
    }

    class ExtendsDialog extends Dialog {
        constructor(options) {
            super(options);
            this.renderInput();
        }
        renderInput() {
            let myInput = document.createElement("input");
            myInput.type = "text";
            myInput.classList.add("input-inner");
            this.dialogHTML.querySelector(".k-body").appendChild(myInput);
        }
        confirm(){
            let value = this.dialogHTML.querySelector(".input-inner").value;
            super.confirm(value);
        }
    }

    let dialog1 = new Dialog({
        width: "40%",
        title: "dialog1测试标题",
        content: "dialog1测试内容",
        isCancel: true,
        maskable: false,
    });
    document.querySelector(".dialog1").onclick = function () {
        dialog1.open();
    }

    let dialog2 = new ExtendsDialog({
        width: "40%",
        height: "250px",
        title: "dialog2测试标题",
        content: "dialog2测试内容",
        isCancel: true,
        maskable: false,
        success(e){
            console.log('内容是:',e.detail);
        }
    });
    document.querySelector(".dialog2").onclick = function () {
        dialog2.open();
    }
</script>

</html>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值