虽然 DmitrySemenov 解决方案对我有用,但当您在页面上有多个模式时,它并不是最好的解决方案。我试过了,我发现它会为每个模式触发关闭事件。
我认为最好的方法是在显示模式时注册“keyup”事件并在隐藏后取消注册。它为您提供了一个优势,因为该事件仅在需要时才注册。为此,您需要为“show”属性添加一个观察者:
props: {
show: {
type: Boolean,
default: false
}
},
watch: {
show() {
if (this.show === false) {
window.removeEventListener("keyup", this.onEscapeKeyUp);
} else {
window.addEventListener("keyup", this.onEscapeKeyUp);
}
}
},
methods: {
onEscapeKeyUp(event) {
if (event.which === 27) {
this.$emit("close");
}
}
}
模态应该具有v-if="show"
控制模态的可见性:
<div class="modal-mask" v-if="show" @click="$emit('close');">
模态的.vue
<template>
<transition name="modal">
<div class="modal-mask" v-if="show" @click="$emit('close');">
<div class="modal-wrapper" @click.stop>
<div class="modal-container">
<div class="modal-header"><slot name="header"></slot></div>
<div class="modal-body"><slot name="body"></slot></div>
<div class="modal-footer">
<slot name="footer">
<div class="buttons">
<a class="button" href="#" @click.prevent="$emit('close');">
OK
</a>
</div>
</slot>
</div>
</div>
</div>
</div>
</transition>
</template>
<script>
export default {
name: "Modal",
props: {
show: {
type: Boolean,
default: false
}
},
watch: {
show() {
const body = document.querySelector("body");
if (this.show === false && body.style.overflow === "hidden") {
body.style.overflow = "";
window.removeEventListener("keyup", this.onEscapeKeyUp);
} else {
body.style.overflow = "hidden";
window.addEventListener("keyup", this.onEscapeKeyUp);
}
}
},
methods: {
onEscapeKeyUp(event) {
if (event.which === 27) {
console.log("close event");
this.$emit("close");
}
}
}
};
</script>
<style lang="scss" scoped>
.modal-mask {
position: fixed;
z-index: 1100;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.5);
overflow: auto;
transition: opacity 0.3s ease;
display: flex;
justify-content: center;
align-items: center;
}
.modal-wrapper {
max-width: 980px;
width: 100%;
}
.modal-container {
padding: 1.5em 2em;
background-color: white;
border-radius: 2px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.33);
transition: all 0.3s ease;
}
.wrapper {
max-width: 980px;
}
.modal-body {
margin: 1em 0;
}
.modal-enter {
opacity: 0;
}
.modal-leave-active {
opacity: 0;
}
.modal-enter .modal-container,
.modal-leave-active .modal-container {
-webkit-transform: scale(1.1);
transform: scale(1.1);
}
</style>
应用程序.vue
<template>
<div id="app">
<button @click="show1 = true;">Show first modal</button>
<button @click="show2 = true;">Show second modal</button>
<Modal :show="show1" @close="show1 = false;">
<div slot="header"><h1>First Modal</h1></div>
<div slot="body">
Lorem ipsum dolor sit amet consectetur, adipisicing elit. Rem beatae
repellat dolores deleniti illum voluptatem facilis neque ut placeat,
eius iusto tempore! Totam omnis non tempore perferendis expedita numquam
neque!
</div>
</Modal>
<Modal :show="show2" @close="show2 = false;">
<div slot="header"><h1>Second Modal</h1></div>
<div slot="body">
Lorem ipsum dolor sit amet consectetur, adipisicing elit. Rem beatae
repellat dolores deleniti illum voluptatem facilis neque ut placeat,
eius iusto tempore! Totam omnis non tempore perferendis expedita numquam
neque!
</div>
</Modal>
</div>
</template>
<script>
import Modal from "./components/Modal";
export default {
name: "App",
components: {
Modal
},
data() {
return {
show1: false,
show2: false
};
}
};
</script>