首页 > 解决方案 > 在 vue 中使用渲染函数进行可重用的过渡

问题描述

我目前正在研究幻灯片模式。类似于Bottom Sheet Vuetify,但它应该从左向右滑动。除此之外,我想使用一个可重用的组件。

我的SlideLeftTransition.ts

import { defineComponent, createElement as h } from '@vue/composition-api';

export const SlideLeftTransition = defineComponent({
  setup(_, context) {
    return function render() {
      return h('transition', {
        props: {
          name: 'animated slideInLeft',
          mode: 'out-in',
        },
      }, 'default' in context.slots ? context.slots.default() : null);
    };
  },
});

然后我使用的组件如下:

import { defineComponent, createElement as h } from '@vue/composition-api';
import { SlideLeftTransition } from '@/ui/components/transitions/SlideLeftTransition';

export const ModalSidePanel = defineComponent<ModalSidePanelProps>({
  setup(props) {
     return function render() {
        return h(SlideLeftTransition, [
          h('div', { style: { display: props.active ? 'block' : 'none' } }, 'this text should appear from left to right sliding'),
        ])
     }
  }
})

我目前的 scss 是:

$animationDuration: 1;

.animated {
  animation-duration: $animationDuration;
  animation-fill-mode: both;
}

@keyframes slideInLeft {
  from {
    transform: translate3d(-100%, 0, 0);
    visibility: visible;
  }

  to {
    transform: translate3d(0, 0, 0);
  }
}

.slideInLeft {
  animation-name: slideInLeft;
}

令人难忘的是没有渲染幻灯片动画。当通过按钮切换时,该元素会神奇地出现在屏幕上。几乎没有关于如何使用带有过渡的渲染功能的文档。有人知道吗?

标签: javascriptvue.js

解决方案


几个问题:

  1. <transition>.name应该只是一个字符串(没有分隔)。该字符串用作动画期间应用的类名。我想你想要的名字是slideInLeft

    // SlideTransition.ts
    return h('transition', {
      props: {
        // name: 'animated slideInLeft', ❌
        name: 'slideInLeft', ✅
        mode: 'out-in',
      },
    })
    
  2. 过渡样式文件 ( SlideTransition.scss) 应导入SlideTransition.ts,以便将样式应用于内容元素。

    // SlideTransition.ts
    import './SlideTransition.scss'
    
  3. 过渡样式应针对__TRANSITION_NAME__-enter-activeand __TRANSITION-NAME__-leave-active

    .slideInLeft {
      &-enter-active {
        animation: slideInLeft .30s;
      }
      &-leave-active {
        animation: slideInLeft .15s reverse;
      }
    }
    
  4. 必须添加/移除的默认插槽<transition>才能使动画生效,因此ModalSidePanel的渲染函数必须有条件地提供子元素而不是使用display:block/none. 还要确保props使用 Options API 声明您的:

    export const ModalSidePanel = defineComponent({
      props: {
        active: Boolean
      },
      setup(props) {
        return function render() {
          return h(
            SlideLeftTransition,
    
            // static child (no transition) ❌
            h('div', { style: { display: props.active ? 'block' : 'none' } }, '...'),
    
            // conditionally added ✅
            props.active && [ h('div', null, '...') ]
          )
        }
      }
    })    
    

演示


推荐阅读