Tout d'abord, les trois points suivants doivent être pris en compte lors du développement :
1. Effets d'animation de saisie et pop-up.
2. Contrôle de l'index Z
3. Superposition du calque de masquage
À propos de l'animation
vue le traitement de l'animation est relativement simple. Ajoutez simplement une animation de transition CSS au composant
<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>
L'externe peut être contrôlé par l'utilisateur, en utilisant v-if ou v-show pour contrôler le afficher
Contrôle du z-index
Concernant le contrôle du z-index, les points suivants doivent être complétés
1. Assurez-vous que le z-index de la boîte contextuelle est suffisamment haute pour activer sa couche la plus externe
2. L'index z de la boîte contextuelle qui apparaît plus tard est plus élevé que celui qui est apparu avant
Pour satisfaire les deux points ci-dessus, nous avons besoin de ce qui suit. Le code implémente
const zIndex = 20141223 // 先预设较高值 const getZIndex = function () { return zIndex++ // 每次获取之后 zindex 自动增加 }
puis lie z-index au composant
<template> <div class="modal" :style="{'z-index': zIndex}" transition="modal-scale"> <!--省略其它内容--> </div> </template> <script> export default { data () { return { zIndex: getZIndex() } } } </script>
Contrôle de la superposition
La couche de revêtement est la partie la plus difficile à gérer dans le composant de la fenêtre contextuelle. Un contrôle parfait de la couche de revêtement doit compléter le processus. points suivants :
1. Entre la couche de revêtement et la couche pop-up L'animation doit être parallèle
2. Le z-index de la couche de revêtement doit être plus petit que celui du calque contextuel
3. Lorsque le calque de recouvrement apparaît, la page du composant doit défiler
4. Cliquer sur le calque de recouvrement nécessite des commentaires sur le calque contextuel
5. Assurez-vous qu'il peut y avoir au plus un calque de recouvrement sur toute la page (plusieurs piles ensemble approfondiront la couleur du calque de recouvrement)
Afin de résoudre ces problèmes et de garantir que tous les composants des boîtes pop-up n'ont pas besoin d'être résolus individuellement, nous avons décidé d'utiliser le mécanisme mixins de vue pour encapsuler la logique commune de ces couches pop-up dans un mixin. calque et chaque boîte contextuelle Faites simplement référence au composant de cadre directement.
vue-popup-mixin
Après avoir clarifié tous les problèmes ci-dessus, nous avons commencé à développer le mixin. Nous avons d'abord besoin d'une superposition (composant de couche de couverture) ;<🎜. >
<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>
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
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) } }
<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>
Ce qui précède sont quelques points de connaissances sur le composant pop-up vue.js. J'espère qu'il sera utile à l'étude ou au travail de chacun. Si vous avez des questions, vous pouvez laisser un message pour communiquer. votre soutien au site PHP chinois.
Pour plus de résumé des points de connaissances sur le composant pop-up vue.js et les articles associés, veuillez faire attention au site Web PHP chinois !