封装一个可以最小化和展开的弹窗组件

news2024/11/23 15:09:40

gl-dialog

大概思路:
在弹窗组件内部引入gl-dialog-collapse,这个组件主要用于存储已经被最小化的弹窗(基础数据)
弹窗内部的数据如何在父组件拿到是通过作用域插槽来实现的
gl-dialog接收一个tempData这个数据会在内部被记录下来,然后通过插槽的形式传递给父组件,供父组件使用
在这里插入图片描述

<template>
  <div class="gl-dialog" ref="dialogRef">
    <el-dialog
      :close-on-click-modal="false"
      v-bind="$attrs"
      :visible.sync="selfVisible"
      :show-close="false"
    >
      <div class="dialog-header" slot="title">
        <div class="left-title">{{ currentData.dialogTitle }}</div>
        <div class="right-icon">
          <i
            title="缩小"
            class="iconfont icon-segi-icon-minus"
            style="font-size: 14px"
            @click="toCollapse"
          ></i>
          <i
            title="关闭"
            class="iconfont icon-Close"
            style="font-size: 14px;font-weight: bold;"
            @click="closeDialog"
          ></i>
        </div>
      </div>
      <slot :tempData="currentData"></slot>
      <footer>
        <slot name="footer" :tempData="currentData" />
      </footer>
    </el-dialog>
    <gl-dialog-collapse :dialogList="dialogList"></gl-dialog-collapse>
  </div>
</template>

<script>
import _ from "lodash";
export default {
  name: "gl-dialog",
  props: {
    visible: {
      type: Boolean,
      default: () => false,
    },
    title: String,
    type: {
      type: String,
      default: () => "default",
    },
    tempData: Object,
  },
  data() {
    return {
      ddd: "okok",
      dialogList: [],
      currentData: {},
      count: 0,
      isExpand: false,
      // dialogId: "",
    };
  },
  computed: {
    dialogId() {
      return this.tempData.dialogTitle + this.count;
    },
    selfVisible: {
      get() {
        return this.visible;
      },
      set(value) {
        this.$emit("update:visible", value);
      },
    },
  },
  watch: {
    visible(N) {
      if (N) {
        if (!this.isExpand) {
          this.currentData = _.cloneDeep(this.tempData);
          this.currentData.dialogTitle = this.title;
          this.currentData.dialogId = this.dialogId;
        } else {
          this.count++;
        }
      }
    },
  },
  methods: {
    toCollapse() {
      const targetIndex = this.dialogList.findIndex((item) => {
        const { dialogId } = this.currentData;
        return dialogId == item.dialogId;
      });
      const isExist = targetIndex >= 0;
      if (!isExist) {
        this.dialogList.push({
          type: this.type,
          title: this.currentData.dialogTitle,
          dialogId: this.dialogId,
          tempData: this.currentData,
          expandCallBack: (tempData) => {
            this.isExpand = true;
            this.currentData = tempData;
            this.currentData.dialogId = tempData.dialogId;
            this.selfVisible = true;
          },
        });
        this.count++;
      }
      this.isExpand = false;
      this.selfVisible = false;
    },
    closeDialog() {
      this.isExpand = false;
      this.selfVisible = false;
      if (!this.dialogList.length) return;
      const targetIndex = this.dialogList.findIndex((item) => {
        const dialogId = this.isExpand
          ? this.currentData.dialogId
          : this.dialogId;
        return dialogId == item.dialogId;
      });
      if (targetIndex >= 0) {
        this.dialogList.splice(targetIndex, 1);
      }
    },
  },
};
</script>

<style lang="scss" scoped>
.dialog-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
}
// ::v-deep .dialog-footer {
//   text-align: right!important;
// }
.iconfont {
  cursor: pointer;
}
footer {
  text-align: right;
}
</style>

gl-dialog-collapse.vue

<template>
  <div class="gl-dialog-collapse">
    <div class="collapse-item" v-for="(item, index) in dialogList" :key="index">
      <div class="title">{{ item.title }}</div>
      <div class="right-icons">
        <i
          title="放大"
          class="iconfont icon-icf_full_screen_arrow"
          @click="toExpand(item)"
        ></i>
        <i title="关闭" class="iconfont icon-Close" @click="closeDialog"></i>
      </div>
    </div>
  </div>
</template>

<script>
export default {
  name: "gl-dialog-collapse",
  props: {
    dialogList: {
      type: Array,
      default: [],
    },
  },
  methods: {
    toExpand(item) {
      const { expandCallBack, tempData } = item;
      expandCallBack(tempData);
      this.closeDialog(item);
    },
    closeDialog(item) {
      const { dialogId } = item;
      const targetIndex = this.dialogList.findIndex(
        (item) => item.dialogId == dialogId
      );
      this.dialogList.splice(targetIndex, 1);
    },
  },
};
</script>

<style lang="scss" scoped>
.gl-dialog-collapse {
  display: flex;
  column-gap: 5px;
  position: fixed;
  left: 201px;
  bottom: 0px;
}
.collapse-item {
  padding: 5px 10px;
  display: flex;
  align-items: center;
  column-gap: 20px;
  border: 1px solid #ccc;
  background-color: #fff;
  .title {
    font-size: 14px;
  }
}
.right-icons {
  i {
    cursor: pointer;
    font-size: 16px;
  }
}
</style>

实现效果:
在这里插入图片描述
在这里插入图片描述
每个最小化的弹窗内部数据都是独立的,因为gl-dialog-collapse内部维护了一个已经被折叠的弹窗数组。
内部的数据结构:

{
          type: this.type,
          title: this.currentData.dialogTitle,
          dialogId: this.dialogId,
          tempData: this.currentData,
          expandCallBack: (tempData) => {
            this.isExpand = true;
            this.currentData = tempData;
            this.currentData.dialogId = tempData.dialogId;
            this.selfVisible = true;
          },
        }

dialogId用于记录唯一弹窗,方便回显数据,以及关闭目标弹窗

反思:当时考虑用cloneNode来实现弹窗的复制,但是考虑到vue里面是通过数据来驱动视图,能够成功复制弹窗,但是里面的交互会失效,所以感觉这种方案会很复杂,所以放弃。中途参考过layui弹窗最小化的实现方式,发现是对节点进行克隆,所以每最小化一个弹窗就会多产生一个节点。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1651933.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Gen-2颠覆AI生成视频!一句话秒出4K高清大片,网友:彻底改变游戏规则

这&#xff0c;绝对称得上是生成式AI进程中的里程碑。 就在深夜&#xff0c;Runway家标志性的AI视频生成工具Gen-2&#xff0c;迎来了“iPhone时刻”般的史诗级更新—— 依旧是简单一句话输入&#xff0c;不过这一次&#xff0c;视频效果一口气拉到了4K超逼真的高度&#xff…

WordPress原创插件:当日24小时发布文章标题变红

WordPress原创插件&#xff1a;当日24小时发布文章标题变红 <?php// 添加自定义样式 function title_red_plugin_styles() {$current_time time();$post_time get_the_time(U);$time_difference $current_time - $post_time;if ($time_difference < 86400) {echo&l…

【doghead】mac与wsl2联通

mbp 设置为发送端,那么要能与windows上 wsl2的ubutnu通信。 mbp的 uv 构建ok zhangbin@zhangbin-mbp-2  ~/tet/Fargo/zhb-bifrost/Bifrost-202403/worker/third_party/libuv   main clion使用lldb cmake构建 更新git2.45.0啊

无人机+垂直起降:微型共轴双旋翼无人机技术详解

微型共轴双旋翼无人机技术是一种独特的无人机设计&#xff0c;它结合了垂直起降&#xff08;VTOL&#xff09;能力和微型无人机的灵活性。这种设计允许无人机在无需跑道的情况下垂直起降&#xff0c;并具备在空中悬停和执行各种飞行动作的能力。 适用于集群控制&#xff0c;荷载…

SAP-ABAP-操作透明表06

1、操作透明表-查询 查询0条数据只做判断 SELECT COUNT(*) FROM ZHY_XYXX_01 WHERE ZBJ = 202404. IF SY-SUBRC = 0. WRITE 班级存在. ELSE. WRITE 班级不存在. ENDIF. 查询一条数据 *查询一条数据 SELECT SINGLE ZBJ, ZXH INTO @GS_Z…

【数据库原理及应用】期末复习汇总高校期末真题试卷07

试卷 一、填空题&#xff08;每空1分&#xff0c;共10分&#xff09; 1.数据库管理系统在外模式、模式和内模式这三级模式之间提供了两层映象&#xff0c;其中 映象保证了数据的逻辑独立性。 2. 数据模型通常由 、数据操作和完整性约束三部分组…

不盖CNAS的证书就是无效的?证书哪些信息是“非必要”?

做设备校准的企业&#xff0c;大多数都是为了拿到仪器校准证书&#xff0c;而说起校准证书&#xff0c;很多人优先就是想到CNAS&#xff0c;CNAS作为校准行业重要的核心资质&#xff0c;无论是校准机构实力的证明&#xff0c;还是满足企业年审的需要&#xff0c;基本上都是关键…

启动任何类型操作系统:不需要检索 ISO 文件 | 开源日报 No.243

netbootxyz/netboot.xyz Stars: 7.7k License: Apache-2.0 netboot.xyz 是一个方便的平台&#xff0c;可以不需要检索 ISO 文件就能启动任何类型操作系统或实用工具磁盘。它使用 iPXE 提供用户友好的 BIOS 菜单&#xff0c;让您轻松选择所需的操作系统以及特定版本或可引导标志…

羊大师:羊奶儿童骨骼发育的助力者

羊大师&#xff1a;羊奶儿童骨骼发育的助力者 羊奶&#xff0c;这一传统而珍贵的营养饮品&#xff0c;羊大师发现羊不仅是美味的象征&#xff0c;更是儿童骨骼发育的助力者。它以其独特的营养价值和易于吸收的特点&#xff0c;为孩子们的健康成长提供了坚实的支持。 儿童时期…

数据库、OS内核安全等精彩继续!龙蜥大讲堂 5 月直播预告来袭

「龙蜥大讲堂」5 月精彩预告来了&#xff0c;点击下方海报抢先了解。本月又是满满的技术干货分享&#xff0c;多位大咖带你共享技术盛宴&#xff01;直播地址&#xff1a;http://live.bilibili.com/24798267 5 月精彩分享直达 &#x1f447; 直播主题及内容介绍 一&#xff1…

vue项目基于WebRTC实现一对一音视频通话

效果 前端代码 <template><div class"flex items-center flex-col text-center p-12 h-screen"><div class"relative h-full mb-4 fBox"><video id"localVideo"></video><video id"remoteVideo">…

团队执行力差,多半都是管理的问题

在日常管理中&#xff0c;我们习惯用“执行力好不好”来评价一个团队的表现&#xff0c;但实际上&#xff0c;执行力更应该是一个管理者需要思考和解决的问题&#xff0c;而非单纯归咎于团队。 我们需要明确一点&#xff1a;执行力不是团队的问题&#xff0c;而是管理者的问题…

MySQL迁移data目录

MYSQL数据库有时候安装好了&#xff0c;想移动一下data目录&#xff0c;但是又不想重新安装一下&#xff0c;就只能想办法把这个目录迁移一下。 先找到my.ini配置文件&#xff0c;可以全局搜索一下&#xff0c; 找到之后&#xff0c;把这个地方修改一下&#xff0c;就把data目…

Linux中文乱码

背景介绍 通过unzip命令解压后中文命名的文件显示乱码 中文名称文件显示乱码 原因 这是因为Linux没有设置对中文的支持 解决办法 编辑~/.bashrc添加export LC_ALLC.UTF-8 使更改的配置生效 source ~/.bashrc查看系统字体编码格式 locale查看中文名称的文件显示是否正常…

落地护眼灯十大品牌哪款性价比高?品牌排行榜前十名全面揭晓!

落地护眼灯十大品牌哪款性价比高&#xff1f;落地护眼灯已经逐渐成为孩子日常使用率较高的电器之一&#xff0c;它的优点非常突出&#xff0c;对于学习、工作、绘画等环境都能够提供良好的健康环境&#xff0c;同时还携带多种智能调节功能&#xff0c;例如&#xff1a;入座感应…

基于大数据+Hadoop的豆瓣电子图书推荐系统实现

&#x1f339;作者主页&#xff1a;青花锁 &#x1f339;简介&#xff1a;Java领域优质创作者&#x1f3c6;、Java微服务架构公号作者&#x1f604; &#x1f339;简历模板、学习资料、面试题库、技术互助 &#x1f339;文末获取联系方式 &#x1f4dd; 系列文章目录 基于大数…

使用STM32CubeMX进行STM32F4的定时器配置

目录 1. Pin脚2. 配置2.1 时钟配置2.2 RCC配置2.3 Timer配置2.4 输出文件 3. 代码3.1 使能定时器3.2 回调函数 1. Pin脚 2. 配置 2.1 时钟配置 timer3时钟挂载在APB1上&#xff1a; 时钟配置如下&#xff1a; 外部使用8MHz晶振 开启内部16MHz晶振 使用锁相环 开启最高100MHz。…

【零基础】system generator①设置卡解析

1.在matlab中我们输入的是双精度浮点型数据&#xff0c;经过gateway后变成定点型。十六位十四个小数位&#xff0c;整个数据有十六位&#xff0c;其中十四位给了小数 2.fixed-point定点型&#xff1b;signed有符号&#xff1b;2’s comp补码 3.量化误差 truncate&#xff0c;舍…

图像涂哪就动哪!Gen-2新功能“神笔马良”爆火,网友:急急急

AI搞视频生成&#xff0c;已经进化到这个程度了&#xff1f;&#xff01; 对着一张照片随手一刷&#xff0c;就能让被选中的目标动起来&#xff01; 明明是一辆静止的卡车&#xff0c;一刷就跑了起来&#xff0c;连光影都完美还原&#xff1a; 原本只是一张火灾照片&#xff0…

一个账号玩遍ChatGPT/Claude-3/Midjourney 省钱又省力

当 OpenAI 的闭源 GPT-4 和 Meta 的开源 LLaMA 3 70B 模型在 Chatbot Arena Elo Score、MMLU 和 MT Benchmark 测试中表现出相当的性能时&#xff0c;选择更昂贵的专有模型&#xff08;其成本高出 58 倍&#xff09;的论据是&#xff1a; NVIDIA GPU Inference 上的运行速度比 …