nvue.js 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. // [z-paging]nvue独有部分模块
  2. import u from '.././z-paging-utils'
  3. import c from '.././z-paging-constant'
  4. import Enum from '.././z-paging-enum'
  5. // #ifdef APP-NVUE
  6. const weexAnimation = weex.requireModule('animation');
  7. // #endif
  8. const ZPNvue = {
  9. props: {
  10. //nvue中修改列表类型,可选值有list、waterfall和scroller,默认为list
  11. nvueListIs: {
  12. type: String,
  13. default: u.gc('nvueListIs', 'list')
  14. },
  15. //nvue waterfall配置,仅在nvue中且nvueListIs=waterfall时有效,配置参数详情参见:https://uniapp.dcloud.io/component/waterfall
  16. nvueWaterfallConfig: {
  17. type: Object,
  18. default: function() {
  19. return u.gc('nvueWaterfallConfig', {});
  20. }
  21. },
  22. //nvue 控制是否回弹效果,iOS不支持动态修改
  23. nvueBounce: {
  24. type: Boolean,
  25. default: u.gc('nvueBounce', true)
  26. },
  27. //nvue中通过代码滚动到顶部/底部时,是否加快动画效果(无滚动动画时无效),默认为否
  28. nvueFastScroll: {
  29. type: Boolean,
  30. default: u.gc('nvueFastScroll', false)
  31. },
  32. //nvue中list的id
  33. nvueListId: {
  34. type: String,
  35. default: u.gc('nvueListId', '')
  36. },
  37. //nvue中refresh组件的样式
  38. nvueRefresherStyle: {
  39. type: Object,
  40. default: function() {
  41. return u.gc('nvueRefresherStyle', {});
  42. }
  43. },
  44. //nvue中是否按分页模式(类似竖向swiper)显示List,默认为false
  45. nvuePagingEnabled: {
  46. type: Boolean,
  47. default: u.gc('nvuePagingEnabled', false)
  48. },
  49. //是否隐藏nvue列表底部的tagView,此view用于标识滚动到底部位置,若隐藏则滚动到底部功能将失效,在nvue中实现吸顶+swiper功能时需将最外层z-paging的此属性设置为true。默认为否
  50. hideNvueBottomTag: {
  51. type: Boolean,
  52. default: u.gc('hideNvueBottomTag', false)
  53. },
  54. },
  55. data() {
  56. return {
  57. nRefresherLoading: false,
  58. nListIsDragging: false,
  59. nShowBottom: true,
  60. nFixFreezing: false,
  61. nShowRefresherReveal: false,
  62. nIsFirstPageAndNoMore: false,
  63. nFirstPageAndNoMoreChecked: false,
  64. nLoadingMoreFixedHeight: false,
  65. nShowRefresherRevealHeight: 0,
  66. nRefresherWidth: uni.upx2px(750),
  67. }
  68. },
  69. watch: {
  70. nIsFirstPageAndNoMore: {
  71. handler(newVal) {
  72. const cellStyle = !this.useChatRecordMode || newVal ? {} : {transform: 'rotate(180deg)'};
  73. this.$emit('update:cellStyle', cellStyle);
  74. },
  75. immediate: true
  76. }
  77. },
  78. computed: {
  79. // #ifdef APP-NVUE
  80. nWaterfallColumnCount() {
  81. if (this.finalNvueListIs !== 'waterfall') return 0;
  82. return this._nGetWaterfallConfig('column-count', 2);
  83. },
  84. nWaterfallColumnWidth() {
  85. return this._nGetWaterfallConfig('column-width', 'auto');
  86. },
  87. nWaterfallColumnGap() {
  88. return this._nGetWaterfallConfig('column-gap', 'normal');
  89. },
  90. nWaterfallLeftGap() {
  91. return this._nGetWaterfallConfig('left-gap', 0);
  92. },
  93. nWaterfallRightGap() {
  94. return this._nGetWaterfallConfig('right-gap', 0);
  95. },
  96. nViewIs() {
  97. const is = this.finalNvueListIs;
  98. return is === 'scroller' || is === 'view' ? 'view' : is === 'waterfall' ? 'header' : 'cell';
  99. },
  100. nSafeAreaBottomHeight() {
  101. return this.safeAreaInsetBottom ? this.safeAreaBottom : 0;
  102. },
  103. finalNvueListIs() {
  104. if (this.usePageScroll) return 'view';
  105. const nvueListIsLowerCase = this.nvueListIs.toLowerCase();
  106. if (['list','waterfall','scroller'].indexOf(nvueListIsLowerCase) !== -1) {
  107. return nvueListIsLowerCase;
  108. }
  109. return 'list';
  110. },
  111. finalNvueSuperListIs() {
  112. return this.usePageScroll ? 'view' : 'scroller';
  113. },
  114. finalNvueRefresherEnabled() {
  115. return this.finalNvueListIs !== 'view' && this.finalRefresherEnabled && !this.nShowRefresherReveal && !this.useChatRecordMode;
  116. },
  117. // #endif
  118. },
  119. methods: {
  120. // #ifdef APP-NVUE
  121. //列表滚动时触发
  122. _nOnScroll(e) {
  123. this.$emit('scroll', e);
  124. const contentOffsetY = -e.contentOffset.y;
  125. this.oldScrollTop = contentOffsetY;
  126. this.nListIsDragging = e.isDragging;
  127. this._checkShouldShowBackToTop(contentOffsetY, contentOffsetY - 1);
  128. },
  129. //列表开始触摸
  130. _nTouchstart() {
  131. this._handleListTouchstart();
  132. },
  133. //下拉刷新刷新中
  134. _nOnRrefresh() {
  135. if (this.nShowRefresherReveal) return;
  136. this.nRefresherLoading = true;
  137. this.refresherStatus = Enum.Refresher.Loading;
  138. this._doRefresherLoad();
  139. },
  140. //下拉刷新下拉中
  141. _nOnPullingdown(e) {
  142. if (this.refresherStatus === Enum.Refresher.Loading || (this.isIos && !this.nListIsDragging)) return;
  143. this._emitTouchmove(e);
  144. const viewHeight = e.viewHeight;
  145. const pullingDis = e.pullingDistance;
  146. this.refresherStatus = pullingDis >= viewHeight ? Enum.Refresher.ReleaseToRefresh : Enum.Refresher.Default;
  147. },
  148. //下拉刷新结束
  149. _nRefresherEnd(doEnd=true) {
  150. if (doEnd) {
  151. this._nDoRefresherEndAnimation(0, -this.nShowRefresherRevealHeight);
  152. !this.usePageScroll && this.$refs['zp-n-list'].resetLoadmore();
  153. this.nRefresherLoading = false;
  154. }
  155. this.$nextTick(() => {
  156. setTimeout(()=> {
  157. this.nShowBottom = true;
  158. }, 10);
  159. })
  160. },
  161. //执行主动触发下拉刷新动画
  162. _nDoRefresherEndAnimation(height, translateY, animate = true, checkStack = true) {
  163. this._cleanRefresherCompleteTimeout();
  164. this._cleanRefresherEndTimeout();
  165. if (!this.finalShowRefresherWhenReload) {
  166. this.refresherEndTimeout = setTimeout(() => {
  167. this.refresherStatus = Enum.Refresher.Default;
  168. }, this.refresherCompleteDuration);
  169. return;
  170. }
  171. const stackCount = this.refresherRevealStackCount;
  172. if (height === 0 && checkStack) {
  173. this.refresherRevealStackCount--;
  174. if (stackCount > 1) return;
  175. this.refresherEndTimeout = setTimeout(() => {
  176. this.refresherStatus = Enum.Refresher.Default;
  177. }, this.refresherCompleteDuration);
  178. }
  179. if (stackCount > 1) {
  180. this.refresherStatus = Enum.Refresher.Loading;
  181. }
  182. const duration = animate ? 180 : 0;
  183. weexAnimation.transition(this.$refs['zp-n-list-refresher-reveal'], {
  184. styles: {
  185. height: `${height}px`,
  186. transform: `translateY(${translateY}px)`,
  187. },
  188. duration: duration,
  189. timingFunction: 'linear',
  190. needLayout: true,
  191. delay: 0
  192. })
  193. setTimeout(() => {
  194. if (animate) {
  195. this.nShowRefresherReveal = height > 0;
  196. }
  197. }, duration > 0 ? duration - 100 : 0);
  198. },
  199. //滚动到底部加载更多
  200. _nOnLoadmore() {
  201. if (this.nShowRefresherReveal || !this.totalData.length) return;
  202. this.useChatRecordMode ? this.doChatRecordLoadMore() : this._onLoadingMore('toBottom');
  203. },
  204. //获取nvue waterfall单项配置
  205. _nGetWaterfallConfig(key, defaultValue) {
  206. return this.nvueWaterfallConfig[key] || defaultValue;
  207. },
  208. //更新nvue 下拉刷新view容器的宽度
  209. _nUpdateRefresherWidth() {
  210. setTimeout(() => {
  211. this.$nextTick(()=>{
  212. this._getNodeClientRect('.zp-n-list').then(node => {
  213. if (node) {
  214. const nodeWidth = node[0].width;
  215. if (nodeWidth) {
  216. this.nRefresherWidth = nodeWidth;
  217. }
  218. }
  219. })
  220. })
  221. },c.delayTime)
  222. }
  223. // #endif
  224. }
  225. }
  226. export default ZPNvue;