u-transition.vue 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207
  1. <template>
  2. <view
  3. v-if="inited"
  4. class="u-transition"
  5. ref="u-transition"
  6. @tap="clickHandler"
  7. :class="classes"
  8. :style="[mergeStyle]"
  9. @touchmove="noop"
  10. >
  11. <slot />
  12. </view>
  13. </template>
  14. <script>
  15. import { props } from './props';
  16. import { mpMixin } from '../../libs/mixin/mpMixin';
  17. import { mixin } from '../../libs/mixin/mixin';
  18. import { addStyle } from '../../libs/function/index';
  19. // 组件的methods方法,由于内容较长,写在外部文件中通过mixin引入
  20. import transitionMixin from "./transitionMixin.js";
  21. /**
  22. * transition 动画组件
  23. * @description
  24. * @tutorial
  25. * @property {String} show 是否展示组件 (默认 false )
  26. * @property {String} mode 使用的动画模式 (默认 'fade' )
  27. * @property {String | Number} duration 动画的执行时间,单位ms (默认 '300' )
  28. * @property {String} timingFunction 使用的动画过渡函数 (默认 'ease-out' )
  29. * @property {Object} customStyle 自定义样式
  30. * @event {Function} before-enter 进入前触发
  31. * @event {Function} enter 进入中触发
  32. * @event {Function} after-enter 进入后触发
  33. * @event {Function} before-leave 离开前触发
  34. * @event {Function} leave 离开中触发
  35. * @event {Function} after-leave 离开后触发
  36. * @example
  37. */
  38. export default {
  39. name: 'u-transition',
  40. data() {
  41. return {
  42. inited: false, // 是否显示/隐藏组件
  43. viewStyle: {}, // 组件内部的样式
  44. status: '', // 记录组件动画的状态
  45. transitionEnded: false, // 组件是否结束的标记
  46. display: false, // 组件是否展示
  47. classes: '', // 应用的类名
  48. }
  49. },
  50. emits: ['click', 'beforeEnter', 'enter', 'afterEnter', 'beforeLeave', 'leave', 'afterLeave'],
  51. computed: {
  52. mergeStyle() {
  53. const { viewStyle, customStyle } = this
  54. return {
  55. // #ifndef APP-NVUE
  56. transitionDuration: `${this.duration}ms`,
  57. // display: `${this.display ? '' : 'none'}`,
  58. transitionTimingFunction: this.timingFunction,
  59. // #endif
  60. // 避免自定义样式影响到动画属性,所以写在viewStyle前面
  61. ...addStyle(customStyle),
  62. ...viewStyle
  63. }
  64. }
  65. },
  66. // 将mixin挂在到组件中,实际上为一个vue格式对象。
  67. mixins: [mpMixin, mixin, transitionMixin, props],
  68. watch: {
  69. show: {
  70. handler(newVal) {
  71. // vue和nvue分别执行不同的方法
  72. // #ifdef APP-NVUE
  73. newVal ? this.nvueEnter() : this.nvueLeave()
  74. // #endif
  75. // #ifndef APP-NVUE
  76. newVal ? this.vueEnter() : this.vueLeave()
  77. // #endif
  78. },
  79. // 表示同时监听初始化时的props的show的意思
  80. immediate: true
  81. }
  82. }
  83. }
  84. </script>
  85. <style lang="scss" scoped>
  86. /* #ifndef APP-NVUE */
  87. // vue版本动画相关的样式抽离在外部文件
  88. // @use './vue.ani-style.scss' as *;
  89. /**
  90. * vue版本动画内置的动画模式有如下:
  91. * fade:淡入
  92. * zoom:缩放
  93. * fade-zoom:缩放淡入
  94. * fade-up:上滑淡入
  95. * fade-down:下滑淡入
  96. * fade-left:左滑淡入
  97. * fade-right:右滑淡入
  98. * slide-up:上滑进入
  99. * slide-down:下滑进入
  100. * slide-left:左滑进入
  101. * slide-right:右滑进入
  102. */
  103. $u-zoom-scale: scale(0.95);
  104. .u-fade-enter-active,
  105. .u-fade-leave-active {
  106. transition-property: opacity;
  107. }
  108. .u-fade-enter,
  109. .u-fade-leave-to {
  110. opacity: 0
  111. }
  112. .u-fade-zoom-enter,
  113. .u-fade-zoom-leave-to {
  114. transform: $u-zoom-scale;
  115. opacity: 0;
  116. }
  117. .u-fade-zoom-enter-active,
  118. .u-fade-zoom-leave-active {
  119. transition-property: transform, opacity;
  120. }
  121. .u-fade-down-enter-active,
  122. .u-fade-down-leave-active,
  123. .u-fade-left-enter-active,
  124. .u-fade-left-leave-active,
  125. .u-fade-right-enter-active,
  126. .u-fade-right-leave-active,
  127. .u-fade-up-enter-active,
  128. .u-fade-up-leave-active {
  129. transition-property: opacity, transform;
  130. }
  131. .u-fade-up-enter,
  132. .u-fade-up-leave-to {
  133. transform: translate3d(0, 100%, 0);
  134. opacity: 0
  135. }
  136. .u-fade-down-enter,
  137. .u-fade-down-leave-to {
  138. transform: translate3d(0, -100%, 0);
  139. opacity: 0
  140. }
  141. .u-fade-left-enter,
  142. .u-fade-left-leave-to {
  143. transform: translate3d(-100%, 0, 0);
  144. opacity: 0
  145. }
  146. .u-fade-right-enter,
  147. .u-fade-right-leave-to {
  148. transform: translate3d(100%, 0, 0);
  149. opacity: 0
  150. }
  151. .u-slide-down-enter-active,
  152. .u-slide-down-leave-active,
  153. .u-slide-left-enter-active,
  154. .u-slide-left-leave-active,
  155. .u-slide-right-enter-active,
  156. .u-slide-right-leave-active,
  157. .u-slide-up-enter-active,
  158. .u-slide-up-leave-active {
  159. transition-property: transform;
  160. }
  161. .u-slide-up-enter,
  162. .u-slide-up-leave-to {
  163. transform: translate3d(0, 100%, 0)
  164. }
  165. .u-slide-down-enter,
  166. .u-slide-down-leave-to {
  167. transform: translate3d(0, -100%, 0)
  168. }
  169. .u-slide-left-enter,
  170. .u-slide-left-leave-to {
  171. transform: translate3d(-100%, 0, 0)
  172. }
  173. .u-slide-right-enter,
  174. .u-slide-right-leave-to {
  175. transform: translate3d(100%, 0, 0)
  176. }
  177. .u-zoom-enter-active,
  178. .u-zoom-leave-active {
  179. transition-property: transform
  180. }
  181. .u-zoom-enter,
  182. .u-zoom-leave-to {
  183. transform: $u-zoom-scale
  184. }
  185. /* #endif */
  186. .u-transition {}
  187. </style>