transition.js 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. import config from '../common/config';
  2. const { prefix } = config;
  3. export default function transition() {
  4. return Behavior({
  5. properties: {
  6. visible: {
  7. type: Boolean,
  8. value: null,
  9. observer: 'watchVisible',
  10. },
  11. appear: Boolean,
  12. name: {
  13. type: String,
  14. value: 'fade',
  15. },
  16. durations: {
  17. type: Number,
  18. optionalTypes: [Array],
  19. },
  20. },
  21. data: {
  22. transitionClass: '',
  23. transitionDurations: 300,
  24. className: '',
  25. realVisible: false,
  26. },
  27. created() {
  28. this.status = '';
  29. this.transitionT = 0;
  30. },
  31. attached() {
  32. this.durations = this.getDurations();
  33. if (this.data.visible) {
  34. this.enter();
  35. }
  36. this.inited = true;
  37. },
  38. detached() {
  39. clearTimeout(this.transitionT);
  40. },
  41. methods: {
  42. watchVisible(curr, prev) {
  43. if (this.inited && curr !== prev) {
  44. curr ? this.enter() : this.leave();
  45. }
  46. },
  47. getDurations() {
  48. const { durations } = this.data;
  49. if (Array.isArray(durations)) {
  50. return durations.map((item) => Number(item));
  51. }
  52. return [Number(durations), Number(durations)];
  53. },
  54. enter() {
  55. const { name } = this.data;
  56. const [duration] = this.durations;
  57. this.status = 'entering';
  58. this.setData({
  59. realVisible: true,
  60. transitionClass: `${prefix}-${name}-enter ${prefix}-${name}-enter-active`,
  61. });
  62. setTimeout(() => {
  63. this.setData({
  64. transitionClass: `${prefix}-${name}-enter-active ${prefix}-${name}-enter-to`,
  65. });
  66. }, 30);
  67. if (typeof duration === 'number' && duration > 0) {
  68. this.transitionT = setTimeout(this.entered.bind(this), duration + 30);
  69. }
  70. },
  71. entered() {
  72. this.customDuration = false;
  73. clearTimeout(this.transitionT);
  74. this.status = 'entered';
  75. this.setData({
  76. transitionClass: '',
  77. });
  78. },
  79. leave() {
  80. const { name } = this.data;
  81. const [, duration] = this.durations;
  82. this.status = 'leaving';
  83. this.setData({
  84. transitionClass: `${prefix}-${name}-leave ${prefix}-${name}-leave-active`,
  85. });
  86. clearTimeout(this.transitionT);
  87. setTimeout(() => {
  88. this.setData({
  89. transitionClass: `${prefix}-${name}-leave-active ${prefix}-${name}-leave-to`,
  90. });
  91. }, 30);
  92. if (typeof duration === 'number' && duration > 0) {
  93. this.customDuration = true;
  94. this.transitionT = setTimeout(this.leaved.bind(this), duration + 30);
  95. }
  96. },
  97. leaved() {
  98. this.customDuration = false;
  99. this.triggerEvent('leaved');
  100. clearTimeout(this.transitionT);
  101. this.status = 'leaved';
  102. this.setData({
  103. transitionClass: '',
  104. });
  105. },
  106. onTransitionEnd() {
  107. if (this.customDuration) {
  108. return;
  109. }
  110. clearTimeout(this.transitionT);
  111. if (this.status === 'entering' && this.data.visible) {
  112. this.entered();
  113. }
  114. else if (this.status === 'leaving' && !this.data.visible) {
  115. this.leaved();
  116. this.setData({
  117. realVisible: false,
  118. });
  119. }
  120. },
  121. },
  122. });
  123. }