vue.extend动态创建弹窗组件

1,537 阅读1分钟

有时候,一个页面会有多个弹窗,而且不一定会触发,如果使用Vue.component的方法,那就要在html中提前书写,且需要多个属性去维护弹窗的显示与隐藏,那么,它来了它来了,它带着代码走来了

创建一个容纳组件的容器

function generateDialogContainer() {
    let stap = (new Date()).getTime();
    $('body').append(`<div id="ymDialog${stap}"></div>`);
    return `ymDialog${stap}`;
}

声明组件的基本结构(函数返回值形态便于传入额外的渲染参数)

function generateDialogTemplate(options) {
    let tpl = {
        template: `
        <el-dialog :title="title"
            :visible.sync="dialogShow"
            custom-class=""
            append-to-body
            >
            ${options.template}    // 相当于slot,可以传入自定义内容
            <div slot="footer" class="dialog-footer">
                <el-button @click="dialogShow = false">取 消</el-button>
                <el-button type="primary" @click="confirmEvent">确 定</el-button>
            </div>
        </el-dialog>
        `,
        data: {
                    //  不要写成函数形态,下面会对其操作
        },
        created() {
        },
        props: {
            title: String
        },
        watch: {
        },
        mounted() {
        },
        methods: {
        }
    }
    // 把参数中的data和methods与当前合并,相当于mixin
    if (!!options.data) {
        Object.keys(options.data).forEach(item => {
            tpl.data[item] = options.data[item]
        })
    }
    const temp = tpl.data
    tpl.data = function () {
        return temp
    }
    if (!!options.methods) {
        Object.keys(options.methods).forEach(item => {
            tpl.methods[item] = options.methods[item]
        })
    }
    return tpl
}

调用组件

// initData 第一次打开弹窗时默认渲染数据,可通过options或props传入
// callback 弹窗点击确定后触发
//  函数参数随意自定义
function openDialog(initData,callback) {
    // 用于存储组件对象,可通过该对象直接操作组件的data或者调用组件的methods
        // object类型,为了应对ajax请求等 异步操作
    let tagDialog = {
        obj: null
    }
    // 初始化组件参数
    let options = {
        template: '<button @click="add">{{total}}<button>',
        data: {
            total: 0
        },
        methods: {
            add() {
                this.total +=  1
            }
        }
    };
    // 传入组件的props
    let props = {
        title: "测试"
    };
    // 生成弹窗的容器
    let id = generateDialogContainer();
    // 初始化组件返回模板
    let tpl = generateDialogTemplate(options);
    // 使用Vue构造器创建一个“子类”
    let judy = Vue.extend(tpl);
    // 实例化“子类”并把它挂在dom上
    tagDialog.obj = new judy({
        propsData: props,
    }).$mount(`#${id}`);
    return tagDialog
}

调用

let dialog = null
function callback(res) {
    console.log(res)
}
let initData = [1,2,3]
if(!dialog) {
    dialog = openDialog(initData,callback)
}else {
    // 可直接通过组件对象操作
    dialog.obj.total = 10
    dialog.obj.add()
}