关于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 showModalDialog 内跳转页面的问题
Nov 25 Javascript
jQuery获取CSS样式中的颜色值的问题,不同浏览器格式不同的解决办法
May 13 Javascript
JS中数组Array的用法示例介绍
Feb 20 Javascript
使用js显示当前时间示例
Mar 02 Javascript
javascript使用输出语句实现网页特效代码
Aug 06 Javascript
AngularJS基础 ng-srcset 指令简单示例
Aug 03 Javascript
JavaScript实现向select下拉框中添加和删除元素的方法
Mar 07 Javascript
jquery在vue脚手架中的使用方式示例
Aug 29 jQuery
js运算符的一些特殊用法
Jul 29 Javascript
Vue表单控件绑定图文详解
Feb 11 Javascript
bootstrapValidator表单校验、更改状态、新增、移除校验字段的实例代码
May 19 Javascript
vue完美实现el-table列宽自适应
May 08 Vue.js
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.ini中文版
2006/10/09 PHP
PHP中的use关键字概述
2014/07/23 PHP
php生成shtml类用法实例
2014/12/09 PHP
php编程中echo用逗号和用点号连接的区别
2016/03/26 PHP
TP5框架实现上传多张图片的方法分析
2020/03/29 PHP
jQuery学习笔记 更改jQuery对象
2012/09/19 Javascript
jquery乱码与contentType属性设置问题解决方案
2013/01/07 Javascript
javascript获取鼠标点击元素对象(示例代码)
2013/12/20 Javascript
jQuery制作可自定义大小的拼图游戏
2015/03/30 Javascript
JS访问SWF的函数用法实例
2015/07/01 Javascript
js实现文本框宽度自适应文本宽度的方法
2015/08/13 Javascript
javascript实现3D切换焦点图
2015/10/16 Javascript
jqPlot jQuery绘图插件的使用
2016/06/18 Javascript
Angular 4环境准备与Angular cli创建项目详解
2017/05/27 Javascript
es7学习教程之fetch解决异步嵌套问题的方法示例
2017/07/21 Javascript
微信小程序之电影影评小程序制作代码
2017/08/03 Javascript
ajax前台后台跨域请求处理方式
2018/02/08 Javascript
在AngularJs中设置请求头信息(headers)的方法及不同方法的比较
2018/09/04 Javascript
vue element upload组件 file-list的动态绑定实现
2019/10/11 Javascript
[01:01:41]DOTA2-DPC中国联赛 正赛 PSG.LGD vs Magma BO3 第二场 1月31日
2021/03/11 DOTA
python实现列表中由数值查到索引的方法
2018/06/27 Python
详解Python中的正则表达式
2018/07/08 Python
Python 3.8新特征之asyncio REPL
2019/05/28 Python
Python生成一个迭代器的实操方法
2019/06/18 Python
Python大数据之网络爬虫的post请求、get请求区别实例分析
2019/11/16 Python
html5 Canvas画图教程(2)—画直线与设置线条的样式如颜色/端点/交汇点
2013/01/09 HTML / CSS
HTML5页面无缝闪开的问题及解决方案
2020/06/11 HTML / CSS
Skyscanner英国:苏格兰的全球三大领先航班搜索服务之一
2017/11/09 全球购物
Strawberrynet草莓网新加坡站:护肤、彩妆、香水及美发产品
2018/08/31 全球购物
英国儿童设计师服装和玩具购物网站:Zac & Lulu
2020/10/19 全球购物
单身联谊活动方案
2014/01/29 职场文书
离婚协议书样本
2015/01/26 职场文书
博士给导师的自荐信
2015/03/06 职场文书
女性健康知识讲座主持词
2015/07/04 职场文书
pytorch通过训练结果的复现设置随机种子
2021/06/01 Python
SpringCloud之@FeignClient()注解的使用方式
2021/09/25 Java/Android