最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Vue.js transitions: animate height while using slide out animation - Stack Overflow

programmeradmin1浏览0评论

I have a number of items on my page that can be collapsed. Here's a codepen to illustrate.

Vueponent('block', {
  template: '#block',
  props: [ 'title', 'items', 'collapsed' ],
});

new Vue({
  el: '#app',
  data: {
    first: [ 
      { name: 'Item 1' }, 
      { name: 'Item 2' }, 
      { name: 'Item 3' }
    ],
    second: [
      { name: 'Item 1' },
      { name: 'Item 2' },
      { name: 'Item 3' }
    ]
  }
});
#app {
  display: flex;
  flex-direction: column;
}
.block {
  $padding: 10px;
  margin: 20px;
  .title {
    color: white;
    background: grey;
    padding: $padding;
    font-weight: bold;
    font-size: 22px;
    cursor: pointer;
  }
  .list {
    position: relative;
    z-index: -1;
    padding: $padding;
    font-size: 16px;
    border: 1px solid lightgrey;
  }
  .list-item:not(:last-child) {
    padding-bottom: $padding;
  }
}

.slide-out-enter-active,
.slide-out-leave-active {
    transition: all 0.3s;
}

.slide-out-enter,
.slide-out-leave-to {
    opacity: 0;
    transform: translateY(-40px);
}
<script src=".3.4/vue.js"></script>
<div id="app">
  <block :items="first" title="First block"></block>

  <block :items="second" title="Second block"></block>
</div>

<script type="text/x-template" id="block">
  <div class="block">
    <div class="title" @click="collapsed = !collapsed">{{ title }} (click to toggle)</div>
    <transition name="slide-out">
      <div v-if="!collapsed" class="list">
        <div class="list-item" v-for="item in items">
          {{item.name}}
        </div>
      </div>
    </transition>
  </div>
</script>

I have a number of items on my page that can be collapsed. Here's a codepen to illustrate.

Vue.ponent('block', {
  template: '#block',
  props: [ 'title', 'items', 'collapsed' ],
});

new Vue({
  el: '#app',
  data: {
    first: [ 
      { name: 'Item 1' }, 
      { name: 'Item 2' }, 
      { name: 'Item 3' }
    ],
    second: [
      { name: 'Item 1' },
      { name: 'Item 2' },
      { name: 'Item 3' }
    ]
  }
});
#app {
  display: flex;
  flex-direction: column;
}
.block {
  $padding: 10px;
  margin: 20px;
  .title {
    color: white;
    background: grey;
    padding: $padding;
    font-weight: bold;
    font-size: 22px;
    cursor: pointer;
  }
  .list {
    position: relative;
    z-index: -1;
    padding: $padding;
    font-size: 16px;
    border: 1px solid lightgrey;
  }
  .list-item:not(:last-child) {
    padding-bottom: $padding;
  }
}

.slide-out-enter-active,
.slide-out-leave-active {
    transition: all 0.3s;
}

.slide-out-enter,
.slide-out-leave-to {
    opacity: 0;
    transform: translateY(-40px);
}
<script src="https://cdnjs.cloudflare./ajax/libs/vue/2.3.4/vue.js"></script>
<div id="app">
  <block :items="first" title="First block"></block>

  <block :items="second" title="Second block"></block>
</div>

<script type="text/x-template" id="block">
  <div class="block">
    <div class="title" @click="collapsed = !collapsed">{{ title }} (click to toggle)</div>
    <transition name="slide-out">
      <div v-if="!collapsed" class="list">
        <div class="list-item" v-for="item in items">
          {{item.name}}
        </div>
      </div>
    </transition>
  </div>
</script>

I managed to animate the collapse. My problem however, is that if you expand the first block, the second block immediately jumps to its final position. I would like the second block to slide down while the first block is expanding.

Any thoughts?

Share Improve this question edited Oct 31, 2018 at 7:07 fikkatra asked Oct 30, 2018 at 16:22 fikkatrafikkatra 5,8424 gold badges44 silver badges73 bronze badges
Add a ment  | 

2 Answers 2

Reset to default 3

The issues is that your layout does not reflow due to the nature of the transform property after the .list-items are added to your .blockss. You can read about 3 diff techniques that could be used for what you are doing here.

My suggestion to use the min-height property instead and get rid of the Vue transition and simply toggle the class on your .list node. Below are the adjustments that you'd need:

CSS:

  // strip all of the .slide-out-* classes

  .list {
    ....
    max-height: 100px;
    transition: all 1s;
  }

  .block .list.is-collapsed {
    transition: all 1s;
    max-height: 0;
    padding-top: 0;
    padding-bottom: 0;
  }

HTML:

remove tags &

<div class="list" :class="{'is-collapsed': collapsed}">    <--- removed 'v-if'

You could also animate the margin property at the same time as translating. See this codepen example

basically just change your enter and leave-to css to something like this

.slide-out-enter,
.slide-out-leave-to {
    opacity: 0;
    transform: translateY(-100px);
    margin-bottom: -100px;
}
发布评论

评论列表(0)

  1. 暂无评论