关于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编写贪吃蛇游戏
Jul 07 Javascript
jQuery实现内容定时切换效果完整实例
Apr 06 Javascript
AngularJS中的指令全面解析(必看)
May 20 Javascript
JavaScript中push(),join() 函数 实例详解
Sep 06 Javascript
如何用js判断dom是否有存在某class的值
Feb 13 Javascript
Node.js获取前端ajax提交的request信息
Feb 20 Javascript
JavaScript的for循环中嵌套一个点击事件的问题解决
Mar 03 Javascript
详解基于node的前端项目编译时内存溢出问题
Aug 01 Javascript
微信小程序wx.previewImage预览图片实例详解
Dec 07 Javascript
vsCode安装使用教程和插件安装方法
Aug 24 Javascript
原生js实现瀑布流效果
Mar 09 Javascript
vue移动端下拉刷新和上滑加载
Oct 27 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的sprintf函数的用法 控制浮点数格式
2014/02/14 PHP
Yii2 rbac权限控制操作步骤实例教程
2016/04/29 PHP
ThinkPHP5+UEditor图片上传到阿里云对象存储OSS功能示例
2019/08/05 PHP
出现“不能执行已释放的Script代码”错误的原因及解决办法
2007/08/29 Javascript
jQuery 1.2.x 升? 1.3.x 注意事项
2009/05/06 Javascript
jquery 表格分页等操作实现代码(pagedown,pageup)
2010/04/11 Javascript
JavaScript call apply使用 JavaScript对象的方法绑定到DOM事件后this指向问题
2011/09/28 Javascript
JSONP 跨域共享信息
2012/08/16 Javascript
网页防止tab键的使用快速解决方法
2013/11/07 Javascript
JavaScript编程的10个实用小技巧
2014/04/18 Javascript
易操作的jQuery表单提示插件
2015/12/01 Javascript
JavaScript面向对象之私有静态变量实例分析
2016/01/14 Javascript
nodejs微信公众号支付开发
2016/09/19 NodeJs
NODE.JS跨域问题的完美解决方案
2016/10/20 Javascript
解决微信内置浏览器返回上一页强制刷新问题方法
2017/02/05 Javascript
从零开始学习Node.js系列教程之基于connect和express框架的多页面实现数学运算示例
2017/04/13 Javascript
在ABP框架中使用BootstrapTable组件的方法
2017/07/31 Javascript
layer.open 按钮的点击事件关闭方法
2018/08/17 Javascript
关于vue v-for循环解决img标签的src动态绑定问题
2018/09/18 Javascript
iView-admin 动态路由问题的解决方法
2018/10/03 Javascript
Nodejs核心模块之net和http的使用详解
2019/04/02 NodeJs
[05:16]《大圣!大圣》——DOTA2新英雄齐天大圣配音李世宏老师专访
2016/12/13 DOTA
[00:34]拔城逐梦,热血永恒!2020(秋)完美世界城市挑战赛报名开启
2020/10/09 DOTA
浅谈Python脚本开头及导包注释自动添加方法
2018/10/27 Python
解决pycharm的Python console不能调试当前程序的问题
2019/01/20 Python
对python判断ip是否可达的实例详解
2019/01/31 Python
Python的log日志功能及设置方法
2019/07/11 Python
CSS3的新特性介绍
2008/10/31 HTML / CSS
Internet体系结构
2014/12/21 面试题
家长会主持词
2014/03/26 职场文书
庆国庆活动总结
2014/08/28 职场文书
民族学专业职业生涯规划范文:积跬步以至千里
2014/09/11 职场文书
工作证明格式及范本
2014/09/12 职场文书
公司财务部岗位职责
2015/04/14 职场文书
入伍志愿书怎么写?
2019/07/19 职场文书
python实现简单的井字棋
2021/05/26 Python