// [z-paging]nvue独有部分模块 import u from '.././z-paging-utils' import c from '.././z-paging-constant' import Enum from '.././z-paging-enum' // #ifdef APP-NVUE const weexAnimation = weex.requireModule('animation'); // #endif export default { props: { // #ifdef APP-NVUE // nvue中修改列表类型,可选值有list、waterfall和scroller,默认为list nvueListIs: { type: String, default: u.gc('nvueListIs', 'list') }, // nvue waterfall配置,仅在nvue中且nvueListIs=waterfall时有效,配置参数详情参见:https://uniapp.dcloud.io/component/waterfall nvueWaterfallConfig: { type: Object, default: u.gc('nvueWaterfallConfig', {}) }, // nvue 控制是否回弹效果,iOS不支持动态修改 nvueBounce: { type: Boolean, default: u.gc('nvueBounce', true) }, // nvue中通过代码滚动到顶部/底部时,是否加快动画效果(无滚动动画时无效),默认为否 nvueFastScroll: { type: Boolean, default: u.gc('nvueFastScroll', false) }, // nvue中list的id nvueListId: { type: String, default: u.gc('nvueListId', '') }, // nvue中refresh组件的样式 nvueRefresherStyle: { type: Object, default: u.gc('nvueRefresherStyle', {}) }, // nvue中是否按分页模式(类似竖向swiper)显示List,默认为false nvuePagingEnabled: { type: Boolean, default: u.gc('nvuePagingEnabled', false) }, // 是否隐藏nvue列表底部的tagView,此view用于标识滚动到底部位置,若隐藏则滚动到底部功能将失效,在nvue中实现吸顶+swiper功能时需将最外层z-paging的此属性设置为true。默认为否 hideNvueBottomTag: { type: Boolean, default: u.gc('hideNvueBottomTag', false) }, // nvue中控制onscroll事件触发的频率:表示两次onscroll事件之间列表至少滚动了10px。注意,将该值设置为较小的数值会提高滚动事件采样的精度,但同时也会降低页面的性能 offsetAccuracy: { type: Number, default: u.gc('offsetAccuracy', 10) }, // #endif }, data() { return { nRefresherLoading: false, nListIsDragging: false, nShowBottom: true, nFixFreezing: false, nShowRefresherReveal: false, nLoadingMoreFixedHeight: false, nShowRefresherRevealHeight: 0, nOldShowRefresherRevealHeight: -1, nRefresherWidth: u.rpx2px(750), nF2Opacity: 0 } }, computed: { // #ifdef APP-NVUE nScopedSlots() { // #ifdef VUE2 return this.$scopedSlots; // #endif // #ifdef VUE3 return null; // #endif }, nWaterfallColumnCount() { if (this.finalNvueListIs !== 'waterfall') return 0; return this._nGetWaterfallConfig('column-count', 2); }, nWaterfallColumnWidth() { return this._nGetWaterfallConfig('column-width', 'auto'); }, nWaterfallColumnGap() { return this._nGetWaterfallConfig('column-gap', 'normal'); }, nWaterfallLeftGap() { return this._nGetWaterfallConfig('left-gap', 0); }, nWaterfallRightGap() { return this._nGetWaterfallConfig('right-gap', 0); }, nViewIs() { const is = this.finalNvueListIs; return is === 'scroller' || is === 'view' ? 'view' : is === 'waterfall' ? 'header' : 'cell'; }, nSafeAreaBottomHeight() { return this.safeAreaInsetBottom ? this.safeAreaBottom : 0; }, finalNvueListIs() { if (this.usePageScroll) return 'view'; const nvueListIsLowerCase = this.nvueListIs.toLowerCase(); if (['list','waterfall','scroller'].indexOf(nvueListIsLowerCase) !== -1) return nvueListIsLowerCase; return 'list'; }, finalNvueSuperListIs() { return this.usePageScroll ? 'view' : 'scroller'; }, finalNvueRefresherEnabled() { return this.finalNvueListIs !== 'view' && this.finalRefresherEnabled && !this.nShowRefresherReveal && !this.useChatRecordMode; }, // #endif }, mounted(){ // #ifdef APP-NVUE //旋转屏幕时更新宽度 uni.onWindowResize((res) => { // this._nUpdateRefresherWidth(); }) // #endif }, methods: { // #ifdef APP-NVUE // 列表滚动时触发 _nOnScroll(e) { this.$emit('scroll', e); const contentOffsetY = -e.contentOffset.y; this.oldScrollTop = contentOffsetY; this.nListIsDragging = e.isDragging; this._checkShouldShowBackToTop(contentOffsetY, contentOffsetY - 1); }, // 列表滚动结束 _nOnScrollend(e) { this.$emit('scrollend', e); // 判断是否滚动到顶部了 if (e?.contentOffset?.y >= 0) { this._emitScrollEvent('scrolltoupper'); } // 判断是否滚动到底部了 this._getNodeClientRect('.zp-n-list').then(node => { if (node) { if (e?.contentSize?.height + e?.contentOffset?.y <= node[0].height) { this._emitScrollEvent('scrolltolower'); } } }) }, // 下拉刷新刷新中 _nOnRrefresh() { if (this.nShowRefresherReveal) return; // 进入刷新状态 this.nRefresherLoading = true; if (this.refresherStatus === Enum.Refresher.GoF2) { this._handleGoF2(); this.$nextTick(() => { this._nRefresherEnd(); }) } else { this.refresherStatus = Enum.Refresher.Loading; this._doRefresherLoad(); } }, // 下拉刷新下拉中 _nOnPullingdown(e) { if (this.refresherStatus === Enum.Refresher.Loading || (this.isIos && !this.nListIsDragging)) return; this._emitTouchmove(e); let { viewHeight, pullingDistance } = e; // 更新下拉刷新状态 // 下拉刷新距离超过阈值 if (pullingDistance >= viewHeight) { // 如果开启了下拉进入二楼并且下拉刷新距离超过进入二楼阈值,则当前下拉刷新状态为松手进入二楼,否则为松手立即刷新 // (pullingDistance - viewHeight) + this.finalRefresherThreshold 不等同于pullingDistance,此处是为了兼容不同平台下拉相同距离pullingDistance不一致的问题,pullingDistance仅与viewHeight互相关联 this.refresherStatus = this.refresherF2Enabled && (pullingDistance - viewHeight) + this.finalRefresherThreshold >= this.finalRefresherF2Threshold ? Enum.Refresher.GoF2 : Enum.Refresher.ReleaseToRefresh; } else { // 下拉刷新距离未超过阈值,显示默认状态 this.refresherStatus = Enum.Refresher.Default; } }, // 下拉刷新结束 _nRefresherEnd(doEnd = true) { if (doEnd) { this._nDoRefresherEndAnimation(0, -this.nShowRefresherRevealHeight); !this.usePageScroll && this.$refs['zp-n-list'].resetLoadmore(); this.nRefresherLoading = false; } }, // 执行主动触发下拉刷新动画 _nDoRefresherEndAnimation(height, translateY, animate = true, checkStack = true) { // 清除下拉刷新相关timeout this._cleanRefresherCompleteTimeout(); this._cleanRefresherEndTimeout(); if (!this.finalShowRefresherWhenReload) { // 如果reload不需要自动展示下拉刷新view,则在complete duration结束后再把下拉刷新状态设置回默认 this.refresherEndTimeout = u.delay(() => { this.refresherStatus = Enum.Refresher.Default; }, this.refresherCompleteDuration); return; } // 用户处理用户在短时间内多次调用reload的情况,此时下拉刷新view不需要重复显示,只需要保证最后一次reload对应的请求结束后收回下拉刷新view即可 const stackCount = this.refresherRevealStackCount; if (height === 0 && checkStack) { this.refresherRevealStackCount --; if (stackCount > 1) return; this.refresherEndTimeout = u.delay(() => { this.refresherStatus = Enum.Refresher.Default; }, this.refresherCompleteDuration); } if (stackCount > 1) { this.refresherStatus = Enum.Refresher.Loading; } const duration = animate ? 200 : 0; if (this.nOldShowRefresherRevealHeight !== height) { if (height > 0) { this.nShowRefresherReveal = true; } // 展示下拉刷新view weexAnimation.transition(this.$refs['zp-n-list-refresher-reveal'], { styles: { height: `${height}px`, transform: `translateY(${translateY}px)`, }, duration, timingFunction: 'linear', needLayout: true, delay: 0 }) } u.delay(() => { if (animate) { this.nShowRefresherReveal = height > 0; } }, duration > 0 ? duration - 60 : 0); this.nOldShowRefresherRevealHeight = height; }, // 滚动到底部加载更多 _nOnLoadmore() { if (this.nShowRefresherReveal || !this.totalData.length) return; this.useChatRecordMode ? this.doChatRecordLoadMore() : this._onLoadingMore('toBottom'); }, // 获取nvue waterfall单项配置 _nGetWaterfallConfig(key, defaultValue) { return this.nvueWaterfallConfig[key] || defaultValue; }, // 更新nvue 下拉刷新view容器的宽度 _nUpdateRefresherWidth() { u.delay(() => { this.$nextTick(()=>{ this._getNodeClientRect('.zp-n-list').then(node => { if (node) { this.nRefresherWidth = node[0].width || this.nRefresherWidth; } }) }) }) } // #endif } }