transition.vue 1.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677
  1. <template>
  2. <transition v-on="on">
  3. <slot />
  4. </transition>
  5. </template>
  6. <script>
  7. import { defineComponent } from 'vue-demi';
  8. import { inlineStyle } from '../../utils/dom';
  9. export default defineComponent({
  10. name: 'mCollapseTransition',
  11. props: {
  12. duration: {
  13. type: Number,
  14. default: 0.5,
  15. },
  16. animate: {
  17. type: String,
  18. default: 'ease',
  19. }
  20. },
  21. setup(props) {
  22. const getStyle = (obj) => {
  23. if (obj.currentStyle) {
  24. return obj.currentStyle;
  25. }
  26. return obj.currentStyle || getComputedStyle(obj);
  27. }
  28. const transition = (config) => {
  29. const style = {
  30. transition: `all ${config.duration}s ${config.animate}`,
  31. overflow: 'hidden',
  32. };
  33. return {
  34. beforeEnter(el) {
  35. el.dataset.paddingTop = getStyle(el).paddingTop; // el.style.paddingTop
  36. el.dataset.paddingBottom = getStyle(el).paddingBottom; // el.style.paddingBottom
  37. inlineStyle(
  38. el,
  39. Object.assign(style, { height: 0 }),
  40. );
  41. },
  42. enter(el) {
  43. setTimeout(() => {
  44. inlineStyle(el, {
  45. height: `${el.scrollHeight}px`,
  46. paddingTop: el.dataset.paddingTop,
  47. paddingBottom: el.dataset.paddingBottom,
  48. });
  49. }, 0);
  50. },
  51. afterEnter(el) {
  52. inlineStyle(el, { height: '', overflow: '' });
  53. },
  54. beforeLeave(el) {
  55. inlineStyle(el, Object.assign(style, {
  56. height: `${el.scrollHeight}px`,
  57. overflow: '',
  58. }));
  59. },
  60. leave(el) {
  61. setTimeout(() => {
  62. inlineStyle(el, { height: 0, overflow: 'hidden' });
  63. }, 0);
  64. },
  65. afterLeave(el) {
  66. inlineStyle(el, { height: 0, overflow: 'hidden' });
  67. },
  68. };
  69. }
  70. return {
  71. on: transition(props)
  72. }
  73. }
  74. })
  75. </script>