【问题标题】:Prevent child elements for receiving click event not working防止子元素接收点击事件不起作用
【发布时间】:2020-03-29 14:29:53
【问题描述】:

我正在尝试制作一个模态组件并在我单击组件外部时将其关闭。这是我当前的设置:

  1. Auth 组件,在 div 元素上设置了点击事件:
    <template>   <div>
        <transition name="modal">
          <div class="modal-mask" @click="$parent.$emit('close')">
            <div class="modal-wrapper">
              <div class="modal-container">
                <div class="modal-header">
                  <slot name="header">Default Header</slot>
                </div>
                <div class="model-body">
                  <slot name="body">Default Body</slot>
                </div>
                <div class="modal-footer">
                  <slot name="footer">Default Footer</slot>
                </div>
              </div>
            </div>
          </div>
        </transition>   </div> </template>
  1. SignIn 组件,用于注入必要的信息:
<template>
  <div>
    <Auth />
  </div>
</template>
  1. Home 使用 SignIn 组件的组件:
<template>
  <div class="home">
    <SignIn v-if="showModal" @close="showModal = false" />
  </div>
</template>

现在,当我在模式外部单击时,它的行为正常,close 事件被调用。
但是当我在模态框内单击时也会调用它。

我没有尝试使用 @click.self ,但现在即使在模式外单击也无法使用。

      <div class="modal-mask" @click.self="$parent.$emit('close')">

我目前正在学习 VueJs,但我不明白它是如何工作的。我认为self 会阻止将点击事件传播到子元素,仅此而已。

有人知道发生了什么吗?

PS:我正在使用此设置,因为我想使用 Auth 组件进行登录和注册。

【问题讨论】:

  • 您尝试过在模态包装器上使用@click.stop 吗?
  • 是的,当点击外部和内部模态时,停止它会消失。

标签: vue.js


【解决方案1】:

&lt;div class="modal-wrapper"&gt;&lt;div class="modal-container"&gt; 需要 @click.prevent.stop

<template>

   <div>

        <transition name="modal">

          <div class="modal-mask" @click="$parent.$emit('close')">

            <div class="modal-wrapper">

              <div class="modal-container" @click.prevent.stop>

                <div class="modal-header">
                  <slot name="header">Default Header</slot>
                </div>

                <div class="model-body">
                  <slot name="body">Default Body</slot>
                </div>

                <div class="modal-footer">
                  <slot name="footer">Default Footer</slot>
                </div>

              </div>

            </div>

          </div>

        </transition>

    </div>

</template>

【讨论】:

  • 你是对的,
【解决方案2】:

使用此代码,您不必担心点击事件的传播 @click.stop,出于 style 的目的,我使用的是 bootstrap.css,但您可以编写自己的样式。

这里是可复用的组件 BsModal.vue

<template lang="pug">
  div(v-if="showModal")
    .modal.fade.d-block(tabindex='-1', role='dialog', :class="{'show': addShowClassToModal}")
      .modal-dialog(role='document')
        .modal-content.border-0
          .modal-header.border-0
            h5.modal-title
              slot(name="title")
            button.close(type='button', data-dismiss='modal', aria-label='Close', @click="hideModal")
              span &times;
          .modal-body.p-0
            slot
    .modal-backdrop.fade(:class="{ 'show': addShowClassToModalBackdrop }")
</template>

<script>
export default {
  name: 'BsModal',
  props: {
    showModal: {
      default: false,
      type: Boolean,
    },
  },

  data() {
    return {
      addShowClassToModal: false,
      addShowClassToModalBackdrop: false,
    };
  },

  mounted() {
    this.toggleBodyClass('addClass', 'modal-open');

    setTimeout(() => {
      this.addShowClassToModalBackdrop = true;
    }, 100);
    setTimeout(() => {
      this.addShowClassToModal = true;
    }, 400);
  },

  destroyed() {
    this.toggleBodyClass('removeClass', 'modal-open');
  },

  methods: {
    hideModal() {
      setTimeout(() => {
        this.addShowClassToModal = false;
      }, 100);

      setTimeout(() => {
        this.addShowClassToModalBackdrop = false;
        this.$emit('hide-modal', false);
      }, 400);
    },
    toggleBodyClass(addRemoveClass, className) {
      const elBody = document.body;

      if (addRemoveClass === 'addClass') {
        elBody.classList.add(className);
      } else {
        elBody.classList.remove(className);
      }
    },
  },
};
</script>

并通过导入在任何需要的地方使用它:

<template lang="pug">
  div
    button(@click="showModal = true")
      | Show Modal
    bs-modal(
      v-if="showModal",
      :show-modal="showModal",
      @hide-modal="showModal = false"
    ).modal
      template(slot="title") Modal Title
      // Modal Body content here
</template>

<script>
import BsModal from '~/components/BsModal.vue';

export default {
  name: 'your component',
  components: { BsModal },

  data() {
    return {
      showModal: false,
    };
  },
};
</script>

如果您不喜欢 pug 模板语言,那么您可以在此处将 PUG 转换为 HTML:https://pughtml.com/

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-07-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-09-22
    • 1970-01-01
    • 2018-07-27
    相关资源
    最近更新 更多