用vue3封装一个符合思维且简单实用的弹出层

下面我将详细讲解用vue3封装一个符合思维且简单实用的弹出层的完整攻略。

1. 弹出层的需求分析

在封装弹出层之前,我们需要对需求进行分析,明确所需功能、交互,进而确定实现方式和技术选型。

弹出层的主要需求包括:弹出层中展示数据、支持输入、支持自定义样式、支持关闭、支持拖拽等。

在交互方面,我们需要考虑以下几个问题:

  1. 如何打开/关闭弹出层?
  2. 如何传递数据给弹出层?
  3. 如何获取弹出层中的输入数据?
  4. 如何实现弹出层的拖拽效果?

2. 弹出层的封装实现

在分析完弹出层的需求和交互后,我们开始进行代码实现。

2.1 实现步骤

  1. 创建一个Popup组件,该组件将作为弹出层的整体结构,包括遮罩层、弹出框、标题、内容等。
  2. Popup组件添加到主组件中,通过v-if控制显示或隐藏。
  3. Popup组件中添加slot插槽,用于插入需要展示的内容。
  4. 实现拖拽效果。
  5. Popup组件中添加事件控制,包括关闭事件和确认事件。

2.2 代码实现

<!-- Popup.vue -->

<template>
  <div class="popup-wrapper" v-show="visible">
    <div class="popup-mask" @click="close"></div>
    <div class="popup-container">
      <div class="popup-title">{{title}}</div>
      <div class="popup-content">
        <slot></slot>
      </div>
      <div class="popup-footer">
        <button class="popup-btn popup-cancel" @click="close">取消</button>
        <button class="popup-btn popup-confirm" @click="confirm">确定</button>
      </div>
    </div>
  </div>
</template>

<script>
export default {
  name: 'Popup',
  props: {
    title: String,
    visible: Boolean,
    draggable: {
      type: Boolean,
      default: true
    }
  },
  data() {
    return {
      startX: 0,
      startY: 0,
      posX: 0,
      posY: 0
    }
  },
  computed: {
    transform() {
      return `translate3d(${this.posX}px, ${this.posY}px, 0)`
    }
  },
  mounted() {
    if (this.draggable) {
      const header = this.$el.querySelector('.popup-title')
      header.style.cursor = 'move'
      header.addEventListener('mousedown', this.startDrag)
    }
  },
  beforeUnmount() {
    if (this.draggable) {
      const header = this.$el.querySelector('.popup-title')
      header.removeEventListener('mousedown', this.startDrag)
    }
  },
  methods: {
    startDrag(event) {
      this.startX = event.clientX
      this.startY = event.clientY
      this.posX = this.$el.offsetLeft
      this.posY = this.$el.offsetTop
      document.addEventListener('mousemove', this.drag)
      document.addEventListener('mouseup', this.stopDrag)
    },
    drag(event) {
      const deltaX = event.clientX - this.startX
      const deltaY = event.clientY - this.startY
      this.posX += deltaX
      this.posY += deltaY
      this.startX = event.clientX
      this.startY = event.clientY
    },
    stopDrag() {
      document.removeEventListener('mousemove', this.drag)
      document.removeEventListener('mouseup', this.stopDrag)
    },
    close() {
      this.$emit('update:visible', false)
    },
    confirm() {
      this.$emit('confirm')
      this.close()
    }
  }
}
</script>

<style scoped>
.popup-wrapper {
  position: fixed;
  z-index: 9999;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  display: flex;
  justify-content: center;
  align-items: center;
}

.popup-mask {
  position: absolute;
  z-index: -1;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background: rgba(0, 0, 0, .5);
}

.popup-container {
  position: relative;
  width: 400px;
  max-height: 600px;
  border-radius: 6px;
  background-color: #fff;
  box-shadow: 0 2px 10px rgba(0, 0, 0, .1);
  overflow: auto;
  transition: transform .3s ease-out;
  transform: translateY(-50%);
}

.popup-title {
  padding: 12px 16px;
  font-size: 16px;
  font-weight: bold;
  text-align: center;
}

.popup-content {
  padding: 16px;
}

.popup-footer {
  display: flex;
  justify-content: center;
  align-items: center;
  margin: 16px 0;
}

.popup-btn {
  padding: 8px 16px;
  border: none;
  border-radius: 6px;
  font-size: 14px;
  font-weight: bold;
  cursor: pointer;
  outline: none;
}

.popup-confirm {
  color: #fff;
  background-color: #42b983;
  margin-left: 16px;
}

.popup-cancel:hover,
.popup-confirm:hover {
  opacity: .8;
}

.popup-title {
  -webkit-user-select: none;
  -moz-user-select: none;
  -ms-user-select: none;
  user-select: none;
}

.popup-title:active {
  cursor: move;
}
</style>

在主组件中使用Popup组件:

<template>
  <div>
    <!-- 弹出层触发按钮 -->
    <button @click="visible = true">打开弹出层</button>
    <!-- 弹出层 -->
    <Popup
      :visible.sync="visible"
      title="弹出层标题"
      @confirm="confirmHandler"
    >
      <p>这里是弹出层内容</p>
    </Popup>
  </div>
</template>

<script>
import Popup from './components/Popup.vue'

export default {
  name: 'App',
  components: { Popup },
  data() {
    return {
      visible: false
    }
  },
  methods: {
    confirmHandler() {
      console.log('点击了确认')
    }
  }
}
</script>

3. 示例说明

下面给出2个示例,以更好地说明Popup组件的用法。

3.1 示例一:弹出层展示表单

利用Popup组件展示一个表单,包括姓名、年龄、性别等字段:

<template>
  <div>
    <!-- 弹出层触发按钮 -->
    <button @click="visible = true">打开弹出层</button>
    <!-- 弹出层 -->
    <Popup
      :visible.sync="visible"
      title="填写信息"
      @confirm="confirmHandler"
    >
      <form>
        <div class="form-group">
          <label for="name">姓名</label>
          <input id="name" type="text" v-model="formData.name" />
        </div>
        <div class="form-group">
          <label for="age">年龄</label>
          <input id="age" type="number" v-model.number="formData.age" />
        </div>
        <div class="form-group">
          <label for="gender">性别</label>
          <select id="gender" v-model="formData.gender">
            <option value="">请选择</option>
            <option value="male">男</option>
            <option value="female">女</option>
          </select>
        </div>
        <button type="submit">提交</button>
      </form>
    </Popup>
  </div>
</template>

<script>
import Popup from './components/Popup.vue'

export default {
  name: 'App',
  components: { Popup },
  data() {
    return {
      visible: false,
      formData: {
        name: '',
        age: 0,
        gender: ''
      }
    }
  },
  methods: {
    confirmHandler() {
      console.log('表单提交', this.formData)
    }
  }
}
</script>

3.2 示例二:弹出层展示自定义内容

利用Popup组件展示一张图片,支持拖拽:

<template>
  <div>
    <!-- 弹出层触发按钮 -->
    <button @click="visible = true">打开弹出层</button>
    <!-- 弹出层 -->
    <Popup
      :visible.sync="visible"
      title="图片预览"
      @confirm="confirmHandler"
    >
      <img
        src="https://picsum.photos/600/400"
        alt="图片"
        @mousedown.stop.prevent="startDrag"
        :style="{ transform }"
      />
    </Popup>
  </div>
</template>

<script>
import Popup from './components/Popup.vue'

export default {
  name: 'App',
  components: { Popup },
  data() {
    return {
      visible: false,
      startX: 0,
      startY: 0,
      posX: 0,
      posY: 0
    }
  },
  computed: {
    transform() {
      return `translate3d(${this.posX}px, ${this.posY}px, 0)`
    }
  },
  methods: {
    startDrag(event) {
      this.startX = event.clientX
      this.startY = event.clientY
      this.posX = event.target.offsetLeft
      this.posY = event.target.offsetTop
      document.addEventListener('mousemove', this.drag)
      document.addEventListener('mouseup', this.stopDrag)
    },
    drag(event) {
      const deltaX = event.clientX - this.startX
      const deltaY = event.clientY - this.startY
      this.posX += deltaX
      this.posY += deltaY
      this.startX = event.clientX
      this.startY = event.clientY
    },
    stopDrag() {
      document.removeEventListener('mousemove', this.drag)
      document.removeEventListener('mouseup', this.stopDrag)
    },
    confirmHandler() {
      console.log('关闭弹出层')
    }
  }
}
</script>

以上是用vue3封装一个符合思维且简单实用的弹出层的完整攻略,希望对您有所帮助。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:用vue3封装一个符合思维且简单实用的弹出层 - Python技术站

(0)
上一篇 2023年6月25日
下一篇 2023年6月25日

相关文章

  • 浅析Java中局部变量与成员变量同名解决技巧

    浅析Java中局部变量与成员变量同名解决技巧 在Java中,当局部变量与成员变量同名时,可能会导致代码逻辑错误或者产生不可预料的结果。为了解决这个问题,我们可以采用以下两种技巧: 1. 使用this关键字 在Java中,this关键字表示当前对象的引用。通过使用this关键字,我们可以明确地指定成员变量。 示例代码如下: public class Examp…

    other 2023年8月8日
    00
  • mysql 5.7.14 安装配置方法图文教程

    以下是关于“mysql 5.7.14 安装配置方法图文教程”的详细攻略: 一、安装前准备 1. 操作系统要求 mysql 5.7.14 支持的操作系统版本有:- Red Hat Enterprise Linux / Oracle Linux 5.x/6.x/7.x- SUSE Linux Enterprise Server 11 SP2/SP3/SP4; 1…

    other 2023年6月20日
    00
  • 判断数据库web是否分离的技巧

    判断数据库Web是否分离的技巧有以下几个方面: 查看数据库连接字符串 首先,判断Web是否连接了数据库,可以查看Web应用程序的连接字符串。该连接字符串通常存储在Web.config或app.config文件中,表示应用程序与数据库之间的通信方式。如果连接字符串中包含IP地址或域名,则表明Web应用程序连接了外部数据库。如果连接字符串中使用的是localho…

    other 2023年6月27日
    00
  • Java 单链表数据结构的增删改查教程

    Java 单链表数据结构的增删改查教程 什么是单链表 单链表是一种常用的线性表,是链式存储结构,由多个结点组成,每个结点包含数据域和指针域,指针域指向下一个结点。单链表的优势在于可以在任意位置进行元素的插入和删除操作,但是在查询某个元素时,需要从头结点依次遍历,效率较低。 节点 单链表中的每一个元素称为节点,使用Java类进行表示 class Node { …

    other 2023年6月27日
    00
  • MySQL约束(创建表时的各种条件说明)

    MySQL约束是用于保证数据完整性和一致性的重要措施之一,创建表时可以通过添加约束来定义表中的一些条件限制,以下是MySQL约束的详细说明: 1. NOT NULL约束 NOT NULL约束用于保证该列的值不能为空,这是一个非常常见的约束。 语法: column_name data_type NOT NULL 示例: CREATE TABLE student…

    other 2023年6月25日
    00
  • Win7电脑开机速度慢解决方法

    Win7电脑开机速度慢解决方法攻略 如果你的Win7电脑开机速度变慢了,不用担心,下面是一些解决方法,帮助你提高开机速度。 1. 清理启动项 启动项是在系统启动时自动运行的程序或服务。过多的启动项会拖慢开机速度。以下是清理启动项的步骤: 打开任务管理器:按下Ctrl + Shift + Esc组合键,或者右键点击任务栏并选择“任务管理器”。 切换到“启动”选…

    other 2023年8月1日
    00
  • Echart绘制趋势图和柱状图总结

    Echart绘制趋势图和柱状图总结 Echart是一款非常流行的开源JavaScript图形库,它可以轻松地绘制各种类型的图表,包括趋势图和柱状图。在本文中,我们将总结如何使用Echart绘制这两种类型的图表。 绘制趋势图 趋势图在数据可视化中非常常见,它可以帮助我们更好地理解趋势变化。Echart提供了一种名为“折线图”的类型,可以用来绘制趋势图。 以下是…

    其他 2023年3月28日
    00
  • springboot的jar能独立运行的原因解析

    当我们使用Spring Boot框架来构建Java Web应用时,可以生成一个可执行的Jar文件,这个Jar文件一般都可以独立运行。那么为什么Spring Boot的Jar文件可以独立运行呢?下面是详细解析。 Spring Boot应用的依赖管理 Spring Boot提供了一种依赖管理的方式,即在pom.xml文件中使用<parent>元素引入…

    other 2023年6月27日
    00
合作推广
合作推广
分享本页
返回顶部