transition.js 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. // @ts-nocheck
  2. import { requestAnimationFrame } from '../common/utils';
  3. import { isObj } from '../common/validator';
  4. const getClassNames = (name) => ({
  5. enter: `van-${name}-enter van-${name}-enter-active enter-class enter-active-class`,
  6. 'enter-to': `van-${name}-enter-to van-${name}-enter-active enter-to-class enter-active-class`,
  7. leave: `van-${name}-leave van-${name}-leave-active leave-class leave-active-class`,
  8. 'leave-to': `van-${name}-leave-to van-${name}-leave-active leave-to-class leave-active-class`,
  9. });
  10. export function transition(showDefaultValue) {
  11. return Behavior({
  12. properties: {
  13. customStyle: String,
  14. // @ts-ignore
  15. show: {
  16. type: Boolean,
  17. value: showDefaultValue,
  18. observer: 'observeShow',
  19. },
  20. // @ts-ignore
  21. duration: {
  22. type: null,
  23. value: 300,
  24. observer: 'observeDuration',
  25. },
  26. name: {
  27. type: String,
  28. value: 'fade',
  29. },
  30. },
  31. data: {
  32. type: '',
  33. inited: false,
  34. display: false,
  35. },
  36. ready() {
  37. if (this.data.show === true) {
  38. this.observeShow(true, false);
  39. }
  40. },
  41. methods: {
  42. observeShow(value, old) {
  43. if (value === old) {
  44. return;
  45. }
  46. value ? this.enter() : this.leave();
  47. },
  48. enter() {
  49. if (this.enterFinishedPromise)
  50. return;
  51. this.enterFinishedPromise = new Promise((resolve) => {
  52. const { duration, name } = this.data;
  53. const classNames = getClassNames(name);
  54. const currentDuration = isObj(duration) ? duration.enter : duration;
  55. if (this.status === 'enter') {
  56. return;
  57. }
  58. this.status = 'enter';
  59. this.$emit('before-enter');
  60. requestAnimationFrame(() => {
  61. if (this.status !== 'enter') {
  62. return;
  63. }
  64. this.$emit('enter');
  65. this.setData({
  66. inited: true,
  67. display: true,
  68. classes: classNames.enter,
  69. currentDuration,
  70. });
  71. requestAnimationFrame(() => {
  72. if (this.status !== 'enter') {
  73. return;
  74. }
  75. this.transitionEnded = false;
  76. this.setData({ classes: classNames['enter-to'] });
  77. resolve();
  78. });
  79. });
  80. });
  81. },
  82. leave() {
  83. if (!this.enterFinishedPromise)
  84. return;
  85. this.enterFinishedPromise.then(() => {
  86. if (!this.data.display) {
  87. return;
  88. }
  89. const { duration, name } = this.data;
  90. const classNames = getClassNames(name);
  91. const currentDuration = isObj(duration) ? duration.leave : duration;
  92. this.status = 'leave';
  93. this.$emit('before-leave');
  94. requestAnimationFrame(() => {
  95. if (this.status !== 'leave') {
  96. return;
  97. }
  98. this.$emit('leave');
  99. this.setData({
  100. classes: classNames.leave,
  101. currentDuration,
  102. });
  103. requestAnimationFrame(() => {
  104. if (this.status !== 'leave') {
  105. return;
  106. }
  107. this.transitionEnded = false;
  108. setTimeout(() => {
  109. this.onTransitionEnd();
  110. this.enterFinishedPromise = null;
  111. }, currentDuration);
  112. this.setData({ classes: classNames['leave-to'] });
  113. });
  114. });
  115. });
  116. },
  117. onTransitionEnd() {
  118. if (this.transitionEnded) {
  119. return;
  120. }
  121. this.transitionEnded = true;
  122. this.$emit(`after-${this.status}`);
  123. const { show, display } = this.data;
  124. if (!show && display) {
  125. this.setData({ display: false });
  126. }
  127. },
  128. },
  129. });
  130. }