参考 alert 组件改造 element 的dialog组件

410 阅读2分钟

在新公司发现弹框是基于 element 改造,但是是依然需要引入组件,设置变量来控制显示隐藏。
对比之前公司,基于 vxe-table 组件的 modal 组件二次封装,在使用时,只需要引用然后调用打开或关闭某个方法 所以,对比二者,简单封装个 demo

参数

按照常用的弹框需求,常见的情形大概有

  1. 只显示弹窗内容
  2. 需要传值给弹框内部组件
  3. 弹窗的宽高,标题的对应参数
  4. 弹窗向外抛出事件

所以在调用时设置参数有:
component 引用的组件
props 传递给 component 的值
options el-dialog 的参数
event 回调的事件

代码

import modal from '../components/modal/index.js' // 弹框组件
import modalContent from '../components/modal/modal-content' // 弹框里面的内容组件

modal.open({
    component: modalContent,
    props:{
        sendModalVal:'传递给弹窗的值'
    },
    options: {
        title: '消息提示',
    }},{
    close(name) {
        console.log('我关闭了')
        modal.close(name)
    },
    changeNum(val) {
        console.log('是我来自弹框组件的值',val)
    }
})

index.js 组件挂载到 dom 上,重点$mount()方法

// WModal.js
import Vue from 'vue';

// 具体的组件
import WModal from './modal.vue';

WModal.newInstance = properties => {
    const props = properties || {};
    // 实例化一个组件,然后挂载到 body 上
    const Instance = new Vue({
        data: props,
        render(h) {
            return h(WModal, {
                props: props
            });
        }
    });
    const component = Instance.$mount();
    document.body.appendChild(component.$el);
    // 通过闭包维护 modal 组件的引用
    const modal = Instance.$children[0];
    return {
        // modal 组件对外暴露的两个方法
        add(modalProps, event) {
            modal.add(modalProps, event);
        },
        remove(name) {
            modal.remove(name);
        }
    }
};

// 提示单例
let messageInstance;

function getMessageInstance() {
    messageInstance = messageInstance || WModal.newInstance();
    return messageInstance;
}

function open({ component, props, options = {title:'提示'}}, event) {
    // 等待接口调用的时候再实例化组件,避免进入页面就直接挂载到 body 上
    let instance = getMessageInstance();
    instance.add({
        component,
        props,
        options
    }, event)
}

function close(id = '') {
    // 等待接口调用的时候再实例化组件,避免进入页面就直接挂载到 body 上
    let instance = getMessageInstance();
    instance.remove(id)
}

// 对外暴露的方法
let modal = {
    open(params, event) {
        return open(params, event);
    },
    close(name) {
        return close(name);
    }
}
export default modal

modal.vue 组件 template,将每个 modal 对象遍历出来,重点:v-on 和 v-bind

<template>
  <div class='modal'>
    <div class='modal-main' v-for='item in modals' :key='item.id'>
      <el-dialog
        :visible='true'
        v-on='item.event'
        v-bind='item.options'
        @close='remove(item.id)'
      >
        <span>{{ item.id }}</span>
        <component :is='item.component' :id='item.id' v-bind='item.props' v-on='item.event'></component>
        <span slot='footer' class='dialog-footer'>
          <el-button @click='remove(item.id)'>取 消</el-button>
          <el-button type='primary' @click='remove(item.id)'>确 定</el-button>
        </span>
      </el-dialog>
    </div>
  </div>
</template>

<script>
let seed = 0;
function getUuid() {
  return 'modal_' + (seed++);
}

export default {
  data() {
    return {
      modals: []
    }
  },
  methods: {
    add(modal, event) {
      console.log(modal)
      const id = getUuid();
      let _modal = Object.assign({
        id: id,
        event
      }, modal);
      this.modals.push(_modal);
    },
    remove(id) {
      const modals = this.modals;
      for (let i = 0; i < modals.length; i++) {
        if (modals[i].id === id) {
          this.modals.splice(i, 1);
          break;
        }
      }
    },
    close(id) {
      this.$emit('close',id)
    }
  }
}
</script>

在 modalContent 中,主要是抛出事件,和获取 modal 传来的值

this.sendModalVal=this.$attrs.sendModalVal

this.$emit('changeNum',this.num)