关于vue.js弹窗组件的知识点总结
首先在开发时需要考虑以下三点:
1、进入和弹出的动画效果。
2、z-index的控制
3、overlay遮盖层
关于动画
vue对于动画的处理相对简单,给组件加入csstransition动画即可
<template>
<divclass="modal"transition="modal-scale">
<!--省略其它内容-->
</div>
</template>
<script>
//...
</script>
<style>
.modal-scale-transition{
transition:transform,opacity.3sease;
}
.modal-scale-enter,
.modal-scale-leave{
opacity:0;
}
.modal-scale-enter{
transform:scale(1.1);
}
.modal-scale-leave{
transform:scale(0.8);
}
</style>
外部可以由使用者自行控制,使用v-if或是v-show控制显示
z-index的控制
关于z-index的控制,需要完成以下几点
1、保证弹出框的z-index足够高能使其再最外层
2、后弹出的弹出框的z-index要比之前弹出的要高
要满足以上两点,我们需要以下代码实现
constzIndex=20141223//先预设较高值
constgetZIndex=function(){
returnzIndex++//每次获取之后zindex自动增加
}
然后绑定把z-index在组件上
<template>
<divclass="modal":style="{'z-index':zIndex}"transition="modal-scale">
<!--省略其它内容-->
</div>
</template>
<script>
exportdefault{
data(){
return{
zIndex:getZIndex()
}
}
}
</script>
overlay遮盖层的控制
遮盖层是弹窗组件中最难处理的部分,一个完美的遮盖层的控制需要完成以下几点:
1、遮盖层和弹出层之间的动画需要并行
2、遮盖层的z-index要较小与弹出层
3、遮盖层的弹出时需要组件页面滚动
4、点击遮盖层需要给予弹出层反馈
5、保证整个页面最多只能有一个遮盖层(多个叠在一起会使遮盖层颜色加深)
为了处理这些问题,也保证所有的弹出框组件不用每一个都解决,所以决定利用vue的mixins机制,将这些弹出层的公共逻辑封装层一个mixin,每个弹出框组件直接引用就好。
vue-popup-mixin
明确了上述所有的问题,开始开发mixin,首先需要一个overlay(遮盖层组件);
<template>
<divclass="overlay"@click="handlerClick"@touchmove="prevent":style="style"transition="overlay-fade"></div>
</template>
<script>
exportdefault{
props:{
onClick:{
type:Function
},
opacity:{
type:Number,
default:0.4
},
color:{
type:String,
default:'#000'
}
},
computed:{
style(){
return{
'opacity':this.opacity,
'background-color':this.color
}
}
},
methods:{
prevent(event){
event.preventDefault()
event.stopPropagation()
},
handlerClick(){
if(this.onClick){
this.onClick()
}
}
}
}
</script>
<stylelang="less">
.overlay{
position:fixed;
left:0;
right:0;
top:0;
bottom:0;
background-color:#000;
opacity:.4;
z-index:1000;
}
.overlay-fade-transition{
transition:all.3slinear;
&.overlay-fade-enter,
&.overlay-fade-leave{
opacity:0!important;
}
}
</style>
然后需要一个js来管理overlay的显示和隐藏。
importVuefrom'vue'
importoverlayOptfrom'../overlay'//引入overlay组件
constOverlay=Vue.extend(overlayOpt)
constgetDOM=function(dom){
if(dom.nodeType===3){
dom=dom.nextElementSibling||dom.nextSibling
getDOM(dom)
}
returndom
}
//z-index控制
constzIndex=20141223
constgetZIndex=function(){
returnzIndex++
}
//管理
constPopupManager={
instances:[],//用来储存所有的弹出层实例
overlay:false,
//弹窗框打开时调用此方法
open(instance){
if(!instance||this.instances.indexOf(instance)!==-1)return
//当没有遮盖层时,显示遮盖层
if(this.instances.length===0){
this.showOverlay(instance.overlayColor,instance.overlayOpacity)
}
this.instances.push(instance)//储存打开的弹出框组件
this.changeOverlayStyle()//控制不同弹出层透明度和颜色
//给弹出层加上z-index
constdom=getDOM(instance.$el)
dom.style.zIndex=getZIndex()
},
//弹出框关闭方法
close(instance){
letindex=this.instances.indexOf(instance)
if(index===-1)return
Vue.nextTick(()=>{
this.instances.splice(index,1)
//当页面上没有弹出层了就关闭遮盖层
if(this.instances.length===0){
this.closeOverlay()
}
this.changeOverlayStyle()
})
},
showOverlay(color,opacity){
letoverlay=this.overlay=newOverlay({
el:document.createElement('div')
})
constdom=getDOM(overlay.$el)
dom.style.zIndex=getZIndex()
overlay.color=color
overlay.opacity=opacity
overlay.onClick=this.handlerOverlayClick.bind(this)
overlay.$appendTo(document.body)
//禁止页面滚动
this.bodyOverflow=document.body.style.overflow
document.body.style.overflow='hidden'
},
closeOverlay(){
if(!this.overlay)return
document.body.style.overflow=this.bodyOverflow
letoverlay=this.overlay
this.overlay=null
overlay.$remove(()=>{
overlay.$destroy()
})
},
changeOverlayStyle(){
if(!this.overlay||this.instances.length===0)return
constinstance=this.instances[this.instances.length-1]
this.overlay.color=instance.overlayColor
this.overlay.opacity=instance.overlayOpacity
},
//遮盖层点击处理,会自动调用弹出层的overlayClick方法
handlerOverlayClick(){
if(this.instances.length===0)return
constinstance=this.instances[this.instances.length-1]
if(instance.overlayClick){
instance.overlayClick()
}
}
}
window.addEventListener('keydown',function(event){
if(event.keyCode===27){//ESC
if(PopupManager.instances.length>0){
consttopInstance=PopupManager.instances[PopupManager.instances.length-1]
if(!topInstance)return
if(topInstance.escPress){
topInstance.escPress()
}
}
}
})
exportdefaultPopupManager
最后再封装成一个mixin
importPopupManagerfrom'./popup-manager'
exportdefault{
props:{
show:{
type:Boolean,
default:false
},
//是否显示遮盖层
overlay:{
type:Boolean,
default:true
},
overlayOpacity:{
type:Number,
default:0.4
},
overlayColor:{
type:String,
default:'#000'
}
},
//组件被挂载时会判断show的值开控制打开
attached(){
if(this.show&&this.overlay){
PopupManager.open(this)
}
},
//组件被移除时关闭
detached(){
PopupManager.close(this)
},
watch:{
show(val){
//修改show值是调用对于的打开关闭方法
if(val&&this.overlay){
PopupManager.open(this)
}else{
PopupManager.close(this)
}
}
},
beforeDestroy(){
PopupManager.close(this)
}
}
使用
以上所有的代码就完成了所有弹出层的共有逻辑,使用时只需要当做一个mixin来加载即可
<template>
<divclass="dialog"
v-show="show"
transition="dialog-fade">
<divclass="dialog-content">
<slot></slot>
</div>
</div>
</template>
<style>
.dialog{
left:50%;
top:50%;
transform:translate(-50%,-50%);
position:fixed;
width:90%;
}
.dialog-content{
background:#fff;
border-radius:8px;
padding:20px;
text-align:center;
}
.dialog-fade-transition{
transition:opacity.3slinear;
}
.dialog-fade-enter,
.dialog-fade-leave{
opacity:0;
}
</style>
<script>
importPopupfrom'../src'
exportdefault{
mixins:[Popup],
methods:{
//响应overlay事件
overlayClick(){
this.show=false
},
//响应esc按键事件
escPress(){
this.show=false
}
}
}
</script>
总结
以上就是关于vue.js弹窗组件的一些知识点,希望对大家的学习或者工作带来一定的帮助,如果大家有疑问可以留言交流,谢谢大家对毛票票的支持。