Nie możesz wybrać więcej, niż 25 tematów Tematy muszą się zaczynać od litery lub cyfry, mogą zawierać myślniki ('-') i mogą mieć do 35 znaków.
 
 
 

165 wiersze
6.5 KiB

  1. // 定义一个一定时间后自动成功的promise,让调用nextTick方法处,进入下一个then方法
  2. const waitTick = () => new Promise(resolve => setTimeout(resolve, 1000 / 50))
  3. // nvue动画模块实现细节抽离在外部文件
  4. // #ifdef APP-NVUE
  5. import animationMap from './nvue-ani-map.js'
  6. // #endif
  7. // #ifndef APP-NVUE
  8. // 定义类名,通过给元素动态切换类名,赋予元素一定的css动画样式
  9. const getClassNames = (name) => ({
  10. enter: `u-${name}-enter u-${name}-enter-active`,
  11. 'enter-to': `u-${name}-enter-to u-${name}-enter-active`,
  12. leave: `u-${name}-leave u-${name}-leave-active`,
  13. 'leave-to': `u-${name}-leave-to u-${name}-leave-active`
  14. })
  15. // #endif
  16. // #ifdef APP-NVUE
  17. // 引入nvue(weex)的animation动画模块,文档见:
  18. // https://weex.apache.org/zh/docs/modules/animation.html#transition
  19. const animation = uni.requireNativePlugin('animation')
  20. const getStyle = (name) => animationMap[name]
  21. // #endif
  22. import { nextTick } from 'vue'
  23. import { sleep } from '../../libs/function/index';
  24. export default {
  25. methods: {
  26. // 组件被点击发出事件
  27. clickHandler() {
  28. this.$emit('click')
  29. },
  30. // #ifndef APP-NVUE
  31. // vue版本的组件进场处理
  32. async vueEnter() {
  33. // 动画进入时的类名
  34. const classNames = getClassNames(this.mode)
  35. // 定义状态和发出动画进入前事件
  36. this.status = 'enter'
  37. this.$emit('beforeEnter')
  38. this.inited = true
  39. this.display = true
  40. this.classes = classNames.enter
  41. await nextTick();
  42. {
  43. // https://github.com/umicro/uView2.0/issues/545
  44. await sleep(20)
  45. // 标识动画尚未结束
  46. this.$emit('enter')
  47. this.transitionEnded = false
  48. // 组件动画进入后触发的事件
  49. this.$emit('afterEnter')
  50. // 赋予组件enter-to类名
  51. this.classes = classNames['enter-to']
  52. }
  53. },
  54. // 动画离场处理
  55. async vueLeave() {
  56. // 如果不是展示状态,无需执行逻辑
  57. if (!this.display) return
  58. const classNames = getClassNames(this.mode)
  59. // 标记离开状态和发出事件
  60. this.status = 'leave'
  61. this.$emit('beforeLeave')
  62. // 获得类名
  63. this.classes = classNames.leave
  64. await nextTick();
  65. {
  66. // 动画正在离场的状态
  67. this.transitionEnded = false
  68. this.$emit('leave')
  69. // 组件执行动画,到了执行的执行时间后,执行一些额外处理
  70. setTimeout(this.onTransitionEnd, this.duration)
  71. this.classes = classNames['leave-to']
  72. }
  73. },
  74. // #endif
  75. // #ifdef APP-NVUE
  76. // nvue版本动画进场
  77. async nvueEnter() {
  78. // 获得样式的名称
  79. const currentStyle = getStyle(this.mode) || getStyle('none')
  80. // 组件动画状态和发出事件
  81. this.status = 'enter'
  82. this.$emit('beforeEnter')
  83. // 展示生成组件元素
  84. this.inited = true
  85. this.display = true
  86. // 在nvue安卓上,由于渲染速度慢,在弹窗,键盘,日历等组件中,渲染其中的内容需要时间
  87. // 导致出现弹窗卡顿,这里让其一开始为透明状态,等一定时间渲染完成后,再让其隐藏起来,再让其按正常逻辑出现
  88. // none 模式为页面内常驻展示,不需要预置透明
  89. this.viewStyle = this.mode === 'none' ? { opacity: 1 } : {
  90. opacity: 0
  91. }
  92. // 等待弹窗内容渲染完成
  93. await nextTick();
  94. {
  95. // 合并样式
  96. this.viewStyle = currentStyle.enter
  97. Promise.resolve()
  98. .then(waitTick)
  99. .then(() => {
  100. // 组件开始进入前的事件
  101. this.$emit('enter')
  102. // nvue的transition动画模块需要通过ref调用组件,注意此处的ref不同于vue的this.$refs['u-transition']用法
  103. animation.transition(this.$refs['u-transition'].ref, {
  104. styles: currentStyle['enter-to'],
  105. duration: this.mode === 'none' ? 0 : this.duration,
  106. timingFunction: this.timingFunction,
  107. needLayout: false,
  108. delay: 0
  109. }, () => {
  110. // 动画执行完毕,发出事件
  111. this.$emit('afterEnter')
  112. })
  113. })
  114. .catch(() => {})
  115. }
  116. },
  117. nvueLeave() {
  118. if (!this.display) {
  119. return
  120. }
  121. const currentStyle = getStyle(this.mode) || getStyle('none')
  122. // 定义状态和事件
  123. this.status = 'leave'
  124. this.$emit('beforeLeave')
  125. // 合并样式
  126. this.viewStyle = currentStyle.leave
  127. // 放到promise中处理执行过程
  128. Promise.resolve()
  129. .then(waitTick) // 等待几十ms
  130. .then(() => {
  131. this.transitionEnded = false
  132. // 动画正在离场的状态
  133. this.$emit('leave')
  134. animation.transition(this.$refs['u-transition'].ref, {
  135. styles: currentStyle['leave-to'],
  136. duration: this.mode === 'none' ? 0 : this.duration,
  137. timingFunction: this.timingFunction,
  138. needLayout: false,
  139. delay: 0
  140. }, () => {
  141. this.onTransitionEnd()
  142. })
  143. })
  144. .catch(() => {})
  145. },
  146. // #endif
  147. // 完成过渡后触发
  148. onTransitionEnd() {
  149. // 如果已经是结束的状态,无需再处理
  150. if (this.transitionEnded) return
  151. this.transitionEnded = true
  152. // 发出组件动画执行后的事件
  153. this.$emit(this.status === 'leave' ? 'afterLeave' : 'afterEnter')
  154. if (!this.show && this.display) {
  155. this.display = false
  156. this.inited = false
  157. }
  158. }
  159. }
  160. }