使⽤Vue组件实现⼀个简单弹窗效果
最近在使⽤element-ui框架,⽤到了Dialog对话框组件,⼤致实现的效果,跟我之前⾃⼰在移动端项⽬⾥⾯弄的⼀个弹窗组件差不太多。然后就想着把这种弹窗组件的实现⽅式与⼤家分享⼀下,下⾯本⽂会带着⼤家⼿摸⼿实现⼀个弹窗组件。
本⽂主要内容会涉及到弹窗遮罩的实现, slot 插槽的使⽤⽅式, props 、 $emit 传参,具体组件代码也传上去了。如果喜欢的话可以点波赞/关注,⽀持⼀下,希望⼤家看完本⽂可以有所收获。
组件最后实现的效果
实现步骤
1. 先搭建组件的html和css样式,遮罩层和内容层。
2. 定制弹窗内容:弹窗组件通过 slot 插槽接受从⽗组件那⾥传过来弹窗内容。
3. 定制弹窗样式:弹窗组件通过 props 接收从⽗组件传过来的弹窗宽度,上下左右的位置。
4. 组件开关:通过⽗组件传进来的 props 控制组件的显⽰与隐藏,⼦组件关闭时通过事件 $emit 触发⽗组件改变值。
1.搭建组件的html和css样式。
html结构:⼀层遮罩层,⼀层内容层,内容层⾥⾯⼜有⼀个头部title和主体内容和⼀个关闭按钮。
下⾯是组件中的html结构,⾥⾯有⼀些后⾯才要加进去的东西,如果看不懂的话可以先跳过,
<template>
<div class="dialog">
<!--外层的遮罩点击事件⽤来关闭弹窗,isShow控制弹窗显⽰隐藏的props-->
<div class="dialog-cover back" v-if="isShow" @click="closeMyself"></div>
<!-- transition 这⾥可以加⼀些简单的动画效果 -->
<transition name="drop">
<!--style 通过props 控制内容的样式 -->
<div class="dialog-content" : v-if="isShow">
<div class="dialog_head back">
<!--弹窗头部 title-->
<slot name="header">提⽰信息</slot>
</div>
<div class="dialog_main" :>
<!--弹窗的内容-->
<slot name="main">弹窗内容</slot>
</div>
<!--弹窗关闭按钮-->
<div class="foot_close" @click="closeMyself">
<div class="close_img back"></div>
</div>
</div>
</transition>
</div>
</template>
下⾯是组件中的主要的css样式,⾥⾯都做了充分的注释,主要通过 z-index 和 background 达到遮罩的效果,具体内容的css 可以根据⾃⼰的需求来设置。
<style lang="scss" scoped>
// 最外层设置position定位
.dialog {
position: relative;
color: #2e2c2d;
font-size: 16px;
}
// 遮罩设置背景层,z-index值要⾜够⼤确保能覆盖,⾼度宽度设置满做到全屏遮罩
.dialog-cover {
background: rgba(0,0,0, 0.8);
position: fixed;
z-index: 200;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
// 内容层 z-index要⽐遮罩⼤,否则会被遮盖,
.dialog-content{
position: fixed;
top: 35%;
// 移动端使⽤felx布局
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
z-index: 300;
}
</style>
2. 通过 slot 定制弹窗内容
这⼀步,只要理解了 slot 的作⽤以及⽤法,就没有问题了。
单个插槽:
<slot>这是在没有slot传进来的时候,才显⽰的弹窗内容</slot>
上⾯是单个插槽也叫默认插槽,在⽗组件中使⽤插槽的正确姿势:
<my-component>
<!--在my-component⾥⾯的所有内容⽚段都将插⼊到slot所在的DOM位置,并且会替换掉slot标签-->
<!--这两个p标签,将替换整个slot标签⾥⾯的内容-->
<p>这是⼀些初始内容</p>
<p>这是更多的初始内容</p>
</my-component>
ps:如果⼦组件⾥⾯包含 slot 插槽,那么上⾯的p标签的内容将会被丢弃。
具名插槽:
所谓的具名插槽,即为 slot 标签赋⼀个 name 属性,具名插槽可以⽗组件中不同的内容⽚段放到⼦组件的不同地⽅,具名插槽还是可以拥有⼀个默认插槽。下⾯可以看⼀下弹窗组件插槽的使⽤⽅式:
<div class="dialog_head back ">
<!--弹窗头部 title-->
<slot name="header">提⽰信息</slot>
</div>
<div class="dialog_main " :>
<!--弹窗的内容-->
<slot name="main">弹窗内容</slot>
</div>
在⽗组件中的使⽤⽅式:
将弹窗组件引⼊要使⽤的组件中,并通过 components 注册成为组件。
⽗组件中弹窗组件插槽的使⽤⽅法如下。
<dialogComponent>
<div slot="header">插⼊到name为header的slot标签⾥⾯</div>
<div class="dialog_publish_main" slot="main">
这⾥是内容插⼊到⼦组件的slot的name为main⾥⾯,可以在⽗组件中添加class定义样式,事件类型等各种操作
</div>
</dialogComponent>
关于组件中⽤到的插槽的介绍就到这⾥了,插槽在弹窗组件中的应⽤是⼀个典型的栗⼦,可以看到插槽作⽤相当强⼤,⽽插槽本⾝的使⽤并不难,同学们爱上插槽了没有?
3.通过 props 控制弹窗显隐&&定制弹窗style
psops 是Vue中⽗组件向⼦组件传递数据的⼀种⽅式,不熟悉的⼩伙伴们可以看⼀下 props⽂档。
因为弹窗组件都是引到别的组件⾥⾯去⽤的,为了适合不同组件场景中的弹窗,所以弹窗组件必须具备⼀定的可定制性,否则这样的组件将毫⽆意义,下⾯介绍⼀下props的使⽤⽅式,以弹窗组件为例:
⾸先需要在被传⼊的组件中定义props的⼀些特性,验证之类的。
然后在⽗组件中绑定props数据。
<script>
export default {
props: {
isShow: {
//弹窗组件是否显⽰默认不显⽰
type: Boolean,
default: false,
required:true, //必须
},
//下⾯这些属性会绑定到div上⾯详情参照上⾯的html结构
// 如: :
widNum:{
//内容宽度
type: Number,
自动弹窗代码default:86.5
},
leftSite:{
// 左定位
type: Number,
default:6.5
},
topDistance: {
//top上边距
type: Number,
default:35
},
pdt:{
//上padding
type: Number,
default:22
},
pdb:{
//下padding
type: Number,
default:47
}
},
}
</script>
⽗组件中使⽤⽅式:
<dialogComponent :is-show="status.isShowPublish" :top-distance="pNum">
</dialogComponent>
ps:props传递数据不是双向绑定的,⽽是单向数据流,⽗组件的数据变化时,也会传递到⼦组件中,这就意外着我们不应该在⼦组件中修改props。所以我们在关闭弹窗的时候就需要通过 $emit 来修改⽗组件的数据,然后数据会⾃动传到⼦组件中。
现在基本上弹窗组件都已实现的差不多了,还差⼀个弹窗的关闭事件,这⾥就涉及到⼦组件往⽗组件传参了。
4. $emit 触发⽗组件事件修改数据,关闭弹窗
Vue中在⼦组件往⽗组件传参,很多都是通过 $emit 来触发⽗组件的事件来修改数据。
在⼦组件中,在点击关闭,或者遮罩层的时候触发下⾯这个⽅法:
methods: {
closeMyself() {
this.$emit("on-close");
//如果需要传参的话,可以在"on-close"后⾯再加参数,然后在⽗组件的函数⾥接收就可以了。
}
}
⽗组件中的写法:
<dialogComponent :is-show="status.isShowPublish" :top-distance="pNum" @on-close="closeDialog">
</dialogComponent>
//"on-close是监听⼦组件的时间有没有触发,触发的时候执⾏closeDialog函数
methods:{
closeDialog(){
// this.status.isShowPublish=false;
//把绑定的弹窗数组设为false即可关闭弹窗
},
}
可以⽤弹窗组件实现下列这种信息展⽰,或者事件交互:
上⾯是把弹窗的每个步骤拆分开来,⼀步步解析的,每⼀步都说的⽐较清楚了,具体连起来的话,可以看看代码,再结合⽂章就能理的很清楚了。
总结
以上所述是⼩编给⼤家介绍的使⽤Vue组件实现⼀个简单弹窗效果,希望对⼤家有所帮助,如果⼤家有任何疑问请给我留⾔,⼩编会及时回复⼤家的。在此也⾮常感谢⼤家对⽹站的⽀持!
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论