v-if 上平滑的 vue 折叠过渡

新手上路,请多包涵

我正在努力尝试使用 v-if 顺利显示/隐藏内容的 vue 转换。虽然我了解 css 类和过渡,但我可以使用不透明度或翻译等方式使内容“平滑地”显示……但是一旦动画完成(或者更确切地说,当它开始时),下面的任何 html 部分似乎“跳跃” ‘.

我正在尝试实现与 Bootstrap 4 ‘collapse’ 类相同的效果 - 单击此处顶部的按钮之一: https ://getbootstrap.com/docs/4.0/components/collapse/

当隐藏部分出现/消失时,所有 html 内容都可以很好地“滑动”。

对于使用 v-if 显示的内容,是否可以使用 Vue 转换? vue transitions docs 上的所有示例虽然具有出色的 css 过渡效果,但在过渡开始或完成后具有以下 html“跳转”。

我见过一些使用最大高度的纯 js 解决方案 - https://jsfiddle.net/wideboy32/7ap15qq0/134/

并尝试使用 vue: https://jsfiddle.net/wideboy32/eywraw8t/303737/

 .smooth-enter-active, .smooth-leave-active {
  transition: max-height .5s;
}
.smooth-enter, .smooth-leave-to {
  max-height: 0 .5s;
}

谢谢!

原文由 The Wideboy 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 968
2 个回答

如果你想为最大高度设置动画,那么你应该为你想要设置动画的元素输入最大高度的数量,同时在最大高度定义中输入’s’(或秒)时更正第二类:

 p{
  max-height: 20px;
}
.smooth-enter-active, .smooth-leave-active {
  transition: max-height .5s;
}
.smooth-enter, .smooth-leave-to {
  max-height: 0;
}

如果你想要像 bs4 collapse 这样的东西,那么 vue 网站中的例子就可以了:

 .smooth-enter-active, .smooth-leave-active {
  transition: opacity .5s;
}
.smooth-enter, .smooth-leave-to {
  opacity: 0
}

编辑:您要做的是通过首先找出内容的高度然后将其设置在 .*-enter-to.*-leave 类中来实现。下面的小提琴演示了一种方法:

https://jsfiddle.net/rezaxdi/sxgyj1f4/3/

您也可以完全忘记 v-if 或 v-show 并使用我认为更平滑的高度值隐藏元素:

https://jsfiddle.net/rezaxdi/tgfabw65/9/

原文由 r3zaxd1 发布,翻译遵循 CC BY-SA 4.0 许可协议

我也有类似的任务。我发现没有 JS 是不可能做到的。所以我编写了自定义转换组件( 可重用转换)并且它对我有用:

 Vue.component('transition-collapse-height', {
  template: `<transition
    enter-active-class="enter-active"
    leave-active-class="leave-active"
    @before-enter="beforeEnter"
    @enter="enter"
    @after-enter="afterEnter"
    @before-leave="beforeLeave"
    @leave="leave"
    @after-leave="afterLeave"
  >
    <slot />
  </transition>`,
  methods: {
    /**
     * @param {HTMLElement} element
     */
    beforeEnter(element) {
      requestAnimationFrame(() => {
        if (!element.style.height) {
          element.style.height = '0px';
        }

        element.style.display = null;
      });
    },
    /**
     * @param {HTMLElement} element
     */
    enter(element) {
      requestAnimationFrame(() => {
        requestAnimationFrame(() => {
          element.style.height = `${element.scrollHeight}px`;
        });
      });
    },
    /**
     * @param {HTMLElement} element
     */
    afterEnter(element) {
      element.style.height = null;
    },
    /**
     * @param {HTMLElement} element
     */
    beforeLeave(element) {
      requestAnimationFrame(() => {
        if (!element.style.height) {
          element.style.height = `${element.offsetHeight}px`;
        }
      });
    },
    /**
     * @param {HTMLElement} element
     */
    leave(element) {
      requestAnimationFrame(() => {
        requestAnimationFrame(() => {
          element.style.height = '0px';
        });
      });
    },
    /**
     * @param {HTMLElement} element
     */
    afterLeave(element) {
      element.style.height = null;
    },
  },
});

new Vue({
  el: '#app',
  data: () => ({
    isOpen: true,
  }),
  methods: {
    onClick() {
      this.isOpen = !this.isOpen;
    }
  }
});
 .enter-active,
.leave-active {
  overflow: hidden;
  transition: height 1s linear;
}

.content {
  background: grey;
}
 <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
  <button @click="onClick">
    open/hide
  </button>
  <transition-collapse-height>
   <div v-show="isOpen" class="content">
     <br/>
     <br/>
     <br/>
     <br/>
   </div>
  </transition-collapse-height>
</div>

原文由 Alexandr Vysotsky 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
logo
Stack Overflow 翻译
子站问答
访问
宣传栏