如何手动关闭element plus的messageBox?

新手上路,请多包涵

element plus版本:2.3.0
需求:在childName子组件中点击按钮,关闭他所在的ElMessageBox,可以怎么实现?
也就说除了消息弹出框自带的关闭按钮等,可以在子组件中获取ElMessageBox实例,通过调用ElMessageBox实例的方法来关闭消息弹出框么?
最终使用的方案4
已经尝试过的方案:

  1. 直接调用ElMessageBox.close();会关闭当前打开的所有消息弹出框。
  2. 通过消息弹出框的class找到它的dom元素,手动移除消息弹出框的dom。可以实现,但是并不想使用这种方法
  3. 评论中给出的options对象上的onVanish()方案
  4. 子组件中通过getCurrentInstance获取到当前实例,再获取父实例。但是要四层$parent才能调用到源码里的doClose方法

     <template>
      <el-button plain @click="open">Common VNode</el-button>
      <el-button plain @click="open1">Dynamic props</el-button>
    </template>
    
    <script lang="ts" setup>
    import { h, ref } from 'vue'
    import { ElMessageBox, ElSwitch } from 'element-plus'
    import ChildName from './ChildName.vue'
    
    const open = () => {
      ElMessageBox({
     title: 'Message',
     message: h(ChildName, { options: () => options }),
      })
    }
    
    const open1 = () => {
      const checked = ref<boolean | string | number>(false)
      ElMessageBox({
     title: 'Message',
     // Should pass a function if VNode contains dynamic props
     message: () =>
       h(ElSwitch, {
         modelValue: checked.value,
         'onUpdate:modelValue': (val: boolean | string | number) => {
           checked.value = val
         },
       }),
      })
    }
    </script>
    

    子组件ChildName.vue的代码

<template>
  <div>
    子组件的内容
    <el-button @click="handleHide">
      自定义关闭关闭
    </el-button>
  </div>
</template>

<script lang="tsx">
import {
  defineComponent,getCurrentInstance,
} from 'vue'
import { ElButton, ElMessage } from 'element-plus'
export default defineComponent({
  name: 'ChildName',
  components: {
    ElButton,
  },
  props: {
    options: {
      type: Function,
      default: () => {},
    },
  },
  setup (props: any) {
    const instance = getCurrentInstance() as any
    const { proxy } = instance
    // 关闭弹窗
    const handleHide = () => {
      // 方案3,但是不太合适
      // props.options()?.onVanish()
      // 方案4
      proxy.$parent.$parent.$parent.$parent.handleClose()
    }
    return {
      handleHide,
    }
  },
})
</script>

补充:四层$parent的原因是:父组件引用子组件的时候还在外面套了多层 UI 组件。
子组件ChildName的$parent是Element Plus的组件el-focus;
$parent.$parent是Element Plus的组件el-overlay;
$parent.$parent.$parent是Element Plus的组件transtion;
$parent.$parent.$parent.$parent才是ElMessageBox组件。

阅读 8.3k
4 个回答
✓ 已被采纳新手上路,请多包涵

最终采用的方案4
通过getCurrentInstance获取当前的ChildName实例对象,然后依次获取其父组件实例,直到获取到ElMessageBox实例对象。调用其handClose方法进行消息弹出框的关闭。

setup (props: any) {
  const instance = getCurrentInstance() as any
  const { proxy } = instance
  // 关闭弹窗
  const handleHide = () => {
    // 方案3,但是不太合适
    // props.options()?.onVanish()
    // 方案4
    proxy.$parent.$parent.$parent.$parent.handleClose()
  }
  return {
    handleHide,
  }
 },

可以另辟蹊跷,看源码得知,ElMessageBox是对options进行填充的
image.png
所以可以直接使用options.onVanish()进行移除
image.png

elMessageBox = ElMessageBox() 拿到返回的这个东西,然后 elMessageBox.close()

你想啊,你 close 的时候,代码怎么知道你要关闭谁呢? 为了告诉代码关闭谁,肯定需要有当前显示的弹窗参与嘛,那就有两种,一个是 close 传值 (应该是没实现这种东西,你可以试一下),一个是实例调用 close。

本文参与了SegmentFault 思否面试闯关挑战赛,欢迎正在阅读的你也加入。

MessageBox 消息弹框看着应该是全局覆盖的,覆盖全局的情况下应该弹窗唯一,但也可能是你这里弹窗中有弹窗,那么可以通过 show-close 展示出关闭按钮,通过 js 选择这个关闭按钮,模拟用户点击实现对应弹窗关闭。

本文参与了SegmentFault 思否面试闯关挑战赛,欢迎正在阅读的你也加入。
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题