下面我将详细讲解用vue3封装一个符合思维且简单实用的弹出层的完整攻略。
1. 弹出层的需求分析
在封装弹出层之前,我们需要对需求进行分析,明确所需功能、交互,进而确定实现方式和技术选型。
弹出层的主要需求包括:弹出层中展示数据、支持输入、支持自定义样式、支持关闭、支持拖拽等。
在交互方面,我们需要考虑以下几个问题:
- 如何打开/关闭弹出层?
- 如何传递数据给弹出层?
- 如何获取弹出层中的输入数据?
- 如何实现弹出层的拖拽效果?
2. 弹出层的封装实现
在分析完弹出层的需求和交互后,我们开始进行代码实现。
2.1 实现步骤
- 创建一个
Popup
组件,该组件将作为弹出层的整体结构,包括遮罩层、弹出框、标题、内容等。 - 将
Popup
组件添加到主组件中,通过v-if
控制显示或隐藏。 - 在
Popup
组件中添加slot
插槽,用于插入需要展示的内容。 - 实现拖拽效果。
- 在
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技术站