Vue3+Element Plus实现自定义弹窗组件的全屏功能

 更新时间:2024年07月17日 08:50:43   作者:阳光的男夹克  
在现代化的前端开发中,弹窗组件是提升用户体验的重要元素,本文将介绍如何使用 Vue 3 和 Element Plus 库来创建一个具有全屏功能的自定义弹窗组件,文中通过代码示例讲解的非常详细,需要的朋友可以参考下

组件概述

我们将构建一个名为 Dialog 的 Vue 组件,该组件具备以下特性:

  • 自定义头部,包括全屏和关闭按钮
  • 支持全屏和还原功能
  • 可配置的弹窗尺寸和位置
  • 拖拽功能(可选)
  • 动态内容区域高度

以下是实现自定义弹窗组件的详细步骤和代码示例。

组件实现

1. 组件模板

我们使用 el-dialog 作为基础组件,并自定义了 header 插槽以添加全屏按钮和关闭图标。

<template>
  <el-dialog
    :dialogHeight="dialogHeight"
    :title="dialogTitle"
    class="dialog min-w-70"
    v-model="dialogVisible"
    append-to-body
    :modal="dialogModal"
    :fullscreen="fullscreen"
    :close-on-click-modal="dialogClickModalClose"
    :draggable="dialogDraggable"
    :show-close="false"
    :width="dialogWidth"
    :align-center="dialogAlignCenter"
    :center="dialogContentCenter"
    @open="open"
    @close="close"
  >
    <template #header>
      <div class="flex justify-between items-content">
        <div class="titleClass">{{ dialogTitle }}</div>
        <div class="icon-content">
          <!-- <el-icon class="single-uploader__icon text-[12px]">
              <i-ep-minus v-if="fullscreen" />
              <i-ep-plus v-else />
            </el-icon>-->
          <div :title="!fullscreen ? '全屏' : '还原'">
            <svg-icon
              class="icon-item-content"
              v-if="showExpand"
              @click="zoom"
              :icon-class="fullscreen ? 'fullscreen-exit' : 'fullscreen'"
            />
          </div>
          <div title="关闭">
            <el-icon
              v-if="showClose"
              @click="close"
              title="关闭"
              class="single-uploader__icon icon-item-content"
            >
              <i-ep-close />
            </el-icon>
          </div>
        </div>
      </div>
    </template>
    <div :style="{ height: dialogBodyHeight }" class="overflow-auto">
      <slot></slot>
    </div>
    <template #footer v-if="dialogFooterBtn">
      <el-button type="primary" @click="SaveSubmit">确 定</el-button>
      <el-button @click="CloseSubmit">取 消</el-button>
    </template>
  </el-dialog>
</template>

2. 组件脚本

在脚本部分,我们定义了组件的 props、slots 和 emits,以及一些必要的响应式数据和函数。

<script setup lang="ts">
// 【接口】接受传参字段
interface IProps {
  // 是否显示 Dialog
  visible: boolean;
  // 对话框的标题
  dialogTitle?: string;
  // 内容区域高度
  dialogHeight?: string;
  // 对话框的宽度
  dialogWidth?: string;
  // 是否需要遮罩层
  dialogModal?: boolean;
  // 是否水平垂直对齐对话框
  dialogAlignCenter?: boolean;
  // 是否让 Dialog 的 header 和 footer 部分居中排列
  dialogContentCenter?: boolean;
  // 是否可以通过点击 modal 关闭 Dialog
  dialogClickModalClose?: boolean;
  // 为 Dialog 启用可拖拽功能
  dialogDraggable?: boolean;
  // 是否显示底部按钮
  dialogFooterBtn?: boolean;
  // 是否显示全屏按钮
  showExpand?: boolean;
  // 是否显示关闭按钮
  showClose?: boolean;
}

// 初始化默认参数
const props = withDefaults(defineProps<IProps>(), {
  dialogTitle: "默认标题",
  dialogWidth: "40%",
  dialogHeight: "auto",
  dialogModal: true,
  dialogAlignCenter: false,
  dialogContentCenter: false,
  dialogClickModalClose: false,
  dialogDraggable: false,
  dialogFooterBtn: true,
  showExpand: false,
  showClose: true,
});

const emit = defineEmits([
  "save",
  "cancellation",
  "open",
  "close",
  "zoom",
  "update:visible",
]);

const dialogVisible = useVModel(props, "visible", emit);
let fullscreen = ref(false);
const dialogBodyHeight = ref<string | number>(); // 初始值为字符串类型

// watch监听
watch(
  [() => props.visible, () => props.dialogHeight, () => props.dialogFooterBtn],
  () => {
    nextTick(() => {
      menuDialogZoom();
    });
  },
  { deep: true, immediate: true }
);

// 保存提交回调函数
const SaveSubmit = () => {
  emit("save"); //emit方法供父级组件调用
};

// 取消保存回调函数
const CloseSubmit = () => {
  emit("cancellation"); //emit方法供父级组件调用
};

// 打开事件回调函数
const open = () => {
  emit("open"); //emit方法供父级组件调用
};

// 关闭事件回调函数(当显示头部关闭按钮时需调用该回调函数方法 -> dialogShowClose = true 反之)
const close = () => {
  emit("close"); //emit方法供父级组件调用
};

// 缩放弹窗
const zoom = () => {
  fullscreen.value = !fullscreen.value;
  menuDialogZoom();
  console.log(fullscreen.value);
  emit("zoom", fullscreen.value); //emit方法供父级组件调用
};

/* 分配权限缩放弹窗 */
const menuDialogZoom = () => {
  if (props.visible && fullscreen.value && props.dialogFooterBtn) {
    dialogBodyHeight.value = "calc(100vh - 120px)";
  } else if (props.visible && fullscreen.value && !props.dialogFooterBtn) {
    dialogBodyHeight.value = "calc(100vh - 80px)";
  } else {
    dialogBodyHeight.value = props.dialogHeight;
  }
};
</script>

3. 组件样式

<style scoped>
.titleClass {
  font-weight: bold;
}

.icon-content {
  display: flex;
  align-items: center;
}

.icon-item-content {
  display: flex;
  align-items: center;
  justify-content: center;
  color: #909399;
}

.icon-item-content:nth-child(1) {
  margin-right: 10px;
}

.icon-item-content:hover {
  color: #1f6feb;
  cursor: pointer;
}

.single-uploader__icon {
  font-size: 18px;
}
</style>

4. 使用案例

以下是如何在父组件中使用 Dialog 组件的示例,包括如何传递参数和处理事件。

<Dialog
	dialogHeight="350px"
	v-model:visible="menuDialogVisible"
	:dialogTitle="'【' + checkedRole.name + '】权限分配'"
	:dialogDraggable="true"
	dialogWidth="30%"
	@close="menuDialogVisible = false"
	@save="handleRoleMenuSubmit"
	@cancellation="menuDialogVisible = false"
>
	内容区域
</Dialog>

5. 弹窗相关数据

定义了控制弹窗显示的响应式数据。

let menuDialogVisible = ref(false);

关键功能实现

自定义头部

我们通过 header 插槽来自定义弹窗的头部,增加了全屏切换按钮和关闭按钮。

<template #header>
  <!-- 省略部分代码,详见完整代码示例 -->
</template>

全屏和还原功能

通过点击全屏按钮,我们可以切换弹窗的全屏状态。这一功能通���修改 fullscreen 响应式数据实现。

const zoom = () => {
  fullscreen.value = !fullscreen.value;
  menuDialogZoom();
  emit("zoom", fullscreen.value);
};

动态内容区域高度

根据弹窗的全屏状态和是否显示底部按钮,我们动态计算内容区域的高度。

const menuDialogZoom = () => {
  // 省略部分代码,详见完整代码示例
};

结论

通过以上步骤,我们创建了一个功能丰富、高度可配置的自定义弹窗组件。这个组件可以根据实际需求调整尺寸、位置和内容,非常适合在复杂的应用场景中使用。希望这篇文章能帮助您在项目中更好地利用 Vue 3 和 Element Plus 库。如果您有任何疑问或建议,欢迎在评论区留言交流。

以上就是Vue3+Element Plus实现自定义弹窗组件的全屏功能的详细内容,更多关于Vue3 Element Plus弹窗组件全屏的资料请关注脚本之家其它相关文章!

相关文章

  • Nuxt 嵌套路由nuxt-child组件用法(父子页面组件的传值)

    Nuxt 嵌套路由nuxt-child组件用法(父子页面组件的传值)

    这篇文章主要介绍了Nuxt 嵌套路由nuxt-child组件用法(父子页面组件的传值),具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-11-11
  • Vue render函数使用详细讲解

    Vue render函数使用详细讲解

    vue中的render函数,它返回的是一个虚拟节点vnode,也就是我们要渲染的节点,下面这篇文章主要给大家介绍了关于Vue中render函数的相关资料,文中通过实例代码介绍的非常详细,需要的朋友可以参考下
    2023-01-01
  • 解决vue初始化项目时,一直卡在Project description上的问题

    解决vue初始化项目时,一直卡在Project description上的问题

    今天小编就为大家分享一篇解决vue初始化项目时,一直卡在Project description上的问题,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2019-10-10
  • Vue.js实现分页查询功能

    Vue.js实现分页查询功能

    这篇文章主要为大家详细介绍了Vue.js实现分页查询功能,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-11-11
  • Vue.js设计与实现分支切换与清除学习总结

    Vue.js设计与实现分支切换与清除学习总结

    这篇文章主要为大家介绍了Vue.js设计与实现分支切换与清除学习总结,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-05-05
  • vue2导入使用vue-codemirror组件的教程详解

    vue2导入使用vue-codemirror组件的教程详解

    vue-codemirror是一个基于Vue的代码在线编辑器组件,它封装了CodeMirror编辑器,使得在Vue项目中可以方便地使用CodeMirror,下面我们就来看看vue-codemirror的具体使用吧
    2024-02-02
  • 基于vue中css预加载使用sass的配置方式详解

    基于vue中css预加载使用sass的配置方式详解

    下面小编就为大家分享一篇基于vue中css预加载使用sass的配置方式详解,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-03-03
  • 用vue-cli开发vue时的代理设置方法

    用vue-cli开发vue时的代理设置方法

    今天小编就为大家分享一篇用vue-cli开发vue时的代理设置方法,具有很好的参考价值。希望对大家有所帮助。一起跟随小编过来看看吧
    2018-09-09
  • Vue组件如何设置Props实例详解

    Vue组件如何设置Props实例详解

    props主要用于组件的传值,他的工作就是为了接收外面传过来的数据,与data、el、ref是一个级别的配置项,下面这篇文章主要给大家介绍了关于Vue组件如何设置Props的相关资料,需要的朋友可以参考下
    2022-06-06
  • vue3中实现图片压缩的示例代码

    vue3中实现图片压缩的示例代码

    图片压缩是一种比较便捷的压缩方式,本文主要介绍了vue3中实现图片压缩的示例代码,文中通过示例代码介绍的非常详细,需要的朋友们下面随着小编来一起学习学习吧
    2024-02-02

最新评论