首页 前端知识 【vue】弹窗组件的几种调用方式

【vue】弹窗组件的几种调用方式

2024-05-25 09:05:56 前端知识 前端哥 814 211 我要收藏

写在前面

本文仅代表个人对vue组件的一些粗浅认识,仅供参考,如有错漏,欢迎指出。

vue 弹窗组件的几种调用方式

1. 同一组件调用

<template>
  <el-button plain @click="dialogVisible = true" >
    Click to open the Dialog
  </el-button>

  <el-dialog
    v-model="dialogVisible"
    title="Tips"
    width="500"
    :center="false"
    :before-close="handleClose"
  >
    <template #footer>
      <div class="dialog-footer">
        <el-button @click="dialogVisible = false">Cancel</el-button>
        <el-button type="primary" @click="dialogVisible = false">
          Confirm
        </el-button>
      </div>
    </template>
  </el-dialog>
</template>

<script lang="ts" setup>
import { ref } from 'vue'
import { ElMessageBox } from 'element-plus'

const dialogVisible = ref(false)

const handleClose = (done: () => void) => {
  ElMessageBox.confirm('Are you sure to close this dialog?')
    .then(() => {
      done()
    })
    .catch(() => {
      // catch error
    })
}
</script>

缺点:弹窗代码在父组件中,导致代码较多

2.父子组件调用

父组件

<template>
<el-button @click="clickBtn">点击出现弹窗</el-button>
<Dialog v-model:visible="visible" @close="close" @submit="submit"></Dialog>
</template>

<script setup lang="ts">
import { ref } from 'vue';
import Dialog from './components/Dialog.vue';

const visible = ref(false)

const clickBtn = () => {
    visible.value = true
}
const close = () => {
    visible.value = false
}
const submit =() => {
    visible.value =false
}
</script>


子组件

<template>
    <el-dialog v-model="props.visible" title="dialog" width="452px">
        <el-button @click="close">取消</el-button>
        <el-button @click="$emit('update:visible', false)">确定</el-button>
    </el-dialog>
</template>

<script lang="ts" setup>
const props = defineProps( { visible: Boolean})
const emit = defineEmits(['update:visible'])
const close =() => {
    emit('update:visible')
}
</script>

缺点:需要一个变量控制子组件展示隐藏,耦合重

3.父组件调用子组件方法

子组件暴露弹窗打开关闭方法

<template>
    <el-dialog v-model="visible" title="dialog" width="452px">
        <el-button @click="close">取消</el-button>
        <el-button @click="submit">确定</el-button>
    </el-dialog>
</template>

<script lang="ts" setup>
import {ref} from 'vue'
const emit = defineEmits(['submit'])

const visible = ref(false)

const open = () => {
    visible.value = true
}

const close =() => {
    visible.value = false
}

const submit = () => {
    visible.value = false
    emit('submit', [123])
}

defineExpose({open, close})
</script>

父组件通过ref调用

<template>
<el-button @click="clickBtn">点击出现弹窗</el-button>
<Dialog2 ref="dialogRef" @submit="submit"></Dialog2>
</template>

<script setup lang="ts">
import { ref } from 'vue';
import Dialog2 from './components/Dialog2.vue';

const dialogRef = ref()

const clickBtn = () => {
    dialogRef.value.open()
}

const submit =(list) => {
    console.log('list :>> ', list);
    dialogRef.value.close()
}
</script>

缺点:需要知道子组件暴露的方法,不利于解耦

4.函数式调用

子组件

<template>
    <el-dialog v-model="visible" title="dialog" width="452px">
        <el-button @click="close">取消</el-button>
        <el-button @click="submit">确定</el-button>
    </el-dialog>
</template>

<script lang="ts" setup>
import {onMounted, ref}  from 'vue'

interface Props {
    close?: () => void,
    submit?: (list:any) => void
}
const props = defineProps<Props>( )

const visible = ref(false)

onMounted( () => {
    visible.value = true
})

const close =() => {
    visible.value = false
    props?.close?.()
}
const submit = () => {
    visible.value = false
    props?.submit?.([123])
}
</script>

index.ts: 动态调用

import Dialog3 from './Dialog3.vue'
import  { createApp } from 'vue';

const useDialog = (options: any) => {
    const mountNode = document.createElement('div')
    document.body.appendChild(mountNode)
    
    return new Promise((resolve, reject) => {
        let app: any = createApp(Dialog3, {
            ...options,
            close: () => {
                app.unmount()
                mountNode.remove()
                app = undefined
                reject()
            },
            submit: (list: any) => {
                app.unmount()
                mountNode.remove()
                app = undefined
                resolve(list)
            }
        })
    
        if (app) {
            app.mount(mountNode)        
        }
    })
    

}
export default useDialog


父组件中使用

<template>
  <el-button @click="clickBtn">点击出现弹窗</el-button>
  </template>
  
  <script setup lang="ts">
  import useDialog from './index.ts'
  
  
  const clickBtn = () => {
      useDialog({}).then(list => {
          console.log('object :>> ', list);
      })
  }
  
  </script>
  
  

优点: 需要使用组件式才调用,只需要传递props,不需要了解子组件内部逻辑
很多组件都是使用这种思想,如element-plus的MessageBox

转载请注明出处或者链接地址:https://www.qianduange.cn//article/9459.html
标签
评论
会员中心 联系我 留言建议 回顶部
复制成功!