nvue.js 7.6 KB

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