0

标题几乎解释了一切。我已经在 StackOverflow 上搜索了解决方案,但他们都没有 帮助。

使用经典模态组件的示例:

Vue.component('modal', {
  template: `
  <transition name="modal">
    <div class="modal-wrapper">
      <div class="modal-dialog">
        <slot></slot>
      </div>
    </div>
  </transition>
  `,
})

const app = new Vue({
  el: '#app',
  data: {
    showModal: false,
  },
})
/* transition */
.modal-enter-active,
.modal-leave-active {
  transition: opacity .5s;
}

.modal-enter,
.modal-leave-to {
  opacity: 0;
}

.modal-wrapper {
  position: absolute;
  left: 0; right: 0;
  top: 0; bottom: 0;
  display: flex;
  justify-content: center;
  align-items: center;
  background: rgba(0, 0, 0, .25);
}

.modal-dialog {
  max-width: 90%;
  padding: 1em;
  background: white;
}
<script src="https://vuejs.org/js/vue.js"></script>
<div id="app">
  <p><button @click="showModal = true">Show modal</button></p>
  <modal v-if="showModal">
    <h3>Hello world</h3>
    <p>Amet quam alias amet incidunt voluptatum sapiente Mollitia</p>
    <p><button @click="showModal = false">Close</button></p>
  </modal>
</div>

(控制台中也没有错误)

但是,使用时一切正常v-show。但我不能在我的项目中真正使用它来代替 v-if 。

Vue.component('modal', {
  template: `
  <transition name="modal">
    <div class="modal-wrapper">
      <div class="modal-dialog">
        <slot></slot>
      </div>
    </div>
  </transition>
  `,
})

const app = new Vue({
  el: '#app',
  data: {
    showModal: false,
  },
})
/* transition */
.modal-enter-active,
.modal-leave-active {
  transition: opacity .5s;
}

.modal-enter,
.modal-leave-to {
  opacity: 0;
}

.modal-wrapper {
  position: absolute;
  left: 0; right: 0;
  top: 0; bottom: 0;
  display: flex;
  justify-content: center;
  align-items: center;
  background: rgba(0, 0, 0, .25);
}

.modal-dialog {
  max-width: 90%;
  padding: 1em;
  background: white;
}
<script src="https://vuejs.org/js/vue.js"></script>
<div id="app">
  <p><button @click="showModal = true">Show modal</button></p>
  <modal v-show="showModal">
    <h3>Hello world</h3>
    <p>Amet quam alias amet incidunt voluptatum sapiente Mollitia</p>
    <p><button @click="showModal = false">Close</button></p>
  </modal>
</div>

也就是说,我必须在使用模态的所有地方进行包装<modal>,并从模态本身删除过渡(这听起来不太好)<transition>

<transition name="modal">
  <modal>
  ...
  </modal>
</transition>

为什么会这样以及如何使输入动画起作用(使用v-if, 和<transition> 模态组件中?

我注意到 Vue 2.5(而不是 Vue 2.6)没有这样的问题。从那以后肯定发生了一些变化。

4

3 回答 3

4

您缺少该appear属性。

默认情况下,第一次插入元素时,Vue 不会动画。根据文档:

如果您还想在节点的初始渲染上应用过渡,可以添加出现属性:

<transition appear>
  <!-- ... -->
</transition>

默认情况下,这将使用为进入和离开指定的转换。但是,如果您愿意,还可以指定自定义 CSS 类:

<transition
  appear
  appear-class="custom-appear-class"
  appear-to-class="custom-appear-to-class"
  appear-active-class="custom-appear-active-class"
>
<!-- ... -->
</transition>

因此,只需添加即可appear解决问题。

于 2021-06-20T04:52:51.390 回答
1

That's because v-if inserts/destroys elements and v-show hides them (does not remove them from DOM). In your example, transition does not exists if v-if is setup on/above transition element. If you move v-if below transition, then it will work.

Vue.component('modal', {
  props: ['showModal'],
  template: `
  <transition name="modal">
    <div class="modal-wrapper" v-if="showModal">
      <div class="modal-dialog">
        <slot></slot>
      </div>
    </div>
  </transition>
  `,
})

const app = new Vue({
  el: '#app',
  data: {
    showModal: false,
  },
})
/* transition */
.modal-enter-active,
.modal-leave-active {
  transition: opacity .5s;
}

.modal-enter,
.modal-leave-to {
  opacity: 0;
}

.modal-wrapper {
  position: absolute;
  left: 0; right: 0;
  top: 0; bottom: 0;
  display: flex;
  justify-content: center;
  align-items: center;
  background: rgba(0, 0, 0, .25);
}

.modal-dialog {
  max-width: 90%;
  padding: 1em;
  background: white;
}
<script src="https://vuejs.org/js/vue.js"></script>
<div id="app">
  <p><button @click="showModal = true">Show modal</button></p>
  <modal :show-modal="showModal">
    <h3>Hello world</h3>
    <p>Amet quam alias amet incidunt voluptatum sapiente Mollitia</p>
    <p><button @click="showModal = false">Close</button></p>
  </modal>
</div>

于 2021-04-16T19:50:21.840 回答
0

这应该可以解决问题:

{
  template: `
  <transition name="modal">
    <div v-if="show">...</div>
  </transition>
  `,
  data() {return {
    show: false,
  }},
  mounted() {
    this.show = true
  },
}

我认为这种方法(我相信确实如此)将动画延迟了 1 个 Vue 滴答声,并且大量嵌套此类动画元素会使速度明显变慢。

Vue.component('modal', {
  template: `
  <transition name="modal">
    <div class="modal-wrapper" v-if="show">
      <div class="modal-dialog">
        <slot></slot>
      </div>
    </div>
  </transition>
  `,
  data() {return {
    show: false,
  }},
  mounted() {
    this.show = true
  }
})

const app = new Vue({
  el: '#app',
  data: {
    showModal: false,
  },
})
/* transition */
.modal-enter-active,
.modal-leave-active {
  transition: opacity .5s;
}

.modal-enter,
.modal-leave-to {
  opacity: 0;
}

.modal-wrapper {
  position: absolute;
  left: 0; right: 0;
  top: 0; bottom: 0;
  display: flex;
  justify-content: center;
  align-items: center;
  background: rgba(0, 0, 0, .25);
}

.modal-dialog {
  max-width: 90%;
  padding: 1em;
  background: white;
}
<script src="https://vuejs.org/js/vue.js"></script>
<div id="app">
  <p><button @click="showModal = true">Show modal</button></p>
  <modal v-if="showModal">
    <h3>Hello world</h3>
    <p>Amet quam alias amet incidunt voluptatum sapiente Mollitia</p>
    <p><button @click="showModal = false">Close</button></p>
  </modal>
</div>

于 2021-06-20T16:50:10.673 回答