首页 > 解决方案 > 无论如何在过渡结束时保持显示块?

问题描述

我正在尝试实现不应该影响另一个元素在目标元素附近的位置的惊人动画。过渡没问题,但问题是当它完成动画时,它display: none;默认设置属性,这使得下一个元素跳起来填充它的位置。

我想知道我是否可以保留它display: block;并仅依赖它,opacity但我无法从文档中获得任何线索。是否可以?还是应该改用动画库?

为了演示,请运行此代码段

console.clear();

new Vue({
  el: '#app',
  data() {
    return {
      showItems: false,
    }
  },
  mounted() {
    this.$nextTick(() => {
      this.showItems = true
    });
  }
});
.slide-in-enter-active {
  transition: opacity .5s linear, transform .5s cubic-bezier(.2, .5, .1, 1);
  transition-delay: calc( 0.1s * var(--i));
}

.slide-in-leave-active {
  transition: opacity .4s linear, transform .4s cubic-bezier(.5, 0, .7, .4); //cubic-bezier(.7,0,.7,1); 
  transition-delay: calc( 0.1s * (var(--total) - var(--i)));
}

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

.slide-in-enter,
.slide-in-leave-to {
  transform: translateX(1rem);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">

  <button @click="showItems = !showItems">Show/Hide Items</button>

  <!--
    in real world, this would be dynamic,
    which is the height is unknown (like larger text on a larger screen).
  -->
  <transition-group tag="ul" name="slide-in" :style="{ '--total': 10 }">
    <li v-for="i in 10" :key="i" :style="{'--i': i}" v-show="showItems">
      Item {{ i }}
    </li>
  </transition-group>

  <div class="the-content-that-should-not-moved-up">
    <p style="margin:0;">Another content that should not moved up</p>
    <p style="margin:0;">Another content that should not moved up</p>
    <p style="margin:0;">Another content that should not moved up</p>
    <p style="margin:0;">Another content that should not moved up</p>
  </div>
</div>

标签: vue.js

解决方案


您可以在隐藏列表时保存列表的当前高度,然后应用样式绑定以相应地设置其高度:

  1. 在元素 (a ) 上应用模板引用,以便我们稍后可以获取元素的高度。transition-groupul

    <transition-group ref="list">
    
  2. 添加一个listHeight数据属性来存储transition-group的高度:

    data() {
      return {
        listHeight: null
      }
    }
    
  3. 将样式绑定添加到transition-group要设置的元素height

    <transition-group :style="{ height: listHeight && `${listHeight}px` }">
    
  4. 添加一个观察者,仅在隐藏时showItems捕获高度:transition-group

    watch: {
      showItems(showItems) {
        if (showItems) {
          this.listHeight = null
        } else {
          this.listHeight = this.$refs.list.$el.offsetHeight
        }
      }
    }
    

console.clear();

new Vue({
  el: '#app',
  data() {
    return {
      showItems: false,
      listHeight: null,
    }
  },
  mounted() {
    this.$nextTick(() => {
      this.showItems = true
    });
  },
  watch: {
    showItems(showItems) {
      if (showItems) {
        this.listHeight = null
      } else {
        this.listHeight = this.$refs.list.$el.offsetHeight
      }
    }
  }
});
.slide-in-enter-active {
  transition: opacity .5s linear, transform .5s cubic-bezier(.2, .5, .1, 1);
  transition-delay: calc( 0.1s * var(--i));
}

.slide-in-leave-active {
  transition: opacity .4s linear, transform .4s cubic-bezier(.5, 0, .7, .4); //cubic-bezier(.7,0,.7,1); 
  transition-delay: calc( 0.1s * (var(--total) - var(--i)));
}

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

.slide-in-enter,
.slide-in-leave-to {
  transform: translateX(1rem);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">

  <button @click="showItems = !showItems">Show/Hide Items</button>

  <!--
    in real world, this would be dynamic,
    which is the height is unknown (like larger text on a larger screen).
  -->
  <transition-group tag="ul" name="slide-in" :style="{ '--total': 10, height: listHeight && `${listHeight}px` }" ref="list">
    <li v-for="i in 10" :key="i" :style="{'--i': i}" v-show="showItems">
      Item {{ i }}
    </li>
  </transition-group>

  <div class="the-content-that-should-not-moved-up">
    <p style="margin:0;">Another content that should not moved up</p>
    <p style="margin:0;">Another content that should not moved up</p>
    <p style="margin:0;">Another content that should not moved up</p>
    <p style="margin:0;">Another content that should not moved up</p>
  </div>
</div>


推荐阅读