vue实战:三分钟实现优雅弹框 [ 项目级组件封装 ][ 超详细 ]
本篇文章将封装一个优雅的项目级通用弹出框。该弹出框实现重用的同时,将内容与表现分离,让使用者可以专注于绘制弹框内容,而不用在意弹框的具体实现。文章阅读预计15分钟。
本篇文章将封装一个优雅的项目级通用弹出框。
该弹出框实现重用的同时,将内容与表现分离,让使用者可以专注于绘制弹框内容,而不用在意弹框的具体实现。
文章阅读预计15分钟。
成果预览:
一 父组件准备
我们创建文件modelTest.vue,将其引入父组件并注册。
// 父组件
<template>
<div class="home">
<button @click="modelVisit">弹框展示</button>
<model-test v-if="modelData.isVisit"></model-test>
</div>
</template>
<script>
import modelTest from './modelTest';
export default {
components: {
modelTest
},
data(){
return {
modelData: {
isVisit: false
}
}
},
methods: {
modelVisit(){
this.modelData.isVisit = true;
}
}
}
</script>
可以看到父组件中定义了标志变量modelData.isVisit,控制弹框的展示。
当点击按钮时展示弹框组件。
二 实现弹框组件
2.1 需求分析
首先我们分析该组件中的内容,组件总体包括两部分, 遮罩和弹出框。
弹出框内容可划分为三部分,header,center,footer。
点击遮罩部分关闭弹框(组件隐藏)。
2.2 遮罩部分实现
2.2.1 绘制页面
遮罩部分在所有组件的前面,使用样式z-index=199实现。
遮罩部分占据整个视口。
// modelTest.vue
<template>
<div class="modelTest">
<div class="sidebox-backdrop"></div>
</div>
</template>
<style scoped>
.modelTest .sidebox-backdrop{
position: fixed;
top: 0;
bottom: 0;
left: 0;
right: 0;
z-index: 199;
background-color: rgb(31 33 38 / 25%);
}
</style>
现在点击按钮,就可以看到弹出的遮罩覆盖整个视口。
2.2.2 添加点击事件
接下来为遮罩添加点击事件。
在遮罩点击事件中,我们希望改变父组件变量的值。
update是子组件改变父组件变量时使用的语法糖。
// 用法示例 下面的代码在子组件中将变量valc付给了父组件变量bar
<comp :myMessage.sync="bar"></comp> //父
this.$emit('update:myMessage',valc); // 子
在这里我们也是同样的用法。改变组件代码如下。
子组件:
<div class="sidebox-backdrop" @click="handleClose"></div>
methods: {
handleClose(){
this.$emit('update:isVisit', false)
}
}
父组件:
<model-test v-if="modelData.isVisit" :isVisit.sync="modelData.isVisit">
2.3 弹框部分实现
2.3.1页面绘制
弹框分为三部分 头 中 脚,为达到组件的通用性,我们将头和脚的样式固定,内容采用动态插槽的格式。
<template>
<div class="modelTest">
<div class="sidebox-backdrop" @click="handleClose"></div>
<div class="sidebox-content" >
<div class="header">
header
</div>
<div class="center" :style="contentStyle">
<slot name="center" />
</div>
<div class="footer">
<slot name="footer" />
</div>
</div>
</div>
</template>
弹框中header未放置插槽,因为header一般比较简单,做一个传入内容的展示即可。
2.3.2 样式添加
我们做一个位置在左侧的抽屉式弹框。
我们为弹框整体类添加样式。
弹框元素在遮罩元素的前面,使用样式z-index=200实现。
我们使用绝对定位将弹框元素相对于视口拉伸。
.modelTest .sidebox-content{
z-index: 200;
position: fixed;
left: 0;
top: 0px;
background-color: white;
}
可以看到这里没有定义弹框的宽度和高度,这是为灵活性考虑,将其以变量形势定义,方便后期从父组件传入。
<div class="sidebox-content" :style="contentStyle">
data(){
return {
width: '550px',
height: '100%'
}
},
computed: {
contentStyle(){
return {
width: this.width,
height: this.height
}
}
}
这样我们得到一个抽屉式弹框,接下来为弹框内部元素定义样式。
.modelTest .sidebox-content .header, .modelTest .sidebox-content .footer{
width: 100%;
height: 30px;
line-height: 30px;
}
.modelTest .sidebox-content .center{
height: calc(100% - 60px);
}
弹框组件基本上完成了,接下来我们看看如何使用。
三 使用组件
刚刚我们已经在父组件中引入了弹框组件,并且设置了点击按钮展示弹框,点击遮罩关闭弹框,在弹框中我们使用了两个插槽center和footer,在父组件中需要给出。
<model-test v-if="modelData.isVisit" :isVisit.sync="modelData.isVisit">
<template slot="center">
<div>center</div>
</template>
<template slot="footer">
<div>footer</div>
</template>
</model-test>
在实际项目中,我们可以将两个插槽封装为组件,在template中使用子组件即可。
<model-test v-if="modelData.isVisit" :isVisit.sync="modelData.isVisit">
<template slot="center">
<center/>
</template>
<template slot="footer">
<footer/>
</template>
</model-test>
在子组件中我们可以完成和修改复杂的逻辑页面,而不用在意弹框的实现。
点击按钮,弹框已经成功展示了。
在header center footer组件上做添加即可。
示例图片:
更多推荐
所有评论(0)