uni-events-helper-wx
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

152 lines
6.1 KiB

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