【问题标题】:Why is transition inside an element with v-if not entering the transition but leaving works?为什么使用 v-if 不进入转换但离开工作的元素内部的转换?
【发布时间】:2021-07-11 19:48:31
【问题描述】:

标题几乎解释了一切。我已经在 StackOverflow 上搜索了解决方案,但 neither of 他们提供了帮助。

一个使用经典模态组件的例子:

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>

也就是说,我必须将 &lt;modal&gt;&lt;transition&gt; 包装在任何地方使用并从模态本身移除过渡(这听起来不太好)

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

为什么会这样以及如何使进入动画工作(v-if&lt;transition&gt; 模态组件中?

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

【问题讨论】:

    标签: javascript vue.js vuejs2 vue-transitions


    【解决方案1】:

    您缺少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 即可解决问题。

    【讨论】:

      【解决方案2】:

      这是因为 v-if 插入/销毁元素而 v-show 隐藏了它们(不会从 DOM 中删除它们)。在您的示例中,如果 v-if 设置在过渡元素上/上方,则 transition 不存在。如果您将v-if 移动到转换下方,那么它将起作用。

      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>

      【讨论】:

      • 谢谢,确实有效。更奇怪的是使用Vue 2.5(而不是2.6)时没有问题
      【解决方案3】:

      这应该可以解决问题:

      {
        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>

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-01-23
        • 1970-01-01
        • 1970-01-01
        • 2021-05-22
        • 2018-07-31
        • 2021-05-26
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多