关于vue.js弹窗组件的知识点总结


Posted in Javascript onSeptember 11, 2016

首先在开发时需要考虑以下三点:

     1、进入和弹出的动画效果。

     2、z-index 的控制

     3、overlay 遮盖层

关于动画

vue 对于动画的处理相对简单,给组件加入css transition 动画即可

<template>
<div class="modal" transition="modal-scale">
 <!--省略其它内容-->
</div>
</template>
<script>
// ...
</script>
<style>
.modal-scale-transition{
 transition: transform,opacity .3s ease;
}

.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 要比之前弹出的要高

要满足以上两点, 我们需要以下代码实现

const zIndex = 20141223 // 先预设较高值

const getZIndex = function () {
 return zIndex++ // 每次获取之后 zindex 自动增加
}

然后绑定把 z-index 在组件上

<template>
<div class="modal" :style="{'z-index': zIndex}" transition="modal-scale">
 <!--省略其它内容-->
</div>
</template>
<script>
export default {
 data () {
  return {
   zIndex: getZIndex()
  }
 }
}
</script>

overlay 遮盖层的控制

遮盖层是弹窗组件中最难处理的部分, 一个完美的遮盖层的控制需要完成以下几点:

     1、遮盖层和弹出层之间的动画需要并行

     2、遮盖层的 z-index 要较小与弹出层

     3、遮盖层的弹出时需要组件页面滚动

     4、点击遮盖层需要给予弹出层反馈

     5、保证整个页面最多只能有一个遮盖层(多个叠在一起会使遮盖层颜色加深)

为了处理这些问题,也保证所有的弹出框组件不用每一个都解决,所以决定利用 vue 的 mixins 机制,将这些弹出层的公共逻辑封装层一个 mixin ,每个弹出框组件直接引用就好。

vue-popup-mixin

明确了上述所有的问题,开始开发 mixin, 首先需要一个 overlay (遮盖层组件) ;

<template>
 <div class="overlay" @click="handlerClick" @touchmove="prevent" :style="style" transition="overlay-fade"></div>
</template>
<script>
export default {
 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>
<style lang="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 .3s linear;
 &.overlay-fade-enter,
 &.overlay-fade-leave {
 opacity: 0 !important;
 }
}
</style>

然后 需要一个 js 来管理 overlay 的显示和隐藏。

import Vue from 'vue'
import overlayOpt from '../overlay' // 引入 overlay 组件
const Overlay = Vue.extend(overlayOpt)

const getDOM = function (dom) {
 if (dom.nodeType === 3) {
 dom = dom.nextElementSibling || dom.nextSibling
 getDOM(dom)
 }
 return dom
}

// z-index 控制
const zIndex = 20141223 

const getZIndex = function () {
 return zIndex++ 
}
// 管理
const PopupManager = {
 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
 const dom = getDOM(instance.$el)
 dom.style.zIndex = getZIndex()
 },
 // 弹出框关闭方法
 close (instance) {
 let index = 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) {
 let overlay = this.overlay = new Overlay({
  el: document.createElement('div')
 })
 const dom = 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
 let overlay = this.overlay
 this.overlay = null
 overlay.$remove(() => {
  overlay.$destroy()
 })
 },
 changeOverlayStyle () {
 if (!this.overlay || this.instances.length === 0) return
 const instance = this.instances[this.instances.length - 1]
 this.overlay.color = instance.overlayColor
 this.overlay.opacity = instance.overlayOpacity
 },
 // 遮盖层点击处理,会自动调用 弹出层的 overlayClick 方法
 handlerOverlayClick () {
 if (this.instances.length === 0) return
 const instance = 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) {
  const topInstance = PopupManager.instances[PopupManager.instances.length - 1]
  if (!topInstance) return
  if (topInstance.escPress) {
  topInstance.escPress()
  }
 }
 }
})

export default PopupManager

最后再封装成一个 mixin

import PopupManager from './popup-manager'

export default {
 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>
 <div class="dialog"
 v-show="show"
 transition="dialog-fade">
 <div class="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 .3s linear;
 }

 .dialog-fade-enter,
 .dialog-fade-leave {
 opacity: 0;
 }
</style>

<script>
import Popup from '../src'

export default {
 mixins: [Popup],
 methods: {
 // 响应 overlay事件
 overlayClick () {
  this.show = false
 },
 // 响应 esc 按键事件
 escPress () {
  this.show = false
 }
 }
}
</script>

总结

以上就是关于vue.js弹窗组件的一些知识点,希望对大家的学习或者工作带来一定的帮助,如果大家有疑问可以留言交流,谢谢大家对三水点靠木的支持。

Javascript 相关文章推荐
JavaScript 编程引入命名空间的方法与代码
Aug 13 Javascript
解读IE和firefox下JScript和HREF的执行顺序
Jan 12 Javascript
JavaScript 面向对象的之私有成员和公开成员
May 04 Javascript
JS判断两个时间大小的示例代码
Jan 28 Javascript
JavaScript排序算法之希尔排序的2个实例
Apr 04 Javascript
PHP+jQuery实现随意拖动层并即时保存拖动位置
Apr 30 Javascript
js代码验证手机号码和电话号码是否合法
Jul 30 Javascript
js模仿php中strtotime()与date()函数实现方法
Aug 11 Javascript
解决vue中使用swiper插件问题及swiper在vue中的用法
Apr 04 Javascript
超出JavaScript安全整数限制的数字计算BigInt详解
Jun 24 Javascript
使用layer弹窗提交表单时判断表单是否输入为空的例子
Sep 26 Javascript
JS实现盒子拖拽效果
Feb 06 Javascript
JavaScript常用代码书写规范的超全面总结
Sep 11 #Javascript
Javascript实现前端简单的路由实例
Sep 11 #Javascript
JavaScript中Array的实用操作技巧分享
Sep 11 #Javascript
JS实现六边形3D拖拽翻转效果的方法
Sep 11 #Javascript
最全面的百度地图JavaScript离线版开发
Sep 10 #Javascript
简单分析javascript中的函数
Sep 10 #Javascript
javascript数组常用方法汇总
Sep 10 #Javascript
You might like
php在线代理转向代码
2012/05/05 PHP
php实现根据url自动生成缩略图的方法
2014/09/23 PHP
PHP实现简单汉字验证码
2015/07/28 PHP
php遍历替换目录下文件指定内容的方法
2016/11/10 PHP
ThinkPHP5.0框架使用build 自动生成模块操作示例
2019/04/11 PHP
解决Laravel5.5下的toArray问题
2019/10/15 PHP
JavaScript网页制作特殊效果用随机数
2007/05/22 Javascript
在javascript中实现函数数组的方法
2013/12/25 Javascript
Jquery遍历checkbox获取选中项value值的方法
2014/02/13 Javascript
javascript实现textarea中tab键的缩排处理方法
2015/06/26 Javascript
JavaScript实现倒计时代码段Item1(非常实用)
2015/11/03 Javascript
jQuery on()方法绑定动态元素的点击事件无响应的解决办法
2016/07/07 Javascript
BootStrap轻松实现微信页面开发代码分享
2016/10/21 Javascript
JavaScript实现图片切换效果
2017/08/12 Javascript
vue引入新版 vue-awesome-swiper插件填坑问题
2018/01/25 Javascript
解决vue build打包之后首页白屏的问题
2018/03/06 Javascript
微信小程序项目实践之九宫格实现及item跳转功能
2018/07/19 Javascript
JavaScript事件冒泡与事件捕获实例分析
2018/08/01 Javascript
一个小时快速搭建微信小程序的方法步骤
2019/04/15 Javascript
vue 实现input表单元素的disabled示例
2019/10/28 Javascript
微信小程序报错: thirdScriptError的错误问题
2020/06/19 Javascript
Python 字符串中的字符倒转
2008/09/06 Python
python正则表达式匹配[]中间为任意字符的实例
2018/12/25 Python
深入解析python中的实例方法、类方法和静态方法
2019/03/11 Python
Python+threading模块对单个接口进行并发测试
2019/06/25 Python
Django Rest framework三种分页方式详解
2019/07/26 Python
Python3.7.0 Shell添加清屏快捷键的实现示例
2020/03/23 Python
python中for in的用法详解
2020/04/17 Python
Python中logging日志记录到文件及自动分割的操作代码
2020/08/05 Python
加拿大高尔夫超市:Golf Town
2018/01/12 全球购物
乌克兰电子产品和家用电器购物网站:TOUCH
2019/08/09 全球购物
教师找工作推荐信
2013/11/23 职场文书
给学校建议书范文
2014/05/13 职场文书
工作能力自我评价2015
2015/03/05 职场文书
解决Swagger2返回map复杂结构不能解析的问题
2021/07/02 Java/Android
apache ftpserver搭建ftp服务器
2022/05/20 Servers