我期待'关闭'事件在我被解雇时被解雇 单击ESC按钮处于“阴影模式”div,但它没有发生
vue 2.5.13,任何想法为什么?
<template>
<div class="shadow-modal"
@keyup.esc="$emit('close')">
<transition name="modal">
<div class="modal-mask">
<div class="modal-wrapper">
<div class="modal-container">
<div class="modal-header">
<slot name="header">
default header
</slot>
</div>
<div class="modal-body">
<slot name="body">
default body
</slot>
</div>
<div class="modal-footer">
<slot name="footer">
<a href="#"
class="btn btn--diagonal btn--blue"
@click="$emit('close')">Cancel</a>
</slot>
</div>
</div>
</div>
</div>
</transition>
</div>
</template>
答案 0 :(得分:17)
虽然您尝试绑定keyborad事件不是输入元素,但除非您定义tabindex,否则它们将无法工作:
<div class="shadow-modal" @keyup.esc="$emit('close')" tabindex="0">
以下是参考资料:https://www.w3.org/WAI/GL/WCAG20/WD-WCAG20-TECHS/SCR29.html
答案 1 :(得分:3)
(除了之前的2个答案。)
你没有用Vue处理所有事件。
这是另一种方式
export default {
created() {
document.onkeydown = evt => {
evt = evt || window.event;
if (evt.keyCode == 27) {
this.$emit("close");
}
};
}
};
答案 2 :(得分:1)
虽然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');">
<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>
<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>
答案 3 :(得分:0)
我的替代实施
<template>
<div class="shadow-modal"
@keyup.esc="$emit('close')">
<transition name="modal">
<div class="modal-mask">
<div class="modal-wrapper">
<div class="modal-container">
<div class="modal-header">
<slot name="header">
default header
</slot>
</div>
<div class="modal-body">
<slot name="body">
default body
</slot>
</div>
<div class="modal-footer">
<slot name="footer">
<a href="#"
class="btn btn--diagonal btn--blue"
@click="$emit('close')">Cancel</a>
</slot>
</div>
</div>
</div>
</div>
</transition>
</div>
</template>
<script>
export default {
beforeMount() {
window.addEventListener('keyup', this.onEscapeKeyUp);
},
beforeDestroy () {
window.removeEventListener('keyup', this.onEscapeKeyUp)
},
methods: {
onEscapeKeyUp (event) {
if (event.which === 27) {
this.$emit('close');
}
},
},
};
</script>
答案 4 :(得分:0)
如果需要关闭模式窗口,则必须遵守几个条件。
<div class="modal-content" ref="modal" tabindex="0" @keyup.esc="$emit('close')">
mounted() {
this.$refs.modal.focus()
}
答案 5 :(得分:-1)
无法从div或其他元素生成Key事件。为了从div获取关键事件,您需要在div元素中使用<Input type="text"></Input>
。