ES6 弹窗组件

<!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%;
        }

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

        .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-default {
            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-default: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-default">取消</span>
        <span class="k-primary">确定</span>
    </div>
</div> -->
<button class="btn">点击显示对话框</button>
<script src="./js/dialog.js" type="text/javascript"></script>
<script>
let dialog = new Dialog({
    width:"40%",
    height:"400px",
    title:"测试标题111",
    content:"测试内容111",
    dragable:true,//是否可拖拽
    maskable:true,//是否有遮罩
    isCancel:true,//是否有取消
    cancel(){
        console.log("我点击了取消~")
    },
    sucess(){
        console.log("我点击了确定~")
    }
});
document.querySelector(".btn").onclick = function(){
    dialog.open();
}
</script>
</body>
</html>
/* 
    别人如何引用我们写的组件呢?
        1.js文件
        2.css文件
        3.js代码:
            1.new 类(参数);
                参数->需求
            2.组件标签
    弹窗组件代码解析:
        1.创建类
        2.默认参数 配置参数 配置项
            在使用类的时候,不需要全部配置都传进去,也可以只传一个或者不传也达到可以执行效果.
            Object.assign
                两个对象合并为一个对象,有相同的就以后面的为主
                第一个对象是默认值
                第二个对象代替第一项
            解构赋值
            默认参数:(width="30%",height="250px",title="测试标题"...) = options;
        3.生成dom结构 createHtml();
            1.创建div
            2.div放置元素
            3.body放入div
                appendChild
            4.创建了之后也是一个隐藏状态
                div.display none
                在点击按钮的时候才显示
        4.初始化函数 init();
            一些一开始就调用的方法放到这里面
            1.实例化完类先调用 this.init();
        5.显示对话框 open()
            这个方法当用户进行单击的时候执行;
            注:找元素,不要使用document.querySelector(""), 应该使用 this.div
        6.对传进来的内容做呈现
            在createHtml,init方法中进行判断...
            1.标题,内容 -> this.opts.title this.opts.content
            2.宽高 -> style=""
            3.遮罩层判断 -> 在init中if(this.opts.maskable)...;
                this.div.querySelector("....").disp none
            4.是否有取消 -> 在dom结构进行三目运算:
                ${this.opts.isCancel?`<span class="k-default">取消</span>`:``}
        7.关闭对话框 close();
            this.div none
            init -> 元素(取消).点击执行close();
            取消按钮:
                判断是否有此节点
        8.关闭对话框2 事件委托
            这三个事件都是在div身上发生的,所以可以使用事件委托:
            this.div.onclick = e=>{
                console.log(e.target);
            }
            若假如有多个className可以使用正则来搞定,但一般情况下,这个组件是自己封装的是完全可控的;
            取消与确定按钮的回调函数:
                1.默认配置也要有这两个回调函数
                    cancel(){},
                    sucess(){}
                2.再点击的时候执行此函数呗...
        9.是否可以拖拽: drag();
            1.先写拖拽函数
            2.在init判断是否可以拖拽
*/
class Dialog{
    constructor(option){
        this.opts = Object.assign({
            width:"30%",
            height:"250px",
            title:"测试标题",
            content:"测试内容",
            dragable:true,//是否可拖拽
            maskable:true,//是否有遮罩
            isCancel:false,//是否有取消
            cancel(){},
            sucess(){}
        },option);
        this.init();
    }
    init(){
        this.createHtml();
        if(!this.opts.maskable){
            this.div.querySelector(".k-wrapper").style.display = "none";
        }
        /* this.div.querySelector(".k-close").onclick = ()=>{
            this.close();
        }
        this.div.querySelector(".k-default").onclick = ()=>{
            this.close();
        } */
        this.div.onclick = e=>{
            // console.log(e.target);
            switch(e.target.className){
                case "k-close":
                    this.close();
                    break;
                case "k-default":
                    this.close();
                    this.opts.cancel();
                    break;
                case "k-primary":
                    this.close();
                    this.opts.sucess();
                    break;
                default :
                    console.log("没点中~");
                    break;
            }
        };
        if(this.opts.dragable){
            this.drag();
        }
    }
    createHtml(){
        this.div = document.createElement("div");
        this.div.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-default">取消</span>`:``}
                    <span class="k-primary">确定</span>
                </div>
            </div>
        `;
        this.div.style.display = "none";
        document.querySelector("body").appendChild(this.div);
    }
    // 显示对话框
    open(){
        this.div.style.display = "block";
    }
    // 关闭对话框
    close(){
        this.div.style.display = "none";
    }
    // 拖拽
    drag(){
        let kDialog = this.div.querySelector(".k-dialog");
        kDialog.onmousedown = e=>{
            let x = e.clientX - kDialog.offsetLeft;
            let y = e.clientY - kDialog.offsetTop;
            document.onmousemove = e=>{
                let xx = e.clientX - x;
                let yy = e.clientY - y;
                console.log(xx,yy)
                kDialog.style.left = xx + "px";
                kDialog.style.top = yy + "px";
            }
            document.onmouseup = function(){
                document.onmousemove = null;
            }
        }
    }
}

 扩展内容

<!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%;
        }

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

        .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-default {
            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-default: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-default">取消</span>
        <span class="k-primary">确定</span>
    </div>
</div> -->
<button class="btn">点击显示对话框</button>
<button class="btn2">点击显示带输入框的对话框</button>
<show-dialog
    width="40%"
    height="300px"
    title="自定义组件标题"
>自定义组件弹框</show-dialog>
<script src="./js/dialog.js" type="text/javascript"></script>
<script>
let dialog = new Dialog({
    width:"40%",
    height:"220px",
    title:"测试标题111",
    content:"测试内容111",
    dragable:true,//是否可拖拽
    maskable:true,//是否有遮罩
    isCancel:true,//是否有取消
    cancel(){
        console.log("我点击了取消~")
    },
    sucess(){
        console.log("我是页面中的回调:点击了确定~");
    }
});
document.querySelector(".btn").onclick = function(){
    dialog.open();
}

let dialog2 = new ExtendsDialog({
    width:"40%",
    height:"220px",
    title:"测试标题222",
    content:"测试内容222",
    dragable:true,//是否可拖拽
    maskable:true,//是否有遮罩
    isCancel:true,//是否有取消
    cancel(){
        console.log("我点击了取消~,第二个")
    },
    sucess(e){
        console.log(e);
        console.log("我是页面中的回调:点击了确定~,第二个值为:",e.detail);
    }
});
document.querySelector(".btn2").onclick = function(){
    dialog2.open();
}

</script>
</body>
</html>
/* 
    别人如何引用我们写的组件呢?
        1.js文件
        2.css文件
        3.js代码:
            1.new 类(参数);
                参数->需求
            2.组件标签
    弹窗组件代码解析:
        1.创建类
        2.默认参数 配置参数 配置项
            在使用类的时候,不需要全部配置都传进去,也可以只传一个或者不传也达到可以执行效果.
            Object.assign
                两个对象合并为一个对象,有相同的就以后面的为主
                第一个对象是默认值
                第二个对象代替第一项
            解构赋值
            默认参数:(width="30%",height="250px",title="测试标题"...) = options;
        3.生成dom结构 createHtml();
            1.创建div
            2.div放置元素
            3.body放入div
                appendChild
            4.创建了之后也是一个隐藏状态
                div.display none
                在点击按钮的时候才显示
        4.初始化函数 init();
            一些一开始就调用的方法放到这里面
            1.实例化完类先调用 this.init();
        5.显示对话框 open()
            这个方法当用户进行单击的时候执行;
            注:找元素,不要使用document.querySelector(""), 应该使用 this.div
        6.对传进来的内容做呈现
            在createHtml,init方法中进行判断...
            1.标题,内容 -> this.opts.title this.opts.content
            2.宽高 -> style=""
            3.遮罩层判断 -> 在init中if(this.opts.maskable)...;
                this.div.querySelector("....").disp none
            4.是否有取消 -> 在dom结构进行三目运算:
                ${this.opts.isCancel?`<span class="k-default">取消</span>`:``}
        7.关闭对话框 close();
            this.div none
            init -> 元素(取消).点击执行close();
            取消按钮:
                判断是否有此节点
        8.关闭对话框2 事件委托
            这三个事件都是在div身上发生的,所以可以使用事件委托:
            this.div.onclick = e=>{
                console.log(e.target);
            }
            若假如有多个className可以使用正则来搞定,但一般情况下,这个组件是自己封装的是完全可控的;
            取消与确定按钮的回调函数:
                1.默认配置也要有这两个回调函数
                    cancel(){},
                    sucess(){}
                2.再点击的时候执行此函数呗...
        9.是否可以拖拽: drag();
            1.先写拖拽函数
            2.在init判断是否可以拖拽
        10.确认功能拆分:sure();
            组件开发功能划分的越细,后面的扩展更方便;
        11.使用自定义事件,绑定一些事件 EventTarget
            这是 系统 自己做了封装处理了;
            https://developer.mozilla.org/zh-CN/docs/Web/API/EventTarget
            1.继承 extends EventTarget
            2.super();
            3.绑定:addEventListener
                this.addEventListener("close",this.close);
                this.addEventListener("close",()=>{console.log("使用了自定义事件触发了,close")});
            4.触发:
                稍微麻烦一点,需要实例化一下
                let close = new CustomEvent("close");
                this.dispatchEvent(close);
        12.带input框的组件新功能的增加 
            若不想改变原来的东西,例游戏更新版本更新,更新失败后我们可以用版本回撤,原来版本不会发生改变;
            所以这里使用继承类 ExtendsDialog
            1.继承
                extends
                super();
            2.参数
                option
            3.input的添加
                找到对应的函数 createHtml();
                1.继承此函数:
                    super.createHtml();
                2.创建input放到对应位置:
                    let myInput = document.createElement("input");
                    myInput.type = "text";
                    myInput.classList.add("input-inner");
                    this.div.querySelector("k-body").appendChild(myInput);
            尽可能少改变我们原来的 类 实现我们的功能;
            4.点击确定 在回调中获取输入框内容的;
                1.子类调用的时候传给父类
                    super.sure(value);
                2.父类接收;
                    sure(value);
                3.使用自定义事件传递
                    let sucess = new CustomEvent("sucess",{
                        detail:value
                    });
                4.回调接收参数;
                    sucess(e){
                        console.log(e);
                        console.log("我是页面中的回调:点击了确定~,第二个值为:",e.detail);
                    }
                不适用detail当然简单的方式也有:
                    this.opts.sucess(value);
        13.引用方式也可以进行 模块化
        14.标签形式调用方式 -> 自定义组件:
            例如vue:
                <my-dialog
                    width="40%"
                    title="测试标题"
                ></my-dialog>
                直接把配置放到属性中
            如何模拟这样的调用方式呢: webComponent
                https://www.cnblogs.com/Afanadmin/p/12381393.html
            1.获取节点属性:
                attributes:
                    let attr = this.attributes;
            2.传递节点属性进入对话框;
                1.判断是否有输入属性
                    let width = this.hasAttribute("width")?attr.width.value:"40%";
                    
*/
class Dialog extends EventTarget{
    constructor(options){
        super();
        this.opts = Object.assign({
            width:"30%",
            height:"250px",
            title:"测试标题",
            content:"测试内容",
            dragable:true,//是否可拖拽
            maskable:true,//是否有遮罩
            isCancel:false,//是否有取消
            cancel(){},
            sucess(){}
        },options);
        this.init();
    }
    init(){
        this.createHtml();
        if(!this.opts.maskable){
            this.div.querySelector(".k-wrapper").style.display = "none";
        }
        /* this.div.querySelector(".k-close").onclick = ()=>{
            this.close();
        }
        this.div.querySelector(".k-default").onclick = ()=>{
            this.close();
        } */

        // 绑定事件;
        this.addEventListener("close",this.close);
        this.addEventListener("close",()=>{console.log("使用了自定义事件触发了,close")});
        // 确定按钮回调函数 绑定自定义事件;
        this.addEventListener("sucess",this.opts.sucess);

        this.div.onclick = e=>{
            // console.log(e.target);
            switch(e.target.className){
                case "k-close":
                    // this.close();
                    let close = new CustomEvent("close");
                    this.dispatchEvent(close);
                    break;
                case "k-default":
                    this.close();
                    this.opts.cancel();
                    break;
                case "k-primary":
                    // 确认按钮
                    this.sure();
                    break;
                default :
                    console.log("没点中~");
                    break;
            }
        };
        if(this.opts.dragable){
            this.drag();
        }
    }
    sure(value){//2.父类接收
        // this.close();
        // this.opts.sucess();
        let close = new CustomEvent("close");
        this.dispatchEvent(close);

        let sucess = new CustomEvent("sucess",{
            detail:value
        });
        this.dispatchEvent(sucess);
    }
    createHtml(){
        this.div = document.createElement("div");
        this.div.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-default">取消</span>`:``}
                    <span class="k-primary">确定</span>
                </div>
            </div>
        `;
        this.div.style.display = "none";
        document.querySelector("body").appendChild(this.div);
    }
    // 显示对话框
    open(){
        this.div.style.display = "block";
    }
    // 关闭对话框
    close(){
        this.div.style.display = "none";
    }
    // 拖拽
    drag(){
        let kDialog = this.div.querySelector(".k-dialog");
        kDialog.onmousedown = e=>{
            let x = e.clientX - kDialog.offsetLeft;
            let y = e.clientY - kDialog.offsetTop;
            if(e.target.className !== "input-inner"){
                document.onmousemove = e=>{
                    let xx = e.clientX - x;
                    let yy = e.clientY - y;
                    kDialog.style.left = xx + "px";
                    kDialog.style.top = yy + "px";
                }
                document.onmouseup = function(){
                    document.onmousemove = null;
                }
            }
        }
    }
}

// 带input的对话框;
class ExtendsDialog extends Dialog{
    constructor(options){
        super(options);
    }
    createHtml(){
        super.createHtml();
        let myInput = document.createElement("input");
        myInput.type = "text";
        myInput.classList.add("input-inner");
        this.div.querySelector(".k-body").appendChild(myInput);
    }
    sure(){
        let value = this.div.querySelector(".input-inner").value;
        console.log(value);
        super.sure(value);//1.子类传给父类
    }
}

// 自定义组件
class ShowDialog extends HTMLElement{
    constructor(){
        super();
        // console.log(this);
        // 获取节点属性;
        let attr = this.attributes;
        let width = this.hasAttribute("width")?attr.width.value:"40%";
        let height = this.hasAttribute("height")? attr.height.value:"250px";
        let title = this.hasAttribute("title")?attr.title.value:"测试标题";
        let content = this.hasAttribute("content")? attr.content.value:"内容";
        // 注意布尔值: -> 获取到的值是一个字符串;
        let maskable = null;
        if(this.hasAttribute("maskable")){
            maskable = attr.maskable.value;
        }else{
            maskable = 'true';
        }
        maskable = maskable==='true'?true:false;
        let dragable = null;
        if(this.hasAttribute("dragable")){
            dragable = attr.dragable.value;
        }else{
            dragable = 'true';
        }
        dragable = dragable==='true'?true:false;
        let isCancel = null;
        if(this.hasAttribute("isCancel")){
            isCancel = attr.isCancel.value;
        }else{
            isCancel = 'false';
        }
        isCancel = isCancel==='true'?true:false;
        /* 
            判断是否有这个值;
                有就赋值;
            三木判断是否等于 字符串'true'
                将转为布尔值
        */
        let dialog = new Dialog({
            width,
            height,
            title,
            content,
            dragable,
            maskable,
            isCancel
        });

        this.innerHTML = `<button>${this.innerText}</button>`;
        this.onclick = function(){
            dialog.open();
        }
    }
}
customElements.define("show-dialog",ShowDialog);

 

posted @ 2020-02-27 10:06  JackAfan  阅读(432)  评论(0)    收藏  举报
setTimeout(function(){ let aImg = document.querySelectorAll("img"); aImg.forEach(img=>{ img.alt = "" }) console.log("去除img-alt成功") },1000)