first commit
This commit is contained in:
108
components/z-paging/js/modules/back-to-top.js
Normal file
108
components/z-paging/js/modules/back-to-top.js
Normal file
@@ -0,0 +1,108 @@
|
||||
// [z-paging]点击返回顶部view模块
|
||||
import u from '.././z-paging-utils'
|
||||
|
||||
const ZPBackToTop = {
|
||||
props: {
|
||||
//自动显示点击返回顶部按钮,默认为否
|
||||
autoShowBackToTop: {
|
||||
type: Boolean,
|
||||
default: u.gc('autoShowBackToTop', false)
|
||||
},
|
||||
//点击返回顶部按钮显示/隐藏的阈值(滚动距离),单位为px,默认为400rpx
|
||||
backToTopThreshold: {
|
||||
type: [Number, String],
|
||||
default: u.gc('backToTopThreshold', '400rpx')
|
||||
},
|
||||
//点击返回顶部按钮的自定义图片地址,默认使用z-paging内置的图片
|
||||
backToTopImg: {
|
||||
type: String,
|
||||
default: u.gc('backToTopImg', '')
|
||||
},
|
||||
//点击返回顶部按钮返回到顶部时是否展示过渡动画,默认为是
|
||||
backToTopWithAnimate: {
|
||||
type: Boolean,
|
||||
default: u.gc('backToTopWithAnimate', true)
|
||||
},
|
||||
//点击返回顶部按钮与底部的距离,注意添加单位px或rpx,默认为160rpx
|
||||
backToTopBottom: {
|
||||
type: [Number, String],
|
||||
default: u.gc('backToTopBottom', '160rpx')
|
||||
},
|
||||
//点击返回顶部按钮的自定义样式
|
||||
backToTopStyle: {
|
||||
type: Object,
|
||||
default: function() {
|
||||
return u.gc('backToTopStyle', {});
|
||||
},
|
||||
},
|
||||
//iOS点击顶部状态栏、安卓双击标题栏时,滚动条返回顶部,只支持竖向,默认为是
|
||||
enableBackToTop: {
|
||||
type: Boolean,
|
||||
default: u.gc('enableBackToTop', true)
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
backToTopClass: 'zp-back-to-top zp-back-to-top-hide',
|
||||
lastBackToTopShowTime: 0,
|
||||
showBackToTopClass: false,
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
finalEnableBackToTop() {
|
||||
return this.usePageScroll ? false : this.enableBackToTop;
|
||||
},
|
||||
finalBackToTopThreshold() {
|
||||
return u.convertTextToPx(this.backToTopThreshold);
|
||||
},
|
||||
finalBackToTopStyle() {
|
||||
let tempBackToTopStyle = this.backToTopStyle;
|
||||
if (!tempBackToTopStyle.bottom) {
|
||||
tempBackToTopStyle.bottom = this.windowBottom + u.convertTextToPx(this.backToTopBottom) + 'px';
|
||||
}
|
||||
if(!tempBackToTopStyle.position){
|
||||
tempBackToTopStyle.position = this.usePageScroll ? 'fixed': 'absolute';
|
||||
}
|
||||
return tempBackToTopStyle;
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
//点击返回顶部
|
||||
_backToTopClick() {
|
||||
!this.backToTopWithAnimate && this._checkShouldShowBackToTop(1, 0);
|
||||
this.scrollToTop(this.backToTopWithAnimate);
|
||||
},
|
||||
//判断是否要显示返回顶部按钮
|
||||
_checkShouldShowBackToTop(newVal, oldVal) {
|
||||
if (!this.autoShowBackToTop) {
|
||||
this.showBackToTopClass = false;
|
||||
return;
|
||||
}
|
||||
if (newVal !== oldVal) {
|
||||
if (newVal > this.finalBackToTopThreshold) {
|
||||
if (!this.showBackToTopClass) {
|
||||
this.showBackToTopClass = true;
|
||||
this.lastBackToTopShowTime = new Date().getTime();
|
||||
setTimeout(() => {
|
||||
this.backToTopClass = 'zp-back-to-top zp-back-to-top-show';
|
||||
}, 300)
|
||||
}
|
||||
} else {
|
||||
if (this.showBackToTopClass) {
|
||||
const currentTime = new Date().getTime();
|
||||
let dalayTime = 300;
|
||||
if(currentTime - this.lastBackToTopShowTime < 500){
|
||||
dalayTime = 0;
|
||||
}
|
||||
this.backToTopClass = 'zp-back-to-top zp-back-to-top-hide';
|
||||
setTimeout(() => {
|
||||
this.showBackToTopClass = false;
|
||||
}, dalayTime)
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
export default ZPBackToTop;
|
||||
732
components/z-paging/js/modules/data-handle.js
Normal file
732
components/z-paging/js/modules/data-handle.js
Normal file
@@ -0,0 +1,732 @@
|
||||
// [z-paging]数据处理模块
|
||||
import u from '.././z-paging-utils'
|
||||
import c from '.././z-paging-constant'
|
||||
import Enum from '.././z-paging-enum'
|
||||
import interceptor from '../z-paging-interceptor'
|
||||
|
||||
const ZPData = {
|
||||
props: {
|
||||
//自定义初始的pageNo,默认为1
|
||||
defaultPageNo: {
|
||||
type: [Number, String],
|
||||
default: u.gc('defaultPageNo', 1),
|
||||
observer: function(newVal, oldVal) {
|
||||
this.pageNo = newVal;
|
||||
},
|
||||
},
|
||||
//自定义pageSize,默认为10
|
||||
defaultPageSize: {
|
||||
type: [Number, String],
|
||||
default: u.gc('defaultPageSize', 10),
|
||||
validator: (value) => {
|
||||
if(value <= 0) u.consoleErr('default-page-size必须大于0!');
|
||||
return value > 0;
|
||||
}
|
||||
},
|
||||
//为保证数据一致,设置当前tab切换时的标识key,并在complete中传递相同key,若二者不一致,则complete将不会生效
|
||||
dataKey: {
|
||||
type: [Number, String, Object],
|
||||
default: function() {
|
||||
return u.gc('dataKey', null);
|
||||
},
|
||||
},
|
||||
//自动注入的list名,可自动修改父view(包含ref="paging")中对应name的list值
|
||||
autowireListName: {
|
||||
type: String,
|
||||
default: function() {
|
||||
return u.gc('autowireListName', '');
|
||||
},
|
||||
},
|
||||
//自动注入的query名,可自动调用父view(包含ref="paging")中的query方法
|
||||
autowireQueryName: {
|
||||
type: String,
|
||||
default: function() {
|
||||
return u.gc('autowireQueryName', '');
|
||||
},
|
||||
},
|
||||
//z-paging mounted后自动调用reload方法(mounted后自动调用接口),默认为是。请使用简便写法:auto
|
||||
mountedAutoCallReload: {
|
||||
type: Boolean,
|
||||
default: u.gc('mountedAutoCallReload', true)
|
||||
},
|
||||
//z-paging mounted后自动调用reload方法(mounted后自动调用接口),默认为是
|
||||
auto: {
|
||||
type: Boolean,
|
||||
default: u.gc('auto', true)
|
||||
},
|
||||
//用户下拉刷新时是否触发reload方法,默认为是
|
||||
reloadWhenRefresh: {
|
||||
type: Boolean,
|
||||
default: u.gc('reloadWhenRefresh', true)
|
||||
},
|
||||
//reload时自动滚动到顶部,默认为是
|
||||
autoScrollToTopWhenReload: {
|
||||
type: Boolean,
|
||||
default: u.gc('autoScrollToTopWhenReload', true)
|
||||
},
|
||||
//reload时立即自动清空原list,默认为是,若立即自动清空,则在reload之后、请求回调之前页面是空白的
|
||||
autoCleanListWhenReload: {
|
||||
type: Boolean,
|
||||
default: u.gc('autoCleanListWhenReload', true)
|
||||
},
|
||||
//列表刷新时自动显示下拉刷新view,默认为否
|
||||
showRefresherWhenReload: {
|
||||
type: Boolean,
|
||||
default: u.gc('showRefresherWhenReload', false)
|
||||
},
|
||||
//列表刷新时自动显示加载更多view,且为加载中状态,默认为否
|
||||
showLoadingMoreWhenReload: {
|
||||
type: Boolean,
|
||||
default: u.gc('showLoadingMoreWhenReload', false)
|
||||
},
|
||||
//组件created时立即触发reload(可解决一些情况下先看到页面再看到loading的问题),auto为true时有效。为否时将在mounted+nextTick后触发reload,默认为否
|
||||
createdReload: {
|
||||
type: Boolean,
|
||||
default: u.gc('createdReload', false)
|
||||
},
|
||||
//本地分页时上拉加载更多延迟时间,单位为毫秒,默认200毫秒
|
||||
localPagingLoadingTime: {
|
||||
type: [Number, String],
|
||||
default: u.gc('localPagingLoadingTime', 200)
|
||||
},
|
||||
//当分页未满一屏时,是否自动加载更多,默认为否(nvue无效)
|
||||
insideMore: {
|
||||
type: Boolean,
|
||||
default: u.gc('insideMore', false)
|
||||
},
|
||||
//使用聊天记录模式,默认为否
|
||||
useChatRecordMode: {
|
||||
type: Boolean,
|
||||
default: u.gc('useChatRecordMode', false)
|
||||
},
|
||||
//自动拼接complete中传过来的数组(使用聊天记录模式时无效)
|
||||
concat: {
|
||||
type: Boolean,
|
||||
default: u.gc('concat', true)
|
||||
},
|
||||
//父组件v-model所绑定的list的值
|
||||
value: {
|
||||
type: Array,
|
||||
default: function() {
|
||||
return [];
|
||||
}
|
||||
},
|
||||
// #ifdef VUE3
|
||||
modelValue: {
|
||||
type: Array,
|
||||
default: function() {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
// #endif
|
||||
},
|
||||
data (){
|
||||
return {
|
||||
currentData: [],
|
||||
totalData: [],
|
||||
realTotalData: [],
|
||||
totalLocalPagingList: [],
|
||||
pageNo: 1,
|
||||
isLocalPaging: false,
|
||||
isAddedData: false,
|
||||
isTotalChangeFromAddData: false,
|
||||
privateConcat: true,
|
||||
myParentQuery: -1,
|
||||
firstPageLoaded: false,
|
||||
pagingLoaded: false,
|
||||
loaded: false,
|
||||
isUserReload: true,
|
||||
fromEmptyViewReload: false,
|
||||
listRendering: false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
pageSize() {
|
||||
return this.defaultPageSize;
|
||||
},
|
||||
finalConcat() {
|
||||
return this.concat && this.privateConcat;
|
||||
},
|
||||
isFirstPage() {
|
||||
return this.pageNo === this.defaultPageNo;
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
totalData(newVal, oldVal) {
|
||||
this._totalDataChange(newVal, oldVal);
|
||||
},
|
||||
currentData(newVal, oldVal) {
|
||||
this._currentDataChange(newVal, oldVal);
|
||||
},
|
||||
useChatRecordMode(newVal, oldVal) {
|
||||
if (newVal) {
|
||||
this.nLoadingMoreFixedHeight = false;
|
||||
}
|
||||
},
|
||||
value: {
|
||||
handler(newVal) {
|
||||
this.realTotalData = newVal;
|
||||
},
|
||||
immediate: true
|
||||
},
|
||||
// #ifdef VUE3
|
||||
modelValue: {
|
||||
handler(newVal) {
|
||||
this.realTotalData = newVal;
|
||||
},
|
||||
immediate: true
|
||||
}
|
||||
// #endif
|
||||
},
|
||||
methods: {
|
||||
//请求结束(成功或者失败)调用此方法,将请求的结果传递给z-paging处理,第一个参数为请求结果数组,第二个参数为是否成功(默认是是)
|
||||
complete(data, success = true) {
|
||||
this.customNoMore = -1;
|
||||
this.addData(data, success);
|
||||
},
|
||||
//简写,与complete完全相同
|
||||
end(data, success = true) {
|
||||
this.complete(data, success);
|
||||
},
|
||||
//【保证数据一致】请求结束(成功或者失败)调用此方法,将请求的结果传递给z-paging处理,第一个参数为请求结果数组,第二个参数为dataKey,需与:data-key绑定的一致,第三个参数为是否成功(默认为是)
|
||||
completeByKey(data, dataKey = null, success = true) {
|
||||
if (dataKey !== null && this.dataKey !== null && dataKey !== this.dataKey) {
|
||||
if (this.isFirstPage) {
|
||||
this.endRefresh();
|
||||
}
|
||||
return;
|
||||
}
|
||||
this.customNoMore = -1;
|
||||
this.addData(data, success);
|
||||
},
|
||||
//简写,与completeByKey完全相同
|
||||
endByKey(data, dataKey = null, success = true) {
|
||||
this.completeByKey(data, dataKey, success);
|
||||
},
|
||||
//【通过totalCount判断是否有更多数据】请求结束(成功或者失败)调用此方法,将请求的结果传递给z-paging处理,第一个参数为请求结果数组,第二个参数为totalCount(列表总数),第三个参数为是否成功(默认为是)
|
||||
completeByTotalCount(data, totalCount, success = true) {
|
||||
if (totalCount == 'undefined') {
|
||||
this.customNoMore = -1;
|
||||
} else {
|
||||
let dataTypeRes = this._checkDataType(data, success, false);
|
||||
data = dataTypeRes.data;
|
||||
success = dataTypeRes.success;
|
||||
if (totalCount >= 0 && success) {
|
||||
this.$nextTick(() => {
|
||||
let nomore = true;
|
||||
let realTotalDataCount = this.realTotalData.length;
|
||||
if (this.pageNo == this.defaultPageNo) {
|
||||
realTotalDataCount = 0;
|
||||
}
|
||||
let exceedCount = realTotalDataCount + data.length - totalCount;
|
||||
if (exceedCount >= 0) {
|
||||
nomore = false;
|
||||
exceedCount = this.defaultPageSize - exceedCount;
|
||||
if (exceedCount > 0 && exceedCount < data.length) {
|
||||
data = data.splice(0, exceedCount);
|
||||
}
|
||||
}
|
||||
this.completeByNoMore(data, nomore, success);
|
||||
})
|
||||
return;
|
||||
}
|
||||
}
|
||||
this.addData(data, success);
|
||||
},
|
||||
//简写,与completeByTotalCount完全相同
|
||||
completeByTotal(data, totalCount, success = true) {
|
||||
this.completeByTotalCount(data, totalCount, success);
|
||||
},
|
||||
//简写,与completeByTotalCount完全相同
|
||||
endByTotalCount(data, totalCount, success = true) {
|
||||
this.completeByTotalCount(data, totalCount, success);
|
||||
},
|
||||
//简写,与completeByTotalCount完全相同
|
||||
endByTotal(data, totalCount, success = true) {
|
||||
this.completeByTotalCount(data, totalCount, success);
|
||||
},
|
||||
//【自行判断是否有更多数据】请求结束(成功或者失败)调用此方法,将请求的结果传递给z-paging处理,第一个参数为请求结果数组,第二个参数为是否有更多数据,第三个参数为是否成功(默认是是)
|
||||
completeByNoMore(data, nomore, success = true) {
|
||||
if (nomore != 'undefined') {
|
||||
this.customNoMore = nomore == true ? 1 : 0;
|
||||
}
|
||||
this.addData(data, success);
|
||||
},
|
||||
//简写,与completeByNoMore完全相同
|
||||
endByNoMore(data, nomore, success = true) {
|
||||
this.completeByNoMore(data, nomore, success);
|
||||
},
|
||||
//与上方complete方法功能一致,新版本中设置服务端回调数组请使用complete方法
|
||||
addData(data, success = true) {
|
||||
if (!this.fromCompleteEmit) {
|
||||
this.disabledCompleteEmit = true;
|
||||
this.fromCompleteEmit = false;
|
||||
}
|
||||
const currentTimeStamp = u.getTime();
|
||||
let addDataDalay = 0;
|
||||
const disTime = currentTimeStamp - this.requestTimeStamp;
|
||||
let minDelay = this.minDelay;
|
||||
if(this.isFirstPage && this.finalShowRefresherWhenReload){
|
||||
minDelay = Math.max(400,minDelay);
|
||||
}
|
||||
if(this.requestTimeStamp > 0 && disTime < minDelay){
|
||||
addDataDalay = minDelay - disTime;
|
||||
}
|
||||
this.$nextTick(() => {
|
||||
let delay = this.delay > 0 ? this.delay : addDataDalay;
|
||||
setTimeout(() => {
|
||||
this._addData(data, success, false);
|
||||
}, delay)
|
||||
})
|
||||
},
|
||||
//从顶部添加数据,不会影响分页的pageNo和pageSize
|
||||
addDataFromTop(data, toTop = true, toTopWithAnimate = true) {
|
||||
let dataType = Object.prototype.toString.call(data);
|
||||
if (dataType !== '[object Array]') {
|
||||
data = [data];
|
||||
}
|
||||
this.totalData = [...data, ...this.totalData];
|
||||
if (toTop) {
|
||||
setTimeout(() => {
|
||||
this._scrollToTop(toTopWithAnimate);
|
||||
}, c.delayTime)
|
||||
}
|
||||
},
|
||||
//重新设置列表数据,调用此方法不会影响pageNo和pageSize,也不会触发请求。适用场景:当需要删除列表中某一项时,将删除对应项后的数组通过此方法传递给z-paging。(当出现类似的需要修改列表数组的场景时,请使用此方法,请勿直接修改page中:list.sync绑定的数组)
|
||||
resetTotalData(data) {
|
||||
if (data == undefined) {
|
||||
if (this.showConsoleError) {
|
||||
u.consoleErr('方法resetTotalData参数缺失!');
|
||||
}
|
||||
return;
|
||||
}
|
||||
this.isTotalChangeFromAddData = true;
|
||||
let dataType = Object.prototype.toString.call(data);
|
||||
if (dataType !== '[object Array]') {
|
||||
data = [data];
|
||||
}
|
||||
this.totalData = data;
|
||||
},
|
||||
//添加聊天记录
|
||||
addChatRecordData(data, toBottom = true, toBottomWithAnimate = true) {
|
||||
let dataType = Object.prototype.toString.call(data);
|
||||
if (dataType !== '[object Array]') {
|
||||
data = [data];
|
||||
}
|
||||
if (!this.useChatRecordMode) return;
|
||||
this.isTotalChangeFromAddData = true;
|
||||
//#ifndef APP-NVUE
|
||||
this.totalData = [...this.totalData, ...data];
|
||||
//#endif
|
||||
//#ifdef APP-NVUE
|
||||
this.totalData = this.nIsFirstPageAndNoMore ? [...this.totalData, ...data] : [...data, ...this.totalData];
|
||||
//#endif
|
||||
if (toBottom) {
|
||||
setTimeout(() => {
|
||||
//#ifndef APP-NVUE
|
||||
this._scrollToBottom(toBottomWithAnimate);
|
||||
//#endif
|
||||
//#ifdef APP-NVUE
|
||||
if (this.nIsFirstPageAndNoMore) {
|
||||
this._scrollToBottom(toBottomWithAnimate);
|
||||
} else {
|
||||
this._scrollToTop(toBottomWithAnimate);
|
||||
}
|
||||
//#endif
|
||||
}, c.delayTime)
|
||||
}
|
||||
},
|
||||
//设置本地分页数据,请求结束(成功或者失败)调用此方法,将请求的结果传递给z-paging作分页处理(若调用了此方法,则上拉加载更多时内部会自动分页,不会触发@query所绑定的事件)
|
||||
setLocalPaging(data, success = true) {
|
||||
this.isLocalPaging = true;
|
||||
this.$nextTick(() => {
|
||||
this._addData(data, success, true);
|
||||
})
|
||||
},
|
||||
//重新加载分页数据,pageNo会恢复为默认值,相当于下拉刷新的效果(animate为true时会展示下拉刷新动画,默认为false)
|
||||
reload(animate = this.showRefresherWhenReload) {
|
||||
if (animate) {
|
||||
this.privateShowRefresherWhenReload = animate;
|
||||
this.isUserPullDown = true;
|
||||
}
|
||||
this._preReload(animate, false);
|
||||
},
|
||||
//刷新列表数据,pageNo和pageSize不会重置,列表数据会重新从服务端获取。必须保证@query绑定的方法中的pageNo和pageSize和传给服务端的一致
|
||||
refresh() {
|
||||
if(!this.realTotalData.length){
|
||||
this.reload();
|
||||
return;
|
||||
}
|
||||
const disPageNo = this.pageNo - this.defaultPageNo + 1;
|
||||
if (disPageNo >= 1) {
|
||||
this.loading = true;
|
||||
this.privateConcat = false;
|
||||
const totalPageSize = disPageNo * this.pageSize;
|
||||
this._emitQuery(this.defaultPageNo, totalPageSize, Enum.QueryFrom.Refresh);
|
||||
this._callMyParentQuery(this.defaultPageNo, totalPageSize);
|
||||
}
|
||||
},
|
||||
//清空分页数据
|
||||
clean() {
|
||||
this._reload(true);
|
||||
this._addData([], true, false);
|
||||
},
|
||||
//清空分页数据
|
||||
clear() {
|
||||
this.clean();
|
||||
},
|
||||
//手动触发滚动到顶部加载更多,聊天记录模式时有效
|
||||
doChatRecordLoadMore() {
|
||||
this.useChatRecordMode && this._onLoadingMore('click');
|
||||
},
|
||||
//reload之前的一些处理
|
||||
_preReload(animate = this.showRefresherWhenReload, isFromMounted = true) {
|
||||
this.isUserReload = true;
|
||||
this.loadingType = Enum.LoadingType.Refresher;
|
||||
if (animate) {
|
||||
this.privateShowRefresherWhenReload = animate;
|
||||
// #ifndef APP-NVUE
|
||||
if (this.useCustomRefresher) {
|
||||
this._doRefresherRefreshAnimate();
|
||||
} else {
|
||||
this.refresherTriggered = true;
|
||||
}
|
||||
// #endif
|
||||
// #ifdef APP-NVUE
|
||||
this.refresherStatus = Enum.Refresher.Loading;
|
||||
this.refresherRevealStackCount++;
|
||||
setTimeout(() => {
|
||||
this._getNodeClientRect('zp-n-refresh-container', false).then((node) => {
|
||||
if (node) {
|
||||
let nodeHeight = node[0].height;
|
||||
this.nShowRefresherReveal = true;
|
||||
this.nShowRefresherRevealHeight = nodeHeight;
|
||||
setTimeout(() => {
|
||||
this._nDoRefresherEndAnimation(0, -nodeHeight, false, false);
|
||||
setTimeout(() => {
|
||||
this._nDoRefresherEndAnimation(nodeHeight, 0);
|
||||
}, 10)
|
||||
}, 10)
|
||||
}
|
||||
this._reload(false, isFromMounted);
|
||||
this._doRefresherLoad(false);
|
||||
});
|
||||
}, 10)
|
||||
return;
|
||||
// #endif
|
||||
} else {
|
||||
this._refresherEnd(false, false, false, false);
|
||||
}
|
||||
this._reload(false, isFromMounted);
|
||||
},
|
||||
//重新加载分页数据
|
||||
_reload(isClean = false, isFromMounted = false, isUserPullDown = false) {
|
||||
this.isAddedData = false;
|
||||
this.cacheScrollNodeHeight = -1;
|
||||
this.insideOfPaging = -1;
|
||||
this.pageNo = this.defaultPageNo;
|
||||
this._cleanRefresherEndTimeout();
|
||||
!this.privateShowRefresherWhenReload && !isClean && this._startLoading(true);
|
||||
this.firstPageLoaded = true;
|
||||
this.isTotalChangeFromAddData = false;
|
||||
this.totalData = [];
|
||||
if (!isClean) {
|
||||
this._emitQuery(this.pageNo, this.defaultPageSize, isUserPullDown ? Enum.QueryFrom.UserPullDown : Enum.QueryFrom.Reload);
|
||||
let delay = 0;
|
||||
// #ifdef MP-TOUTIAO
|
||||
delay = 5;
|
||||
// #endif
|
||||
setTimeout(() => {
|
||||
this._callMyParentQuery();
|
||||
}, delay)
|
||||
if (!isFromMounted && this.autoScrollToTopWhenReload) {
|
||||
let checkedNRefresherLoading = true;
|
||||
// #ifdef APP-NVUE
|
||||
checkedNRefresherLoading = !this.nRefresherLoading;
|
||||
// #endif
|
||||
if (checkedNRefresherLoading) {
|
||||
this._scrollToTop(false);
|
||||
}
|
||||
}
|
||||
// #ifndef APP-NVUE
|
||||
if (!this.usePageScroll && this.useChatRecordMode) {
|
||||
if (this.showConsoleError) {
|
||||
u.consoleWarn('使用聊天记录模式时,建议使用页面滚动,可将usePageScroll设置为true以启用页面滚动!!');
|
||||
}
|
||||
}
|
||||
// #endif
|
||||
}
|
||||
this.$nextTick(() => {
|
||||
// #ifdef APP-NVUE
|
||||
this.nShowBottom = this.realTotalData.length > 0;
|
||||
// #endif
|
||||
})
|
||||
},
|
||||
//处理服务端返回的数组
|
||||
_addData(data, success, isLocal) {
|
||||
this.isAddedData = true;
|
||||
this.fromEmptyViewReload = false;
|
||||
this.isTotalChangeFromAddData = true;
|
||||
this.refresherTriggered = false;
|
||||
!this.useCustomRefresher && uni.stopPullDownRefresh();
|
||||
// #ifdef APP-NVUE
|
||||
this.usePageScroll && uni.stopPullDownRefresh();
|
||||
// #endif
|
||||
const tempIsUserPullDown = this.isUserPullDown;
|
||||
if (this.showRefresherUpdateTime && this.isFirstPage) {
|
||||
u.setRefesrherTime(u.getTime(), this.refresherUpdateTimeKey);
|
||||
this.tempLanguageUpdateKey = u.getTime();
|
||||
this.$refs.refresh && this.$refs.refresh.updateTime();
|
||||
}
|
||||
if (tempIsUserPullDown && this.isFirstPage) {
|
||||
this.isUserPullDown = false;
|
||||
}
|
||||
let dataTypeRes = this._checkDataType(data, success, isLocal);
|
||||
data = dataTypeRes.data;
|
||||
success = dataTypeRes.success;
|
||||
let delayTime = c.delayTime;
|
||||
// #ifdef APP-NVUE
|
||||
if (this.useChatRecordMode) delayTime = 0;
|
||||
// #endif
|
||||
this.loadingForNow = false;
|
||||
setTimeout(() => {
|
||||
this.pagingLoaded = true;
|
||||
this.$nextTick(()=>{
|
||||
this._refresherEnd(delayTime > 0, true, tempIsUserPullDown);
|
||||
})
|
||||
}, delayTime)
|
||||
if (this.isFirstPage) {
|
||||
this.isLoadFailed = !success;
|
||||
}
|
||||
if (success) {
|
||||
if (!(this.privateConcat === false && this.loadingStatus === Enum.More.NoMore)) {
|
||||
this.loadingStatus = Enum.More.Default;
|
||||
}
|
||||
if (isLocal) {
|
||||
this.totalLocalPagingList = data;
|
||||
this._localPagingQueryList(this.defaultPageNo, this.defaultPageSize, 0, (res) => {
|
||||
this.complete(res);
|
||||
})
|
||||
} else {
|
||||
let dataChangeDelayTime = 0;
|
||||
// #ifdef APP-NVUE
|
||||
if (this.privateShowRefresherWhenReload && this.finalNvueListIs === 'waterfall') {
|
||||
dataChangeDelayTime = 150;
|
||||
}
|
||||
// #endif
|
||||
setTimeout(() => {
|
||||
this._currentDataChange(data, this.currentData);
|
||||
}, dataChangeDelayTime)
|
||||
}
|
||||
} else {
|
||||
this._currentDataChange(data, this.currentData);
|
||||
this.loadingStatus = Enum.More.Fail;
|
||||
if (this.loadingType === Enum.LoadingType.LoadingMore) {
|
||||
this.pageNo--;
|
||||
}
|
||||
}
|
||||
},
|
||||
//所有数据改变时调用
|
||||
_totalDataChange(newVal, oldVal, eventThrow=true) {
|
||||
if ((!this.isUserReload || !this.autoCleanListWhenReload) && this.firstPageLoaded && !newVal.length && oldVal.length) {
|
||||
return;
|
||||
}
|
||||
this._doCheckScrollViewShouldFullHeight(newVal);
|
||||
if(!this.realTotalData.length && !newVal.length){
|
||||
eventThrow = false;
|
||||
}
|
||||
this.realTotalData = newVal;
|
||||
if (eventThrow) {
|
||||
this.$emit('input', newVal);
|
||||
// #ifdef VUE3
|
||||
this.$emit('update:modelValue', newVal);
|
||||
// #endif
|
||||
this.$emit('update:list', newVal);
|
||||
this.$emit('listChange', newVal);
|
||||
this._callMyParentList(newVal);
|
||||
}
|
||||
this.firstPageLoaded = false;
|
||||
this.isTotalChangeFromAddData = false;
|
||||
this.$nextTick(() => {
|
||||
setTimeout(()=>{
|
||||
this._getNodeClientRect('.zp-paging-container-content').then((res) => {
|
||||
if (res) {
|
||||
this.$emit('contentHeightChanged', res[0].height);
|
||||
}
|
||||
});
|
||||
},this.isIos?100:300)
|
||||
// #ifdef APP-NVUE
|
||||
if (this.useChatRecordMode && this.nIsFirstPageAndNoMore && this.isFirstPage && !this.nFirstPageAndNoMoreChecked) {
|
||||
this.nFirstPageAndNoMoreChecked = true;
|
||||
this._scrollToBottom(false);
|
||||
}
|
||||
// #endif
|
||||
})
|
||||
},
|
||||
//当前数据改变时调用
|
||||
_currentDataChange(newVal, oldVal) {
|
||||
newVal = [...newVal];
|
||||
this.listRendering = true;
|
||||
this.$nextTick(() => {
|
||||
setTimeout(() => {
|
||||
this.listRendering = false;
|
||||
},50)
|
||||
})
|
||||
// #ifndef APP-NVUE
|
||||
if (this.finalUseVirtualList) {
|
||||
this._setCellIndex(newVal,this.totalData.length === 0);
|
||||
}
|
||||
this.useChatRecordMode && newVal.reverse();
|
||||
// #endif
|
||||
if (this.isFirstPage && this.finalConcat) {
|
||||
this.totalData = [];
|
||||
}
|
||||
if (this.customNoMore !== -1) {
|
||||
if (this.customNoMore === 0 || !newVal.length) {
|
||||
this.loadingStatus = Enum.More.NoMore;
|
||||
}
|
||||
} else {
|
||||
if (!newVal.length || (newVal.length && newVal.length < this.defaultPageSize)) {
|
||||
this.loadingStatus = Enum.More.NoMore;
|
||||
}
|
||||
}
|
||||
if (!this.totalData.length) {
|
||||
if (this.finalConcat) {
|
||||
// #ifdef APP-NVUE
|
||||
if(this.useChatRecordMode && this.isFirstPage && this.loadingStatus === Enum.More.NoMore){
|
||||
newVal.reverse();
|
||||
}
|
||||
// #endif
|
||||
this.totalData = newVal;
|
||||
}
|
||||
if (this.useChatRecordMode) {
|
||||
// #ifndef APP-NVUE
|
||||
this.$nextTick(() => {
|
||||
this._scrollToBottom(false);
|
||||
})
|
||||
// #endif
|
||||
}
|
||||
} else {
|
||||
if (this.useChatRecordMode) {
|
||||
// #ifdef APP-NVUE
|
||||
this.totalData = [...this.totalData, ...newVal];
|
||||
// #endif
|
||||
//#ifndef APP-NVUE
|
||||
const idIndex = newVal.length;
|
||||
let idIndexStr = `z-paging-${idIndex}`;
|
||||
this.totalData = [...newVal, ...this.totalData];
|
||||
if (this.pageNo !== this.defaultPageNo) {
|
||||
this.privateScrollWithAnimation = 0;
|
||||
let delayTime = 200;
|
||||
this.$emit('update:chatIndex', idIndex);
|
||||
setTimeout(() => {
|
||||
this._scrollIntoView(idIndexStr, 30 + this.cacheTopHeight, false, () => {
|
||||
this.$emit('update:chatIndex', 0);
|
||||
});
|
||||
}, this.usePageScroll ? 0 : delayTime)
|
||||
} else {
|
||||
this.$nextTick(() => {
|
||||
this._scrollToBottom(false);
|
||||
})
|
||||
}
|
||||
//#endif
|
||||
|
||||
} else {
|
||||
if (this.finalConcat) {
|
||||
const currentScrollTop = this.oldScrollTop;
|
||||
this.totalData = [...this.totalData, ...newVal];
|
||||
// #ifdef MP-WEIXIN
|
||||
if (!this.isIos && !this.refresherOnly && !this.usePageScroll && newVal.length) {
|
||||
this.loadingMoreTimeStamp = u.getTime();
|
||||
this.$nextTick(()=>{
|
||||
this.scrollToY(currentScrollTop);
|
||||
})
|
||||
}
|
||||
// #endif
|
||||
} else {
|
||||
this.totalData = newVal;
|
||||
}
|
||||
}
|
||||
}
|
||||
this.privateConcat = true;
|
||||
},
|
||||
//本地分页请求
|
||||
_localPagingQueryList(pageNo, pageSize, localPagingLoadingTime, callback) {
|
||||
pageNo = parseInt(pageNo);
|
||||
pageSize = parseInt(pageSize);
|
||||
if (pageNo < 0 || pageSize <= 0) {
|
||||
this._localPagingQueryResult(callback, [], localPagingLoadingTime);
|
||||
return;
|
||||
}
|
||||
pageNo = Math.max(1,pageNo);
|
||||
let totalPagingList = [...this.totalLocalPagingList];
|
||||
let pageNoIndex = (pageNo - 1) * pageSize;
|
||||
if (pageNoIndex + pageSize <= totalPagingList.length) {
|
||||
this._localPagingQueryResult(callback, totalPagingList.splice(pageNoIndex, pageSize), localPagingLoadingTime);
|
||||
} else if (pageNoIndex < totalPagingList.length) {
|
||||
this._localPagingQueryResult(callback, totalPagingList.splice(pageNoIndex, totalPagingList.length - pageNoIndex), localPagingLoadingTime);
|
||||
} else {
|
||||
this._localPagingQueryResult(callback, [], localPagingLoadingTime);
|
||||
}
|
||||
},
|
||||
//本地分页请求回调
|
||||
_localPagingQueryResult(callback, arg, localPagingLoadingTime) {
|
||||
setTimeout(() => {
|
||||
callback(arg);
|
||||
}, localPagingLoadingTime)
|
||||
},
|
||||
//修改父view的list
|
||||
_callMyParentList(newVal) {
|
||||
if (this.autowireListName.length) {
|
||||
const myParent = u.getParent(this.$parent);
|
||||
if (myParent && myParent[this.autowireListName]) {
|
||||
myParent[this.autowireListName] = newVal;
|
||||
}
|
||||
}
|
||||
},
|
||||
//调用父view的query
|
||||
_callMyParentQuery(customPageNo = 0, customPageSize = 0) {
|
||||
if (this.autowireQueryName) {
|
||||
if (this.myParentQuery === -1) {
|
||||
const myParent = u.getParent(this.$parent);
|
||||
if (myParent && myParent[this.autowireQueryName]) {
|
||||
this.myParentQuery = myParent[this.autowireQueryName];
|
||||
}
|
||||
}
|
||||
if (this.myParentQuery !== -1) {
|
||||
if (customPageSize > 0) {
|
||||
this.myParentQuery(customPageNo, customPageSize);
|
||||
} else {
|
||||
this.myParentQuery(this.pageNo, this.defaultPageSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
//发射query事件
|
||||
_emitQuery(pageNo, pageSize, from){
|
||||
this.requestTimeStamp = u.getTime();
|
||||
this.$emit('query', ...interceptor._handleQuery(pageNo, pageSize, from));
|
||||
},
|
||||
//检查complete data的类型
|
||||
_checkDataType(data, success, isLocal) {
|
||||
const dataType = Object.prototype.toString.call(data);
|
||||
if (dataType === '[object Boolean]') {
|
||||
success = data;
|
||||
data = [];
|
||||
} else if (dataType === '[object Null]') {
|
||||
data = [];
|
||||
} else if (dataType !== '[object Array]') {
|
||||
data = [];
|
||||
let methodStr = isLocal ? 'setLocalPaging' : 'complete';
|
||||
if (dataType !== '[object Undefined]') {
|
||||
if (this.showConsoleError) {
|
||||
u.consoleErr(`${methodStr}参数类型不正确,第一个参数类型必须为Array!`);
|
||||
}
|
||||
}
|
||||
}
|
||||
return {data,success};
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
export default ZPData;
|
||||
150
components/z-paging/js/modules/empty.js
Normal file
150
components/z-paging/js/modules/empty.js
Normal file
@@ -0,0 +1,150 @@
|
||||
// [z-paging]空数据图view模块
|
||||
import u from '.././z-paging-utils'
|
||||
|
||||
const ZPEmptyView = {
|
||||
props: {
|
||||
//是否强制隐藏空数据图,默认为否
|
||||
hideEmptyView: {
|
||||
type: Boolean,
|
||||
default: u.gc('hideEmptyView', false)
|
||||
},
|
||||
//空数据图描述文字,默认为“没有数据哦~”
|
||||
emptyViewText: {
|
||||
type: [String, Object],
|
||||
default: u.gc('emptyViewText', null)
|
||||
},
|
||||
//是否显示空数据图重新加载按钮(无数据时),默认为否
|
||||
showEmptyViewReload: {
|
||||
type: Boolean,
|
||||
default: u.gc('showEmptyViewReload', false)
|
||||
},
|
||||
//加载失败时是否显示空数据图重新加载按钮,默认为是
|
||||
showEmptyViewReloadWhenError: {
|
||||
type: Boolean,
|
||||
default: u.gc('showEmptyViewReloadWhenError', true)
|
||||
},
|
||||
//空数据图点击重新加载文字,默认为“重新加载”
|
||||
emptyViewReloadText: {
|
||||
type: [String, Object],
|
||||
default: u.gc('emptyViewReloadText', null)
|
||||
},
|
||||
//空数据图图片,默认使用z-paging内置的图片
|
||||
emptyViewImg: {
|
||||
type: String,
|
||||
default: u.gc('emptyViewImg', '')
|
||||
},
|
||||
//空数据图“加载失败”描述文字,默认为“很抱歉,加载失败”
|
||||
emptyViewErrorText: {
|
||||
type: [String, Object],
|
||||
default: u.gc('emptyViewErrorText', null)
|
||||
},
|
||||
//空数据图“加载失败”图片,默认使用z-paging内置的图片
|
||||
emptyViewErrorImg: {
|
||||
type: String,
|
||||
default: u.gc('emptyViewErrorImg', '')
|
||||
},
|
||||
//空数据图样式
|
||||
emptyViewStyle: {
|
||||
type: Object,
|
||||
default: function() {
|
||||
return u.gc('emptyViewStyle', {});
|
||||
}
|
||||
},
|
||||
//空数据图容器样式
|
||||
emptyViewSuperStyle: {
|
||||
type: Object,
|
||||
default: function() {
|
||||
return u.gc('emptyViewSuperStyle', {});
|
||||
}
|
||||
},
|
||||
//空数据图img样式
|
||||
emptyViewImgStyle: {
|
||||
type: Object,
|
||||
default: function() {
|
||||
return u.gc('emptyViewImgStyle', {});
|
||||
}
|
||||
},
|
||||
//空数据图描述文字样式
|
||||
emptyViewTitleStyle: {
|
||||
type: Object,
|
||||
default: function() {
|
||||
return u.gc('emptyViewTitleStyle', {});
|
||||
}
|
||||
},
|
||||
//空数据图重新加载按钮样式
|
||||
emptyViewReloadStyle: {
|
||||
type: Object,
|
||||
default: function() {
|
||||
return u.gc('emptyViewReloadStyle', {});
|
||||
}
|
||||
},
|
||||
//空数据图片是否铺满z-paging,默认为是。若设置为否,则为填充满z-paging的剩余部分
|
||||
emptyViewFixed: {
|
||||
type: Boolean,
|
||||
default: function() {
|
||||
return u.gc('emptyViewFixed', false)
|
||||
}
|
||||
},
|
||||
//空数据图片是否垂直居中,默认为是。emptyViewFixed为false时有效
|
||||
emptyViewCenter: {
|
||||
type: Boolean,
|
||||
default: function() {
|
||||
return u.gc('emptyViewCenter', true)
|
||||
}
|
||||
},
|
||||
//加载中时是否自动隐藏空数据图,默认为是
|
||||
autoHideEmptyViewWhenLoading: {
|
||||
type: Boolean,
|
||||
default: u.gc('autoHideEmptyViewWhenLoading', true)
|
||||
},
|
||||
//用户下拉列表触发下拉刷新加载中时是否自动隐藏空数据图,默认为是
|
||||
autoHideEmptyViewWhenPull: {
|
||||
type: Boolean,
|
||||
default: u.gc('autoHideEmptyViewWhenPull', true)
|
||||
},
|
||||
//空数据view的z-index,默认为9
|
||||
emptyViewZIndex: {
|
||||
type: Number,
|
||||
default: u.gc('emptyViewZIndex', 9)
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
finalEmptyViewImg() {
|
||||
return this.isLoadFailed ? this.emptyViewErrorImg : this.emptyViewImg;
|
||||
},
|
||||
finalShowEmptyViewReload() {
|
||||
return this.isLoadFailed ? this.showEmptyViewReloadWhenError : this.showEmptyViewReload;
|
||||
},
|
||||
showEmpty() {
|
||||
if(this.refresherOnly || this.hideEmptyView || this.totalData.length) return false;
|
||||
if(this.autoHideEmptyViewWhenLoading){
|
||||
if (this.isAddedData && !this.firstPageLoaded && !this.loading) return true;
|
||||
}else{
|
||||
return true;
|
||||
}
|
||||
if (!this.autoHideEmptyViewWhenPull && !this.isUserReload) return true;
|
||||
return false;
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
//点击了空数据view重新加载按钮
|
||||
_emptyViewReload() {
|
||||
let callbacked = false;
|
||||
this.$emit('emptyViewReload', (reload) => {
|
||||
if (reload === undefined || reload === true) {
|
||||
this.fromEmptyViewReload = true;
|
||||
this.reload();
|
||||
}
|
||||
callbacked = true;
|
||||
});
|
||||
this.$nextTick(() => {
|
||||
if (!callbacked) {
|
||||
this.fromEmptyViewReload = true;
|
||||
this.reload();
|
||||
}
|
||||
})
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
export default ZPEmptyView;
|
||||
98
components/z-paging/js/modules/i18n.js
Normal file
98
components/z-paging/js/modules/i18n.js
Normal file
@@ -0,0 +1,98 @@
|
||||
// [z-paging]i18n模块
|
||||
import u from '.././z-paging-utils'
|
||||
import c from '.././z-paging-constant'
|
||||
import zI18n from '.././z-paging-i18n'
|
||||
|
||||
const systemInfo = uni.getSystemInfoSync();
|
||||
const ZPI18n = {
|
||||
props: {
|
||||
//i18n国际化设置语言,支持简体中文(zh-cn)、繁体中文(zh-hant-cn)和英文(en)
|
||||
language: {
|
||||
type: String,
|
||||
default: u.gc('language', '')
|
||||
},
|
||||
//i18n国际化默认是否跟随系统语言,默认为是
|
||||
followSystemLanguage: {
|
||||
type: Boolean,
|
||||
default: u.gc('followSystemLanguage', true)
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
tempLanguageUpdateKey: 0,
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
tempLanguage() {
|
||||
let systemLanguage = false;
|
||||
const temp = this.tempLanguageUpdateKey;
|
||||
if (this.followSystemLanguage) {
|
||||
systemLanguage = systemInfo.language;
|
||||
}
|
||||
return uni.getStorageSync(c.i18nUpdateKey) || systemLanguage || 'zh-cn';
|
||||
},
|
||||
finalTempLanguage() {
|
||||
return this.language.length ? this.language : this.tempLanguage;
|
||||
},
|
||||
finalLanguage() {
|
||||
let language = this.finalTempLanguage.toLowerCase();
|
||||
return zI18n._getPrivateLanguage(language, this.followSystemLanguage);
|
||||
},
|
||||
finalRefresherDefaultText() {
|
||||
return this._getI18nText('refresherDefaultText', this.refresherDefaultText);
|
||||
},
|
||||
finalRefresherPullingText() {
|
||||
return this._getI18nText('refresherPullingText', this.refresherPullingText);
|
||||
},
|
||||
finalRefresherRefreshingText() {
|
||||
return this._getI18nText('refresherRefreshingText', this.refresherRefreshingText);
|
||||
},
|
||||
finalRefresherCompleteText() {
|
||||
return this._getI18nText('refresherCompleteText', this.refresherCompleteText);
|
||||
},
|
||||
finalLoadingMoreDefaultText() {
|
||||
return this._getI18nText('loadingMoreDefaultText', this.loadingMoreDefaultText);
|
||||
},
|
||||
finalLoadingMoreLoadingText() {
|
||||
return this._getI18nText('loadingMoreLoadingText', this.loadingMoreLoadingText);
|
||||
},
|
||||
finalLoadingMoreNoMoreText() {
|
||||
return this._getI18nText('loadingMoreNoMoreText', this.loadingMoreNoMoreText);
|
||||
},
|
||||
finalLoadingMoreFailText() {
|
||||
return this._getI18nText('loadingMoreFailText', this.loadingMoreFailText);
|
||||
},
|
||||
finalEmptyViewText() {
|
||||
return this.isLoadFailed ? this.finalEmptyViewErrorText : this._getI18nText('emptyViewText', this.emptyViewText);
|
||||
},
|
||||
finalEmptyViewReloadText() {
|
||||
return this._getI18nText('emptyViewReloadText', this.emptyViewReloadText);
|
||||
},
|
||||
finalEmptyViewErrorText() {
|
||||
return this._getI18nText('emptyViewErrorText', this.emptyViewErrorText);
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
//设置i18n国际化语言
|
||||
setI18n(language) {
|
||||
zI18n.setLanguage(language);
|
||||
},
|
||||
//获取当前z-paging的语言
|
||||
getLanguage() {
|
||||
return this.finalLanguage;
|
||||
},
|
||||
//获取国际化转换后的文本
|
||||
_getI18nText(key, value) {
|
||||
const dataType = Object.prototype.toString.call(value);
|
||||
if (dataType === '[object Object]') {
|
||||
const nextValue = value[this.finalLanguage];
|
||||
if (nextValue) return nextValue;
|
||||
} else if (dataType === '[object String]') {
|
||||
return value;
|
||||
}
|
||||
return zI18n.t[key][this.finalLanguage];
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
export default ZPI18n;
|
||||
328
components/z-paging/js/modules/load-more.js
Normal file
328
components/z-paging/js/modules/load-more.js
Normal file
@@ -0,0 +1,328 @@
|
||||
// [z-paging]滚动到底部加载更多模块
|
||||
import u from '.././z-paging-utils'
|
||||
import Enum from '.././z-paging-enum'
|
||||
|
||||
const ZPLoadMore = {
|
||||
props: {
|
||||
//自定义底部加载更多样式
|
||||
loadingMoreCustomStyle: {
|
||||
type: Object,
|
||||
default: function() {
|
||||
return u.gc('loadingMoreCustomStyle', {});
|
||||
}
|
||||
},
|
||||
//自定义底部加载更多文字样式
|
||||
loadingMoreTitleCustomStyle: {
|
||||
type: Object,
|
||||
default: function() {
|
||||
return u.gc('loadingMoreTitleCustomStyle', {});
|
||||
}
|
||||
},
|
||||
//自定义底部加载更多加载中动画样式
|
||||
loadingMoreLoadingIconCustomStyle: {
|
||||
type: Object,
|
||||
default: function() {
|
||||
return u.gc('loadingMoreLoadingIconCustomStyle', {});
|
||||
}
|
||||
},
|
||||
//自定义底部加载更多加载中动画图标类型,可选flower或circle,默认为flower
|
||||
loadingMoreLoadingIconType: {
|
||||
type: String,
|
||||
default: u.gc('loadingMoreLoadingIconType', 'flower')
|
||||
},
|
||||
//自定义底部加载更多加载中动画图标图片
|
||||
loadingMoreLoadingIconCustomImage: {
|
||||
type: String,
|
||||
default: u.gc('loadingMoreLoadingIconCustomImage', '')
|
||||
},
|
||||
//底部加载更多加载中view是否展示旋转动画,默认为是
|
||||
loadingMoreLoadingAnimated: {
|
||||
type: Boolean,
|
||||
default: u.gc('loadingMoreLoadingAnimated', true)
|
||||
},
|
||||
//是否启用加载更多数据(含滑动到底部加载更多数据和点击加载更多数据),默认为是
|
||||
loadingMoreEnabled: {
|
||||
type: Boolean,
|
||||
default: u.gc('loadingMoreEnabled', true)
|
||||
},
|
||||
//是否启用滑动到底部加载更多数据,默认为是
|
||||
toBottomLoadingMoreEnabled: {
|
||||
type: Boolean,
|
||||
default: u.gc('toBottomLoadingMoreEnabled', true)
|
||||
},
|
||||
//滑动到底部状态为默认状态时,以加载中的状态展示,默认为否。若设置为是,可避免滚动到底部看到默认状态然后立刻变为加载中状态的问题,但分页数量未超过一屏时,不会显示【点击加载更多】
|
||||
loadingMoreDefaultAsLoading: {
|
||||
type: [Boolean],
|
||||
default: u.gc('loadingMoreDefaultAsLoading', false)
|
||||
},
|
||||
//滑动到底部"默认"文字,默认为【点击加载更多】
|
||||
loadingMoreDefaultText: {
|
||||
type: [String, Object],
|
||||
default: u.gc('loadingMoreDefaultText', null)
|
||||
},
|
||||
//滑动到底部"加载中"文字,默认为【正在加载...】
|
||||
loadingMoreLoadingText: {
|
||||
type: [String, Object],
|
||||
default: u.gc('loadingMoreLoadingText', null)
|
||||
},
|
||||
//滑动到底部"没有更多"文字,默认为【没有更多了】
|
||||
loadingMoreNoMoreText: {
|
||||
type: [String, Object],
|
||||
default: u.gc('loadingMoreNoMoreText', null)
|
||||
},
|
||||
//滑动到底部"加载失败"文字,默认为【加载失败,点击重新加载】
|
||||
loadingMoreFailText: {
|
||||
type: [String, Object],
|
||||
default: u.gc('loadingMoreFailText', null)
|
||||
},
|
||||
//当没有更多数据且分页内容未超出z-paging时是否隐藏没有更多数据的view,默认为否
|
||||
hideLoadingMoreWhenNoMoreAndInsideOfPaging: {
|
||||
type: Boolean,
|
||||
default: u.gc('hideLoadingMoreWhenNoMoreAndInsideOfPaging', false)
|
||||
},
|
||||
//当没有更多数据且分页数组长度少于这个值时,隐藏没有更多数据的view,默认为0,代表不限制。
|
||||
hideLoadingMoreWhenNoMoreByLimit: {
|
||||
type: Number,
|
||||
default: u.gc('hideLoadingMoreWhenNoMoreByLimit', 0)
|
||||
},
|
||||
//是否显示默认的加载更多text,默认为是
|
||||
showDefaultLoadingMoreText: {
|
||||
type: Boolean,
|
||||
default: u.gc('showDefaultLoadingMoreText', true)
|
||||
},
|
||||
//是否显示没有更多数据的view
|
||||
showLoadingMoreNoMoreView: {
|
||||
type: Boolean,
|
||||
default: u.gc('showLoadingMoreNoMoreView', true)
|
||||
},
|
||||
//是否显示没有更多数据的分割线,默认为是
|
||||
showLoadingMoreNoMoreLine: {
|
||||
type: Boolean,
|
||||
default: u.gc('showLoadingMoreNoMoreLine', true)
|
||||
},
|
||||
//自定义底部没有更多数据的分割线样式
|
||||
loadingMoreNoMoreLineCustomStyle: {
|
||||
type: Object,
|
||||
default: function() {
|
||||
return u.gc('loadingMoreNoMoreLineCustomStyle', {});
|
||||
},
|
||||
},
|
||||
//距底部/右边多远时(单位px),触发 scrolltolower 事件,默认为100rpx
|
||||
lowerThreshold: {
|
||||
type: [Number, String],
|
||||
default: u.gc('lowerThreshold', '100rpx')
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
//底部加载更多状态
|
||||
loadingStatus: Enum.More.Default,
|
||||
loadingStatusAfterRender: Enum.More.Default,
|
||||
loadingMoreTimeStamp: 0,
|
||||
loadingMoreDefaultSlot: null,
|
||||
showLoadingMore: false,
|
||||
customNoMore: -1,
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
zPagingLoadMoreConfig() {
|
||||
return {
|
||||
status: this.loadingStatusAfterRender,
|
||||
defaultAsLoading: this.loadingMoreDefaultAsLoading,
|
||||
defaultThemeStyle: this.finalLoadingMoreThemeStyle,
|
||||
customStyle: this.loadingMoreCustomStyle,
|
||||
titleCustomStyle: this.loadingMoreTitleCustomStyle,
|
||||
iconCustomStyle: this.loadingMoreLoadingIconCustomStyle,
|
||||
loadingIconType: this.loadingMoreLoadingIconType,
|
||||
loadingIconCustomImage: this.loadingMoreLoadingIconCustomImage,
|
||||
loadingAnimated: this.loadingMoreLoadingAnimated,
|
||||
showNoMoreLine: this.showLoadingMoreNoMoreLine,
|
||||
noMoreLineCustomStyle: this.loadingMoreNoMoreLineCustomStyle,
|
||||
defaultText: this.finalLoadingMoreDefaultText,
|
||||
loadingText: this.finalLoadingMoreLoadingText,
|
||||
noMoreText: this.finalLoadingMoreNoMoreText,
|
||||
failText: this.finalLoadingMoreFailText,
|
||||
hideContent: !this.loadingMoreDefaultAsLoading && this.listRendering
|
||||
};
|
||||
},
|
||||
finalLoadingMoreThemeStyle() {
|
||||
return this.loadingMoreThemeStyle.length ? this.loadingMoreThemeStyle : this.defaultThemeStyle;
|
||||
},
|
||||
showLoadingMoreDefault() {
|
||||
return this._showLoadingMore('Default');
|
||||
},
|
||||
showLoadingMoreLoading() {
|
||||
return this._showLoadingMore('Loading');
|
||||
},
|
||||
showLoadingMoreNoMore() {
|
||||
return this._showLoadingMore('NoMore');
|
||||
},
|
||||
showLoadingMoreFail() {
|
||||
return this._showLoadingMore('Fail');
|
||||
},
|
||||
showLoadingMoreCustom() {
|
||||
return this._showLoadingMore('Custom');
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
//手动触发上拉加载更多(非必须,可依据具体需求使用)
|
||||
doLoadMore(type) {
|
||||
this._onLoadingMore(type);
|
||||
},
|
||||
//通过@scroll事件检测是否滚动到了底部
|
||||
_checkScrolledToBottom(scrollDiff, checked = false) {
|
||||
if (this.checkScrolledToBottomTimeOut) {
|
||||
clearTimeout(this.checkScrolledToBottomTimeOut);
|
||||
this.checkScrolledToBottomTimeOut = null;
|
||||
}
|
||||
if (this.cacheScrollNodeHeight === -1) {
|
||||
this._getNodeClientRect('.zp-scroll-view').then((res) => {
|
||||
if (res) {
|
||||
let pageScrollNodeHeight = res[0].height;
|
||||
this.cacheScrollNodeHeight = pageScrollNodeHeight;
|
||||
if (scrollDiff - pageScrollNodeHeight <= this.finalLowerThreshold) {
|
||||
this._onLoadingMore('toBottom');
|
||||
}
|
||||
}
|
||||
});
|
||||
} else {
|
||||
if (scrollDiff - this.cacheScrollNodeHeight <= this.finalLowerThreshold) {
|
||||
this._onLoadingMore('toBottom');
|
||||
} else if (scrollDiff - this.cacheScrollNodeHeight <= 500 && !checked) {
|
||||
this.checkScrolledToBottomTimeOut = setTimeout(() => {
|
||||
this._getNodeClientRect('.zp-scroll-view', true, true).then((res) => {
|
||||
this.oldScrollTop = res[0].scrollTop;
|
||||
const newScrollDiff = res[0].scrollHeight - this.oldScrollTop;
|
||||
this._checkScrolledToBottom(newScrollDiff, true);
|
||||
})
|
||||
}, 150)
|
||||
}
|
||||
}
|
||||
},
|
||||
//触发加载更多时调用,from:0-滑动到底部触发;1-点击加载更多触发
|
||||
_onLoadingMore(from = 'click') {
|
||||
if (from === 'toBottom') {
|
||||
if (!this.scrollToBottomBounceEnabled) {
|
||||
if (this.scrollEnable) {
|
||||
this.scrollEnable = false;
|
||||
this.$nextTick(() => {
|
||||
this.scrollEnable = true;
|
||||
})
|
||||
}
|
||||
}
|
||||
//#ifdef APP-VUE || H5
|
||||
if (this.isIos) {
|
||||
this.renderPropUsePageScroll = -1;
|
||||
this.$nextTick(() => {
|
||||
this.renderPropUsePageScroll = this.usePageScroll;
|
||||
})
|
||||
}
|
||||
//#endif
|
||||
}
|
||||
this.$emit('scrolltolower', from);
|
||||
if (from === 'toBottom' && (!this.toBottomLoadingMoreEnabled || this.useChatRecordMode)) return;
|
||||
if (this.refresherOnly || !this.loadingMoreEnabled || !(this.loadingStatus === Enum.More.Default || this.loadingStatus === Enum.More.Fail) || this.loading) return;
|
||||
// #ifdef MP-WEIXIN
|
||||
if (!this.isIos && !this.refresherOnly && !this.usePageScroll) {
|
||||
const currentTimestamp = u.getTime();
|
||||
if (this.loadingMoreTimeStamp > 0 && currentTimestamp - this.loadingMoreTimeStamp < 100) {
|
||||
this.loadingMoreTimeStamp = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
// #endif
|
||||
this._doLoadingMore();
|
||||
},
|
||||
//处理开始加载更多
|
||||
_doLoadingMore() {
|
||||
if (this.pageNo >= this.defaultPageNo && this.loadingStatus !== Enum.More.NoMore) {
|
||||
this.pageNo++;
|
||||
this._startLoading(false);
|
||||
if (this.isLocalPaging) {
|
||||
this._localPagingQueryList(this.pageNo, this.defaultPageSize, this.localPagingLoadingTime, (res) => {
|
||||
this.addData(res);
|
||||
})
|
||||
} else {
|
||||
this._emitQuery(this.pageNo, this.defaultPageSize, Enum.QueryFrom.LoadingMore);
|
||||
this._callMyParentQuery();
|
||||
}
|
||||
this.loadingType = Enum.LoadingType.LoadingMore;
|
||||
}
|
||||
},
|
||||
//(预处理)判断当没有更多数据且分页内容未超出z-paging时是否显示没有更多数据的view
|
||||
_preCheckShowLoadingMoreWhenNoMoreAndInsideOfPaging(newVal, scrollViewNode, pagingContainerNode) {
|
||||
if (this.loadingStatus === Enum.More.NoMore && this.hideLoadingMoreWhenNoMoreByLimit > 0 && newVal.length) {
|
||||
this.showLoadingMore = newVal.length > this.hideLoadingMoreWhenNoMoreByLimit;
|
||||
} else if ((this.loadingStatus === Enum.More.NoMore && this.hideLoadingMoreWhenNoMoreAndInsideOfPaging && newVal.length) || (this.insideMore && this.insideOfPaging !== false && newVal.length)) {
|
||||
this.$nextTick(() => {
|
||||
this._checkShowLoadingMoreWhenNoMoreAndInsideOfPaging(newVal, scrollViewNode, pagingContainerNode);
|
||||
})
|
||||
if (this.insideMore && this.insideOfPaging !== false && newVal.length) {
|
||||
this.showLoadingMore = newVal.length;
|
||||
}
|
||||
} else {
|
||||
this.showLoadingMore = newVal.length;
|
||||
}
|
||||
},
|
||||
//判断当没有更多数据且分页内容未超出z-paging时是否显示没有更多数据的view
|
||||
async _checkShowLoadingMoreWhenNoMoreAndInsideOfPaging(totalData, oldScrollViewNode, oldPagingContainerNode) {
|
||||
try {
|
||||
const scrollViewNode = oldScrollViewNode || await this._getNodeClientRect('.zp-scroll-view');
|
||||
if (this.usePageScroll) {
|
||||
if (scrollViewNode) {
|
||||
const scrollViewTotalH = scrollViewNode[0].top + scrollViewNode[0].height;
|
||||
this.insideOfPaging = scrollViewTotalH < this.windowHeight;
|
||||
if (this.hideLoadingMoreWhenNoMoreAndInsideOfPaging) {
|
||||
this.showLoadingMore = !this.insideOfPaging;
|
||||
}
|
||||
this._updateInsideOfPaging();
|
||||
}
|
||||
} else {
|
||||
let pagingContainerH = 0;
|
||||
let scrollViewH = 0;
|
||||
const pagingContainerNode = oldPagingContainerNode || await this._getNodeClientRect('.zp-paging-container-content');
|
||||
if (pagingContainerNode) {
|
||||
pagingContainerH = pagingContainerNode[0].height;
|
||||
}
|
||||
if (scrollViewNode) {
|
||||
scrollViewH = scrollViewNode[0].height;
|
||||
}
|
||||
this.insideOfPaging = pagingContainerH < scrollViewH;
|
||||
if (this.hideLoadingMoreWhenNoMoreAndInsideOfPaging) {
|
||||
this.showLoadingMore = !this.insideOfPaging;
|
||||
}
|
||||
this._updateInsideOfPaging();
|
||||
}
|
||||
} catch (e) {
|
||||
this.insideOfPaging = !totalData.length;
|
||||
if (this.hideLoadingMoreWhenNoMoreAndInsideOfPaging) {
|
||||
this.showLoadingMore = !this.insideOfPaging;
|
||||
}
|
||||
this._updateInsideOfPaging();
|
||||
}
|
||||
},
|
||||
//是否要展示上拉加载更多view
|
||||
_showLoadingMore(type) {
|
||||
if (!(this.loadingStatus === Enum.More.Default ? this.nShowBottom : true) || !this.totalData.length) return false;
|
||||
if (((!this.showLoadingMoreWhenReload || this.isUserPullDown || this.loadingStatus !== Enum.More.Loading) && !this.showLoadingMore) ||
|
||||
(!this.loadingMoreEnabled && (!this.showLoadingMoreWhenReload || this.isUserPullDown || this.loadingStatus !== Enum.More.Loading)) ||
|
||||
this.refresherOnly) return false;
|
||||
if (this.useChatRecordMode && type !== 'Loading') return false;
|
||||
if (!this.$slots) return false;
|
||||
if (type === 'Custom') {
|
||||
return this.showDefaultLoadingMoreText && !(this.loadingStatus === Enum.More.NoMore && !this.showLoadingMoreNoMoreView);
|
||||
}
|
||||
const res = this.loadingStatus === Enum.More[type] && this.$slots[`loadingMore${type}`] && (type === 'NoMore' ? this.showLoadingMoreNoMoreView : true);
|
||||
if (res) {
|
||||
// #ifdef APP-NVUE
|
||||
if (!this.isIos) {
|
||||
this.nLoadingMoreFixedHeight = false;
|
||||
}
|
||||
// #endif
|
||||
}
|
||||
return res;
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
export default ZPLoadMore;
|
||||
219
components/z-paging/js/modules/nvue.js
Normal file
219
components/z-paging/js/modules/nvue.js
Normal file
@@ -0,0 +1,219 @@
|
||||
// [z-paging]nvue独有部分模块
|
||||
import u from '.././z-paging-utils'
|
||||
import Enum from '.././z-paging-enum'
|
||||
|
||||
// #ifdef APP-NVUE
|
||||
const weexAnimation = weex.requireModule('animation');
|
||||
// #endif
|
||||
const ZPNvue = {
|
||||
props: {
|
||||
//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: function() {
|
||||
return 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: function() {
|
||||
return 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)
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
nRefresherLoading: false,
|
||||
nListIsDragging: false,
|
||||
nShowBottom: true,
|
||||
nFixFreezing: false,
|
||||
nShowRefresherReveal: false,
|
||||
nIsFirstPageAndNoMore: false,
|
||||
nFirstPageAndNoMoreChecked: false,
|
||||
nLoadingMoreFixedHeight: false,
|
||||
nShowRefresherRevealHeight: 0,
|
||||
nRefresherWidth: uni.upx2px(750),
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
nIsFirstPageAndNoMore: {
|
||||
handler(newVal) {
|
||||
const cellStyle = !this.useChatRecordMode || newVal ? {} : {transform: 'rotate(180deg)'};
|
||||
this.$emit('update:cellStyle', cellStyle);
|
||||
},
|
||||
immediate: true
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
// #ifdef APP-NVUE
|
||||
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
|
||||
},
|
||||
methods: {
|
||||
// #ifdef APP-NVUE
|
||||
//列表滚动时触发
|
||||
_nOnScroll(e) {
|
||||
this.$emit('scroll', e);
|
||||
const contentOffsetY = e.contentOffset.y;
|
||||
this.nListIsDragging = e.isDragging;
|
||||
this._checkShouldShowBackToTop(-e.contentOffset.y, -e.contentOffset.y - 1);
|
||||
},
|
||||
//下拉刷新刷新中
|
||||
_nOnRrefresh() {
|
||||
if (this.nShowRefresherReveal) return;
|
||||
this.nRefresherLoading = true;
|
||||
this.refresherStatus = Enum.Refresher.Loading;
|
||||
this._doRefresherLoad();
|
||||
},
|
||||
//下拉刷新下拉中
|
||||
_nOnPullingdown(e) {
|
||||
if (this.refresherStatus === Enum.Refresher.Loading || (this.isIos && !this.nListIsDragging)) return;
|
||||
this._emitTouchmove(e);
|
||||
const viewHeight = e.viewHeight;
|
||||
const pullingDis = e.pullingDistance;
|
||||
this.refresherStatus = pullingDis >= viewHeight ? Enum.Refresher.ReleaseToRefresh : Enum.Refresher.Default;
|
||||
},
|
||||
//下拉刷新结束
|
||||
_nRefresherEnd(doEnd=true) {
|
||||
if (doEnd) {
|
||||
this._nDoRefresherEndAnimation(0, -this.nShowRefresherRevealHeight);
|
||||
!this.usePageScroll && this.$refs['zp-n-list'].resetLoadmore();
|
||||
this.nRefresherLoading = false;
|
||||
}
|
||||
this.$nextTick(() => {
|
||||
setTimeout(()=> {
|
||||
this.nShowBottom = true;
|
||||
}, 10);
|
||||
})
|
||||
},
|
||||
//执行主动触发下拉刷新动画
|
||||
_nDoRefresherEndAnimation(height, translateY, animate = true, checkStack = true) {
|
||||
this._cleanRefresherCompleteTimeout();
|
||||
this._cleanRefresherEndTimeout();
|
||||
if (!this.finalShowRefresherWhenReload) {
|
||||
this.refresherEndTimeout = setTimeout(() => {
|
||||
this.refresherStatus = Enum.Refresher.Default;
|
||||
}, this.refresherCompleteDuration);
|
||||
return;
|
||||
}
|
||||
const stackCount = this.refresherRevealStackCount;
|
||||
if (height === 0 && checkStack) {
|
||||
this.refresherRevealStackCount--;
|
||||
if (stackCount > 1) return;
|
||||
this.refresherEndTimeout = setTimeout(() => {
|
||||
this.refresherStatus = Enum.Refresher.Default;
|
||||
}, this.refresherCompleteDuration);
|
||||
}
|
||||
if (stackCount > 1) {
|
||||
this.refresherStatus = Enum.Refresher.Loading;
|
||||
}
|
||||
const duration = animate ? 120 : 0;
|
||||
weexAnimation.transition(this.$refs['zp-n-list-refresher-reveal'], {
|
||||
styles: {
|
||||
height: `${height}px`,
|
||||
transform: `translateY(${translateY}px)`,
|
||||
},
|
||||
duration: duration,
|
||||
timingFunction: 'linear',
|
||||
needLayout: true,
|
||||
delay: 0
|
||||
})
|
||||
setTimeout(() => {
|
||||
if (animate) {
|
||||
this.nShowRefresherReveal = height > 0;
|
||||
}
|
||||
}, duration > 0 ? duration - 100 : 0);
|
||||
},
|
||||
//滚动到底部加载更多
|
||||
_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() {
|
||||
this.$nextTick(()=>{
|
||||
this._getNodeClientRect('.zp-n-list').then(node => {
|
||||
if (node) {
|
||||
const nodeWidth = node[0].width;
|
||||
this.nRefresherWidth = nodeWidth;
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
}
|
||||
// #endif
|
||||
}
|
||||
}
|
||||
|
||||
export default ZPNvue;
|
||||
632
components/z-paging/js/modules/refresher.js
Normal file
632
components/z-paging/js/modules/refresher.js
Normal file
@@ -0,0 +1,632 @@
|
||||
// [z-paging]下拉刷新view模块
|
||||
import u from '.././z-paging-utils'
|
||||
import c from '.././z-paging-constant'
|
||||
import Enum from '.././z-paging-enum'
|
||||
|
||||
const ZPRefresher = {
|
||||
props: {
|
||||
//下拉刷新的主题样式,支持black,white,默认black
|
||||
refresherThemeStyle: {
|
||||
type: String,
|
||||
default: function() {
|
||||
return u.gc('refresherThemeStyle', '');
|
||||
}
|
||||
},
|
||||
//自定义下拉刷新中左侧图标的样式
|
||||
refresherImgStyle: {
|
||||
type: Object,
|
||||
default: function() {
|
||||
return u.gc('refresherImgStyle', {});
|
||||
}
|
||||
},
|
||||
//自定义下拉刷新中右侧状态描述文字的样式
|
||||
refresherTitleStyle: {
|
||||
type: Object,
|
||||
default: function() {
|
||||
return u.gc('refresherTitleStyle', {});
|
||||
}
|
||||
},
|
||||
//自定义下拉刷新中右侧最后更新时间文字的样式(show-refresher-update-time为true时有效)
|
||||
refresherUpdateTimeStyle: {
|
||||
type: Object,
|
||||
default: function() {
|
||||
return u.gc('refresherUpdateTimeStyle', {});
|
||||
}
|
||||
},
|
||||
//在微信小程序和QQ小程序中,是否实时监听下拉刷新中进度,默认为否
|
||||
watchRefresherTouchmove: {
|
||||
type: Boolean,
|
||||
default: u.gc('watchRefresherTouchmove', false)
|
||||
},
|
||||
//底部加载更多的主题样式,支持black,white,默认black
|
||||
loadingMoreThemeStyle: {
|
||||
type: String,
|
||||
default: function() {
|
||||
return u.gc('loadingMoreThemeStyle', '');
|
||||
}
|
||||
},
|
||||
//是否只使用下拉刷新,设置为true后将关闭mounted自动请求数据、关闭滚动到底部加载更多,强制隐藏空数据图。默认为否
|
||||
refresherOnly: {
|
||||
type: Boolean,
|
||||
default: u.gc('refresherOnly', false)
|
||||
},
|
||||
//自定义下拉刷新默认状态下回弹动画时间,单位为毫秒,默认为100毫秒,nvue无效
|
||||
refresherDefaultDuration: {
|
||||
type: [Number, String],
|
||||
default: u.gc('refresherDefaultDuration', 100)
|
||||
},
|
||||
//自定义下拉刷新结束以后延迟回弹的时间,单位为毫秒,默认为0
|
||||
refresherCompleteDelay: {
|
||||
type: [Number, String],
|
||||
default: u.gc('refresherCompleteDelay', 0)
|
||||
},
|
||||
//自定义下拉刷新结束回弹动画时间,单位为毫秒,默认为300毫秒(refresherEndBounceEnabled为false时,refresherCompleteDuration为设定值的1/3),nvue无效
|
||||
refresherCompleteDuration: {
|
||||
type: [Number, String],
|
||||
default: u.gc('refresherCompleteDuration', 300)
|
||||
},
|
||||
//自定义下拉刷新结束状态下是否允许列表滚动,默认为否
|
||||
refresherCompleteScrollable: {
|
||||
type: Boolean,
|
||||
default: u.gc('refresherCompleteScrollable', false)
|
||||
},
|
||||
//是否使用自定义的下拉刷新,默认为是,即使用z-paging的下拉刷新。设置为false即代表使用uni scroll-view自带的下拉刷新,h5、App、微信小程序以外的平台不支持uni scroll-view自带的下拉刷新
|
||||
useCustomRefresher: {
|
||||
type: Boolean,
|
||||
default: u.gc('useCustomRefresher', true)
|
||||
},
|
||||
//自定义下拉刷新下拉帧率,默认为40,过高可能会出现抖动问题
|
||||
refresherFps: {
|
||||
type: [Number, String],
|
||||
default: u.gc('refresherFps', 40)
|
||||
},
|
||||
//自定义下拉刷新允许触发的最大下拉角度,默认为40度,当下拉角度小于设定值时,自定义下拉刷新动画不会被触发
|
||||
refresherMaxAngle: {
|
||||
type: [Number, String],
|
||||
default: u.gc('refresherMaxAngle', 40)
|
||||
},
|
||||
//自定义下拉刷新的角度由未达到最大角度变到达到最大角度时,是否继续下拉刷新手势,默认为否
|
||||
refresherAngleEnableChangeContinued: {
|
||||
type: Boolean,
|
||||
default: u.gc('refresherAngleEnableChangeContinued', false)
|
||||
},
|
||||
//自定义下拉刷新默认状态下的文字
|
||||
refresherDefaultText: {
|
||||
type: [String, Object],
|
||||
default: u.gc('refresherDefaultText', null)
|
||||
},
|
||||
//自定义下拉刷新松手立即刷新状态下的文字
|
||||
refresherPullingText: {
|
||||
type: [String, Object],
|
||||
default: u.gc('refresherPullingText', null)
|
||||
},
|
||||
//自定义下拉刷新刷新中状态下的文字
|
||||
refresherRefreshingText: {
|
||||
type: [String, Object],
|
||||
default: u.gc('refresherRefreshingText', null)
|
||||
},
|
||||
//自定义下拉刷新刷新结束状态下的文字
|
||||
refresherCompleteText: {
|
||||
type: [String, Object],
|
||||
default: u.gc('refresherCompleteText', null)
|
||||
},
|
||||
//是否开启自定义下拉刷新刷新结束回弹效果,默认为是
|
||||
refresherEndBounceEnabled: {
|
||||
type: Boolean,
|
||||
default: u.gc('refresherEndBounceEnabled', true)
|
||||
},
|
||||
//是否开启自定义下拉刷新,默认为是
|
||||
refresherEnabled: {
|
||||
type: Boolean,
|
||||
default: u.gc('refresherEnabled', true)
|
||||
},
|
||||
//设置自定义下拉刷新阈值,默认为80rpx
|
||||
refresherThreshold: {
|
||||
type: [Number, String],
|
||||
default: u.gc('refresherThreshold', '80rpx')
|
||||
},
|
||||
//设置系统下拉刷新默认样式,支持设置 black,white,none,none 表示不使用默认样式,默认为black
|
||||
refresherDefaultStyle: {
|
||||
type: String,
|
||||
default: u.gc('refresherDefaultStyle', 'black')
|
||||
},
|
||||
//设置自定义下拉刷新区域背景
|
||||
refresherBackground: {
|
||||
type: String,
|
||||
default: u.gc('refresherBackground', 'transparent')
|
||||
},
|
||||
//设置固定的自定义下拉刷新区域背景
|
||||
refresherFixedBackground: {
|
||||
type: String,
|
||||
default: u.gc('refresherFixedBackground', 'transparent')
|
||||
},
|
||||
//设置固定的自定义下拉刷新区域高度,默认为0
|
||||
refresherFixedBacHeight: {
|
||||
type: [Number, String],
|
||||
default: u.gc('refresherFixedBacHeight', 0)
|
||||
},
|
||||
//设置自定义下拉刷新下拉超出阈值后继续下拉位移衰减的比例,范围0-1,值越大代表衰减越多。默认为0.7(nvue无效)
|
||||
refresherOutRate: {
|
||||
type: Number,
|
||||
default: u.gc('refresherOutRate', 0.7)
|
||||
},
|
||||
//是否显示最后更新时间,默认为否
|
||||
showRefresherUpdateTime: {
|
||||
type: Boolean,
|
||||
default: u.gc('showRefresherUpdateTime', false)
|
||||
},
|
||||
//如果需要区别不同页面的最后更新时间,请为不同页面的z-paging的`refresher-update-time-key`设置不同的字符串
|
||||
refresherUpdateTimeKey: {
|
||||
type: String,
|
||||
default: u.gc('refresherUpdateTimeKey', 'default')
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
//下拉刷新状态
|
||||
refresherStatus: Enum.Refresher.Default,
|
||||
refresherTouchstartY: 0,
|
||||
lastRefresherTouchmove: null,
|
||||
refresherReachMaxAngle: true,
|
||||
refresherTransform: 'translateY(0px)',
|
||||
refresherTransition: '',
|
||||
finalRefresherDefaultStyle: 'black',
|
||||
refresherRevealStackCount: 0,
|
||||
refresherCompleteTimeout: null,
|
||||
refresherCompleteSubTimeout: null,
|
||||
refresherEndTimeout: null,
|
||||
isTouchmovingTimeout: null,
|
||||
refresherTriggered: false,
|
||||
isTouchmoving: false,
|
||||
isTouchEnded: false,
|
||||
isUserPullDown: false,
|
||||
privateRefresherEnabled: -1,
|
||||
privateShowRefresherWhenReload: false,
|
||||
customRefresherHeight: -1,
|
||||
showCustomRefresher: false,
|
||||
doRefreshAnimateAfter: false,
|
||||
isRefresherInComplete: false,
|
||||
pullDownTimeStamp: 0,
|
||||
moveDis: 0,
|
||||
oldMoveDis: 0,
|
||||
oldRefresherTouchmoveY: 0,
|
||||
oldTouchDirection: ''
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
refresherDefaultStyle: {
|
||||
handler(newVal) {
|
||||
if (newVal.length) {
|
||||
this.finalRefresherDefaultStyle = newVal;
|
||||
}
|
||||
},
|
||||
immediate: true
|
||||
},
|
||||
refresherStatus(newVal, oldVal) {
|
||||
if (newVal === Enum.Refresher.Loading){
|
||||
this._cleanRefresherEndTimeout();
|
||||
}
|
||||
this.$emit('refresherStatusChange', newVal);
|
||||
this.$emit('update:refresherStatus', newVal);
|
||||
},
|
||||
moveDis(newVal, oldVal){
|
||||
this.oldMoveDis = oldVal;
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
pullDownDisTimeStamp() {
|
||||
return 1000 / this.refresherFps;
|
||||
},
|
||||
finalRefresherEnabled() {
|
||||
if (this.useChatRecordMode) return false;
|
||||
if (this.privateRefresherEnabled === -1) return this.refresherEnabled;
|
||||
return this.privateRefresherEnabled === 1;
|
||||
},
|
||||
finalRefresherThreshold() {
|
||||
let refresherThreshold = this.refresherThreshold;
|
||||
let idDefault = false;
|
||||
if (refresherThreshold === '80rpx') {
|
||||
idDefault = true;
|
||||
if (this.showRefresherUpdateTime) {
|
||||
refresherThreshold = '120rpx';
|
||||
}
|
||||
}
|
||||
if (idDefault && this.customRefresherHeight > 0) {
|
||||
return this.customRefresherHeight;
|
||||
}
|
||||
return u.convertTextToPx(refresherThreshold);
|
||||
},
|
||||
finalRefresherFixedBacHeight() {
|
||||
return u.convertTextToPx(this.refresherFixedBacHeight);
|
||||
},
|
||||
finalRefresherThemeStyle() {
|
||||
return this.refresherThemeStyle.length ? this.refresherThemeStyle : this.defaultThemeStyle;
|
||||
},
|
||||
finalRefresherOutRate() {
|
||||
let rate = this.refresherOutRate;
|
||||
rate = Math.max(0,rate);
|
||||
rate = Math.min(1,rate);
|
||||
return rate;
|
||||
},
|
||||
finalRefresherTransform() {
|
||||
if (this.refresherTransform === 'translateY(0px)') return 'none';
|
||||
return this.refresherTransform;
|
||||
},
|
||||
finalShowRefresherWhenReload() {
|
||||
return this.showRefresherWhenReload || this.privateShowRefresherWhenReload;
|
||||
},
|
||||
finalRefresherTriggered() {
|
||||
if (!(this.finalRefresherEnabled && !this.useCustomRefresher)) return false;
|
||||
return this.refresherTriggered;
|
||||
},
|
||||
showRefresher() {
|
||||
const showRefresher = this.finalRefresherEnabled && this.useCustomRefresher && this.isTouchmoving;
|
||||
// #ifndef APP-NVUE
|
||||
if (this.customRefresherHeight === -1 && showRefresher) {
|
||||
setTimeout(() => {
|
||||
this.$nextTick(()=>{
|
||||
this._updateCustomRefresherHeight();
|
||||
})
|
||||
}, 100)
|
||||
}
|
||||
// #endif
|
||||
return showRefresher;
|
||||
},
|
||||
hasTouchmove(){
|
||||
// #ifdef VUE2
|
||||
// #ifdef APP-VUE || H5
|
||||
if (this.$listeners && !this.$listeners.refresherTouchmove) return false;
|
||||
// #endif
|
||||
// #ifdef MP-WEIXIN || MP-QQ
|
||||
return this.watchRefresherTouchmove;
|
||||
// #endif
|
||||
return true;
|
||||
// #endif
|
||||
return this.watchRefresherTouchmove;
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
//终止下拉刷新状态
|
||||
endRefresh(){
|
||||
this._refresherEnd();
|
||||
},
|
||||
handleRefresherStatusChanged(func) {
|
||||
this.refresherStatusChangedFunc = func;
|
||||
},
|
||||
//自定义下拉刷新被触发
|
||||
_onRefresh(fromScrollView=false,isUserPullDown=true) {
|
||||
if (fromScrollView && !(this.finalRefresherEnabled && !this.useCustomRefresher)) return;
|
||||
this.$emit('onRefresh');
|
||||
this.$emit('Refresh');
|
||||
// #ifdef APP-NVUE
|
||||
if (this.loading) {
|
||||
setTimeout(()=>{
|
||||
this._nRefresherEnd();
|
||||
},500)
|
||||
return;
|
||||
}
|
||||
// #endif
|
||||
if (this.loading || this.isRefresherInComplete) return;
|
||||
this.loadingType = Enum.LoadingType.Refresher;
|
||||
if (this.nShowRefresherReveal) return;
|
||||
this.isUserPullDown = isUserPullDown;
|
||||
this.isUserReload = !isUserPullDown;
|
||||
this._startLoading(true);
|
||||
this.refresherTriggered = true;
|
||||
if(this.reloadWhenRefresh && isUserPullDown){
|
||||
if (this.useChatRecordMode) {
|
||||
this._onLoadingMore('click')
|
||||
} else {
|
||||
this._reload(false, false, isUserPullDown);
|
||||
}
|
||||
}
|
||||
},
|
||||
//自定义下拉刷新被复位
|
||||
_onRestore() {
|
||||
this.refresherTriggered = 'restore';
|
||||
this.$emit('onRestore');
|
||||
this.$emit('Restore');
|
||||
},
|
||||
// #ifndef APP-VUE || MP-WEIXIN || MP-QQ || H5
|
||||
//拖拽开始
|
||||
_refresherTouchstart(e) {
|
||||
if (this._touchDisabled()) return;
|
||||
const touch = u.getTouch(e);
|
||||
this._handleRefresherTouchstart(touch);
|
||||
},
|
||||
// #endif
|
||||
//进一步处理拖拽开始结果
|
||||
_handleRefresherTouchstart(touch) {
|
||||
if (!this.loading && this.isTouchEnded) {
|
||||
this.isTouchmoving = false;
|
||||
}
|
||||
this.isTouchmovingTimeout && clearTimeout(this.isTouchmovingTimeout);
|
||||
this.isTouchEnded = false;
|
||||
this.refresherTransition = '';
|
||||
this.refresherTouchstartY = touch.touchY;
|
||||
this.$emit('refresherTouchstart', this.refresherTouchstartY);
|
||||
this.lastRefresherTouchmove = touch;
|
||||
this._cleanRefresherCompleteTimeout();
|
||||
this._cleanRefresherEndTimeout();
|
||||
},
|
||||
// #ifndef APP-VUE || MP-WEIXIN || MP-QQ || H5
|
||||
//拖拽中
|
||||
_refresherTouchmove(e) {
|
||||
const currentTimeStamp = u.getTime();
|
||||
let touch = null;
|
||||
let refresherTouchmoveY = 0;
|
||||
if (this.watchTouchDirectionChange) {
|
||||
touch = u.getTouch(e);
|
||||
refresherTouchmoveY = touch.touchY;
|
||||
const direction = refresherTouchmoveY > this.oldRefresherTouchmoveY ? 'top' : 'bottom';
|
||||
direction === this.oldTouchDirection && this._handleTouchDirectionChange({direction});
|
||||
this.oldTouchDirection = direction;
|
||||
this.oldRefresherTouchmoveY = refresherTouchmoveY;
|
||||
}
|
||||
if (this.pullDownTimeStamp && currentTimeStamp - this.pullDownTimeStamp <= this.pullDownDisTimeStamp) return;
|
||||
if (this._touchDisabled()) return;
|
||||
this.pullDownTimeStamp = Number(currentTimeStamp);
|
||||
touch = u.getTouch(e);
|
||||
refresherTouchmoveY = touch.touchY;
|
||||
let moveDis = refresherTouchmoveY - this.refresherTouchstartY;
|
||||
if (moveDis < 0) return;
|
||||
if (this.refresherMaxAngle >= 0 && this.refresherMaxAngle <= 90 && this.lastRefresherTouchmove && this.lastRefresherTouchmove.touchY <= refresherTouchmoveY) {
|
||||
if (!moveDis && !this.refresherAngleEnableChangeContinued && this.moveDis < 1 && !this.refresherReachMaxAngle) return;
|
||||
const x = Math.abs(touch.touchX - this.lastRefresherTouchmove.touchX);
|
||||
const y = Math.abs(refresherTouchmoveY - this.lastRefresherTouchmove.touchY);
|
||||
const z = Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2));
|
||||
if ((x || y) && x > 1) {
|
||||
const angle = Math.asin(y / z) / Math.PI * 180;
|
||||
if (angle < this.refresherMaxAngle) {
|
||||
this.lastRefresherTouchmove = touch;
|
||||
this.refresherReachMaxAngle = false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
moveDis = this._getFinalRefresherMoveDis(moveDis);
|
||||
this._handleRefresherTouchmove(moveDis, touch);
|
||||
if (!this.disabledBounce) {
|
||||
if(this.isIos){
|
||||
// #ifndef MP-LARK
|
||||
this._handleScrollViewDisableBounce({bounce: false});
|
||||
// #endif
|
||||
}
|
||||
this.disabledBounce = true;
|
||||
}
|
||||
this._emitTouchmove({pullingDistance:moveDis,dy:this.moveDis - this.oldMoveDis});
|
||||
},
|
||||
// #endif
|
||||
//进一步处理拖拽中结果
|
||||
_handleRefresherTouchmove(moveDis, touch) {
|
||||
this.refresherReachMaxAngle = true;
|
||||
this.isTouchmovingTimeout && clearTimeout(this.isTouchmovingTimeout);
|
||||
this.isTouchmoving = true;
|
||||
//this.refresherTransition = '';
|
||||
this.isTouchEnded = false;
|
||||
this.refresherStatus = moveDis >= this.finalRefresherThreshold ? Enum.Refresher.ReleaseToRefresh : this.refresherStatus = Enum.Refresher.Default;
|
||||
// #ifndef APP-VUE || MP-WEIXIN || MP-QQ || H5
|
||||
// this.scrollEnable = false;
|
||||
this.refresherTransform = `translateY(${moveDis}px)`;
|
||||
this.lastRefresherTouchmove = touch;
|
||||
// #endif
|
||||
this.moveDis = moveDis;
|
||||
},
|
||||
// #ifndef APP-VUE || MP-WEIXIN || MP-QQ || H5
|
||||
//拖拽结束
|
||||
_refresherTouchend(e) {
|
||||
if (this._touchDisabled() || !this.isTouchmoving) return;
|
||||
const touch = u.getTouch(e);
|
||||
let refresherTouchendY = touch.touchY;
|
||||
let moveDis = refresherTouchendY - this.refresherTouchstartY;
|
||||
moveDis = this._getFinalRefresherMoveDis(moveDis);
|
||||
this._handleRefresherTouchend(moveDis);
|
||||
this._handleScrollViewDisableBounce({bounce: true});
|
||||
this.disabledBounce = false;
|
||||
},
|
||||
// #endif
|
||||
//进一步处理拖拽结束结果
|
||||
_handleRefresherTouchend(moveDis) {
|
||||
// #ifndef APP-PLUS || H5 || MP-WEIXIN
|
||||
if (!this.isTouchmoving) return;
|
||||
// #endif
|
||||
this.isTouchmovingTimeout && clearTimeout(this.isTouchmovingTimeout);
|
||||
this.refresherReachMaxAngle = true;
|
||||
if (moveDis < 0 && this.usePageScroll && this.loadingMoreEnabled && this.useCustomRefresher && this.pageScrollTop === -1) {
|
||||
if (this.showConsoleError) {
|
||||
u.consoleErr('usePageScroll为true并且自定义下拉刷新时必须引入mixin或在page滚动时通过调用z-paging组件的updatePageScrollTop方法设置当前的scrollTop');
|
||||
}
|
||||
}
|
||||
this.isTouchEnded = true;
|
||||
if (moveDis >= this.finalRefresherThreshold && this.refresherStatus === Enum.Refresher.ReleaseToRefresh) {
|
||||
// #ifndef APP-VUE || MP-WEIXIN || MP-QQ || H5
|
||||
this.refresherTransform = `translateY(${this.finalRefresherThreshold}px)`;
|
||||
// #endif
|
||||
this.moveDis = this.finalRefresherThreshold;
|
||||
this.refresherStatus = Enum.Refresher.Loading;
|
||||
this._doRefresherLoad();
|
||||
} else {
|
||||
this._refresherEnd();
|
||||
this.isTouchmovingTimeout = setTimeout(() => {
|
||||
this.isTouchmoving = false;
|
||||
}, this.refresherDefaultDuration);
|
||||
}
|
||||
this.scrollEnable = true;
|
||||
this.$emit('refresherTouchend', moveDis);
|
||||
},
|
||||
//处理scroll-view bounce是否生效
|
||||
_handleScrollViewDisableBounce(e) {
|
||||
if (!this.usePageScroll && !this.scrollToTopBounceEnabled) {
|
||||
this.refresherTransition = '';
|
||||
this.scrollEnable = e.bounce;
|
||||
}
|
||||
},
|
||||
//wxs正在下拉状态改变处理
|
||||
_handleWxsPullingDownStatusChange(onPullingDown) {
|
||||
this.wxsOnPullingDown = onPullingDown;
|
||||
if (onPullingDown && !this.useChatRecordMode) {
|
||||
this.renderPropScrollTop = 0;
|
||||
}
|
||||
},
|
||||
//wxs正在下拉处理
|
||||
_handleWxsPullingDown(e){
|
||||
this._emitTouchmove({pullingDistance:e.moveDis,dy:e.diffDis});
|
||||
},
|
||||
//wxs触摸方向改变
|
||||
_handleTouchDirectionChange(e) {
|
||||
this.$emit('touchDirectionChange',e.direction);
|
||||
},
|
||||
//wxs通知更新其props
|
||||
_handlePropUpdate(e){
|
||||
this.wxsPropType = u.getTime().toString();
|
||||
},
|
||||
//下拉刷新结束
|
||||
_refresherEnd(shouldEndLoadingDelay = true, fromAddData = false, isUserPullDown = false, setLoading = true) {
|
||||
if (this.loadingType === Enum.LoadingType.Refresher) {
|
||||
let refresherCompleteDelay = 0;
|
||||
if(fromAddData && (isUserPullDown || this.showRefresherWhenReload)){
|
||||
refresherCompleteDelay = this.refresherCompleteDuration > 700 ? 1 : this.refresherCompleteDelay;
|
||||
}
|
||||
const refresherStatus = refresherCompleteDelay > 0 ? Enum.Refresher.Complete : Enum.Refresher.Default;
|
||||
if (this.finalShowRefresherWhenReload) {
|
||||
const stackCount = this.refresherRevealStackCount;
|
||||
this.refresherRevealStackCount--;
|
||||
if (stackCount > 1) return;
|
||||
}
|
||||
this._cleanRefresherEndTimeout();
|
||||
this.refresherEndTimeout = setTimeout(() => {
|
||||
this.refresherStatus = refresherStatus;
|
||||
}, this.refresherStatus !== Enum.Refresher.Default && refresherStatus === Enum.Refresher.Default ? this.refresherCompleteDuration : 0);
|
||||
|
||||
// #ifndef APP-NVUE
|
||||
if (refresherCompleteDelay > 0) {
|
||||
this.isRefresherInComplete = true;
|
||||
}
|
||||
// #endif
|
||||
this._cleanRefresherCompleteTimeout();
|
||||
this.refresherCompleteTimeout = setTimeout(() => {
|
||||
let animateDuration = 1;
|
||||
const animateType = this.refresherEndBounceEnabled && fromAddData ? 'cubic-bezier(0.19,1.64,0.42,0.72)' : 'linear';
|
||||
if (fromAddData) {
|
||||
animateDuration = this.refresherEndBounceEnabled ? this.refresherCompleteDuration / 1000 : this.refresherCompleteDuration / 3000;
|
||||
}
|
||||
this.refresherTransition = `transform ${fromAddData ? animateDuration : this.refresherDefaultDuration / 1000}s ${animateType}`;
|
||||
// #ifndef APP-VUE || MP-WEIXIN || MP-QQ || H5
|
||||
this.refresherTransform = 'translateY(0px)';
|
||||
// #endif
|
||||
// #ifdef APP-VUE || MP-WEIXIN || MP-QQ || H5
|
||||
this.wxsPropType = this.refresherTransition + 'end' + u.getTime();
|
||||
// #endif
|
||||
// #ifdef APP-NVUE
|
||||
this._nRefresherEnd();
|
||||
// #endif
|
||||
this.moveDis = 0;
|
||||
// #ifndef APP-NVUE
|
||||
if (refresherStatus === Enum.Refresher.Complete) {
|
||||
if (this.refresherCompleteSubTimeout) {
|
||||
clearTimeout(this.refresherCompleteSubTimeout);
|
||||
this.refresherCompleteSubTimeout = null;
|
||||
}
|
||||
this.refresherCompleteSubTimeout = setTimeout(() => {
|
||||
this.$nextTick(() => {
|
||||
this.refresherStatus = Enum.Refresher.Default;
|
||||
this.isRefresherInComplete = false;
|
||||
})
|
||||
}, animateDuration * 800);
|
||||
}
|
||||
// #endif
|
||||
}, refresherCompleteDelay);
|
||||
}
|
||||
if (setLoading) {
|
||||
setTimeout(() => {
|
||||
this.loading = false;
|
||||
}, shouldEndLoadingDelay ? c.delayTime : 0);
|
||||
isUserPullDown && this._onRestore();
|
||||
}
|
||||
},
|
||||
//模拟用户手动触发下拉刷新
|
||||
_doRefresherRefreshAnimate() {
|
||||
this._cleanRefresherCompleteTimeout();
|
||||
// #ifndef APP-NVUE
|
||||
const doRefreshAnimateAfter = !this.doRefreshAnimateAfter && (this.finalShowRefresherWhenReload) && this
|
||||
.customRefresherHeight === -1 && this.refresherThreshold === '80rpx';
|
||||
if (doRefreshAnimateAfter) {
|
||||
this.doRefreshAnimateAfter = true;
|
||||
return;
|
||||
}
|
||||
// #endif
|
||||
this.refresherRevealStackCount++;
|
||||
// #ifndef APP-VUE || MP-WEIXIN || MP-QQ || H5
|
||||
this.refresherTransform = `translateY(${this.finalRefresherThreshold}px)`;
|
||||
// #endif
|
||||
// #ifdef APP-VUE || MP-WEIXIN || MP-QQ || H5
|
||||
this.wxsPropType = 'begin' + u.getTime();
|
||||
// #endif
|
||||
this.moveDis = this.finalRefresherThreshold;
|
||||
this.refresherStatus = Enum.Refresher.Loading;
|
||||
this.isTouchmoving = true;
|
||||
this.isTouchmovingTimeout && clearTimeout(this.isTouchmovingTimeout);
|
||||
this._doRefresherLoad(false);
|
||||
},
|
||||
//触发下拉刷新
|
||||
_doRefresherLoad(isUserPullDown=true) {
|
||||
this._onRefresh(false,isUserPullDown);
|
||||
this.loading = true;
|
||||
},
|
||||
//获取处理后的moveDis
|
||||
_getFinalRefresherMoveDis(moveDis) {
|
||||
moveDis = moveDis * 0.85;
|
||||
if (moveDis >= this.finalRefresherThreshold) {
|
||||
moveDis = this.finalRefresherThreshold + (moveDis - this.finalRefresherThreshold) * (1 - this.finalRefresherOutRate);
|
||||
}
|
||||
return moveDis;
|
||||
},
|
||||
// #ifndef APP-VUE || MP-WEIXIN || MP-QQ || H5
|
||||
//判断touch手势是否要触发
|
||||
_touchDisabled() {
|
||||
let checkOldScrollTop = this.oldScrollTop > 5;
|
||||
return this.loading || this.isRefresherInComplete || this.useChatRecordMode || !this.refresherEnabled || !this.useCustomRefresher ||(this.usePageScroll && this.useCustomRefresher && this.pageScrollTop > 10) || (!(this.usePageScroll && this.useCustomRefresher) && checkOldScrollTop);
|
||||
},
|
||||
// #endif
|
||||
//更新自定义下拉刷新view高度
|
||||
_updateCustomRefresherHeight() {
|
||||
this._getNodeClientRect('.zp-custom-refresher-slot-view').then((res) => {
|
||||
if (res) {
|
||||
this.customRefresherHeight = res[0].height;
|
||||
if (this.customRefresherHeight > 0) {
|
||||
this.showCustomRefresher = true;
|
||||
}
|
||||
} else {
|
||||
this.customRefresherHeight = 0;
|
||||
}
|
||||
if (this.doRefreshAnimateAfter) {
|
||||
this.doRefreshAnimateAfter = false;
|
||||
this._doRefresherRefreshAnimate();
|
||||
}
|
||||
});
|
||||
},
|
||||
//发射pullingDown事件
|
||||
_emitTouchmove(e){
|
||||
// #ifndef APP-NVUE
|
||||
e.viewHeight = this.finalRefresherThreshold;
|
||||
// #endif
|
||||
e.rate = e.pullingDistance / e.viewHeight;
|
||||
if(this.hasTouchmove){
|
||||
this.$emit('refresherTouchmove',e);
|
||||
}
|
||||
},
|
||||
//清除refresherCompleteTimeout
|
||||
_cleanRefresherCompleteTimeout() {
|
||||
this.refresherCompleteTimeout = this._cleanTimeout(this.refresherCompleteTimeout);
|
||||
// #ifdef APP-NVUE
|
||||
this._nRefresherEnd(false);
|
||||
// #endif
|
||||
},
|
||||
//清除refresherEndTimeout
|
||||
_cleanRefresherEndTimeout() {
|
||||
this.refresherEndTimeout = this._cleanTimeout(this.refresherEndTimeout);
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
export default ZPRefresher;
|
||||
469
components/z-paging/js/modules/scroller.js
Normal file
469
components/z-paging/js/modules/scroller.js
Normal file
@@ -0,0 +1,469 @@
|
||||
// [z-paging]scroll相关模块
|
||||
import u from '.././z-paging-utils'
|
||||
import Enum from '.././z-paging-enum'
|
||||
|
||||
// #ifdef APP-NVUE
|
||||
const weexDom = weex.requireModule('dom');
|
||||
// #endif
|
||||
const ZPScroller = {
|
||||
props: {
|
||||
//使用页面滚动,默认为否,当设置为是时则使用页面的滚动而非此组件内部的scroll-view的滚动,使用页面滚动时z-paging无需设置确定的高度且对于长列表展示性能更高,但配置会略微繁琐
|
||||
usePageScroll: {
|
||||
type: Boolean,
|
||||
default: u.gc('usePageScroll', false)
|
||||
},
|
||||
//是否可以滚动,使用内置scroll-view和nvue时有效,默认为是
|
||||
scrollable: {
|
||||
type: Boolean,
|
||||
default: u.gc('scrollable', true)
|
||||
},
|
||||
//控制是否出现滚动条,默认为是
|
||||
showScrollbar: {
|
||||
type: Boolean,
|
||||
default: u.gc('showScrollbar', true)
|
||||
},
|
||||
//是否允许横向滚动,默认为否
|
||||
scrollX: {
|
||||
type: Boolean,
|
||||
default: u.gc('scrollX', false)
|
||||
},
|
||||
//iOS设备上滚动到顶部时是否允许回弹效果,默认为否。关闭回弹效果后可使滚动到顶部与下拉刷新更连贯,但是有吸顶view时滚动到顶部时可能出现抖动。
|
||||
scrollToTopBounceEnabled: {
|
||||
type: Boolean,
|
||||
default: u.gc('scrollToTopBounceEnabled', false)
|
||||
},
|
||||
//iOS设备上滚动到底部时是否允许回弹效果,默认为是。
|
||||
scrollToBottomBounceEnabled: {
|
||||
type: Boolean,
|
||||
default: u.gc('scrollToBottomBounceEnabled', true)
|
||||
},
|
||||
//在设置滚动条位置时使用动画过渡,默认为否
|
||||
scrollWithAnimation: {
|
||||
type: Boolean,
|
||||
default: u.gc('scrollWithAnimation', false)
|
||||
},
|
||||
//值应为某子元素id(id不能以数字开头)。设置哪个方向可滚动,则在哪个方向滚动到该元素
|
||||
scrollIntoView: {
|
||||
type: String,
|
||||
default: u.gc('scrollIntoView', '')
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
scrollTop: 0,
|
||||
oldScrollTop: 0,
|
||||
scrollViewStyle: {},
|
||||
scrollViewContainerStyle: {},
|
||||
scrollViewInStyle: {},
|
||||
pageScrollTop: -1,
|
||||
scrollEnable: true,
|
||||
privateScrollWithAnimation: -1,
|
||||
cacheScrollNodeHeight: -1
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
oldScrollTop(newVal, oldVal) {
|
||||
!this.usePageScroll && this._scrollTopChange(newVal,oldVal,false);
|
||||
},
|
||||
pageScrollTop(newVal, oldVal) {
|
||||
this.usePageScroll && this._scrollTopChange(newVal,oldVal,true);
|
||||
},
|
||||
usePageScroll: {
|
||||
handler(newVal) {
|
||||
this.$nextTick(() => {
|
||||
this.renderPropUsePageScroll = newVal;
|
||||
})
|
||||
if (this.loaded && this.autoHeight) {
|
||||
this._setAutoHeight(!newVal);
|
||||
}
|
||||
// #ifdef H5
|
||||
if (newVal) {
|
||||
this.$nextTick(()=>{
|
||||
const mainScrollRef = this.$refs['zp-scroll-view'].$refs.main;
|
||||
if (mainScrollRef) {
|
||||
mainScrollRef.style = {};
|
||||
}
|
||||
})
|
||||
}
|
||||
// #endif
|
||||
},
|
||||
immediate: true
|
||||
},
|
||||
finalScrollTop(newVal, oldVal) {
|
||||
if (!this.useChatRecordMode) {
|
||||
this.renderPropScrollTop = newVal < 6 ? 0 : 10;
|
||||
}
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
finalScrollWithAnimation() {
|
||||
if (this.privateScrollWithAnimation !== -1) {
|
||||
const scrollWithAnimation = this.privateScrollWithAnimation === 1;
|
||||
this.privateScrollWithAnimation = -1;
|
||||
return scrollWithAnimation;
|
||||
}
|
||||
return this.scrollWithAnimation;
|
||||
},
|
||||
finalScrollViewStyle() {
|
||||
if (this.superContentZIndex != 1) {
|
||||
this.scrollViewStyle['z-index'] = this.superContentZIndex;
|
||||
this.scrollViewStyle['position'] = 'relative';
|
||||
}
|
||||
return this.scrollViewStyle;
|
||||
},
|
||||
finalScrollTop() {
|
||||
return this.usePageScroll ? this.pageScrollTop : this.oldScrollTop;
|
||||
},
|
||||
finalIsOldWebView() {
|
||||
return this.isOldWebView && !this.usePageScroll;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
//滚动到顶部,animate为是否展示滚动动画,默认为是
|
||||
scrollToTop(animate,checkReverse = true) {
|
||||
// #ifdef APP-NVUE
|
||||
if (checkReverse && this.useChatRecordMode) {
|
||||
if(!this.nIsFirstPageAndNoMore){
|
||||
this.scrollToBottom(animate, false);
|
||||
return;
|
||||
}
|
||||
}
|
||||
// #endif
|
||||
this.$nextTick(() => {
|
||||
this._scrollToTop(animate, false);
|
||||
// #ifdef APP-NVUE
|
||||
if (this.nvueFastScroll && animate) {
|
||||
setTimeout(() => {
|
||||
this._scrollToTop(false, false);
|
||||
}, 150);
|
||||
}
|
||||
// #endif
|
||||
})
|
||||
},
|
||||
//滚动到底部,animate为是否展示滚动动画,默认为是
|
||||
scrollToBottom(animate,checkReverse = true) {
|
||||
// #ifdef APP-NVUE
|
||||
if (checkReverse && this.useChatRecordMode) {
|
||||
if(!this.nIsFirstPageAndNoMore){
|
||||
this.scrollToTop(animate, false);
|
||||
return;
|
||||
}
|
||||
}
|
||||
// #endif
|
||||
this.$nextTick(() => {
|
||||
this._scrollToBottom(animate);
|
||||
// #ifdef APP-NVUE
|
||||
if (this.nvueFastScroll && animate) {
|
||||
setTimeout(() => {
|
||||
this._scrollToBottom(false);
|
||||
}, 150);
|
||||
}
|
||||
// #endif
|
||||
})
|
||||
},
|
||||
//滚动到指定view(vue中有效)。sel为需要滚动的view的id值,不包含"#";offset为偏移量,单位为px;animate为是否展示滚动动画,默认为否
|
||||
scrollIntoViewById(sel, offset, animate) {
|
||||
this._scrollIntoView(sel, offset, animate);
|
||||
},
|
||||
//滚动到指定view(vue中有效)。nodeTop为需要滚动的view的top值(通过uni.createSelectorQuery()获取);offset为偏移量,单位为px;animate为是否展示滚动动画,默认为否
|
||||
scrollIntoViewByNodeTop(nodeTop, offset, animate) {
|
||||
this.scrollTop = this.oldScrollTop;
|
||||
this.$nextTick(() => {
|
||||
this._scrollIntoViewByNodeTop(nodeTop, offset, animate);
|
||||
})
|
||||
},
|
||||
//滚动到指定位置(vue中有效)。y为与顶部的距离,单位为px;offset为偏移量,单位为px;animate为是否展示滚动动画,默认为否
|
||||
scrollToY(y, offset, animate) {
|
||||
this.scrollTop = this.oldScrollTop;
|
||||
this.$nextTick(() => {
|
||||
this._scrollToY(y, offset, animate);
|
||||
})
|
||||
},
|
||||
//滚动到指定view(nvue中有效)。index为需要滚动的view的index(第几个);offset为偏移量,单位为px;animate为是否展示滚动动画,默认为否
|
||||
scrollIntoViewByIndex(index, offset, animate) {
|
||||
this._scrollIntoView(index, offset, animate);
|
||||
},
|
||||
//滚动到指定view(nvue中有效)。view为需要滚动的view(通过`this.$refs.xxx`获取),不包含"#";offset为偏移量,单位为px;animate为是否展示滚动动画,默认为否
|
||||
scrollIntoViewByView(view, offset, animate) {
|
||||
this._scrollIntoView(view, offset, animate);
|
||||
},
|
||||
//当使用页面滚动并且自定义下拉刷新时,请在页面的onPageScroll中调用此方法,告知z-paging当前的pageScrollTop,否则会导致在任意位置都可以下拉刷新
|
||||
updatePageScrollTop(value) {
|
||||
if (value == undefined) {
|
||||
u.consoleErr('updatePageScrollTop方法缺少参数,请将页面onPageScroll事件中的scrollTop传递给此方法');
|
||||
return;
|
||||
}
|
||||
this.pageScrollTop = value;
|
||||
},
|
||||
//当使用页面滚动并且设置了slot="top"时,默认初次加载会自动获取其高度,并使内部容器下移,当slot="top"的view高度动态改变时,在其高度需要更新时调用此方法
|
||||
updatePageScrollTopHeight() {
|
||||
this._updatePageScrollTopOrBottomHeight('top');
|
||||
},
|
||||
//当使用页面滚动并且设置了slot="bottom"时,默认初次加载会自动获取其高度,并使内部容器下移,当slot="bottom"的view高度动态改变时,在其高度需要更新时调用此方法
|
||||
updatePageScrollBottomHeight() {
|
||||
this._updatePageScrollTopOrBottomHeight('bottom');
|
||||
},
|
||||
//更新z-paging内置scroll-view的scrollTop
|
||||
updateScrollViewScrollTop(scrollTop, animate = true) {
|
||||
this.privateScrollWithAnimation = animate ? 1 : 0;
|
||||
this.scrollTop = this.oldScrollTop;
|
||||
this.$nextTick(() => {
|
||||
this.scrollTop = scrollTop;
|
||||
this.oldScrollTop = this.scrollTop;
|
||||
});
|
||||
},
|
||||
|
||||
//当滚动到顶部时
|
||||
_scrollToUpper() {
|
||||
this.$emit('scrolltoupper');
|
||||
this.$emit('scrollTopChange', 0);
|
||||
this.$nextTick(() => {
|
||||
this.oldScrollTop = 0;
|
||||
})
|
||||
if (!this.useChatRecordMode) return;
|
||||
if (this.loadingStatus === Enum.More.NoMore) return;
|
||||
this._onLoadingMore('click');
|
||||
},
|
||||
//滚动到顶部
|
||||
_scrollToTop(animate = true, isPrivate = true) {
|
||||
// #ifdef APP-NVUE
|
||||
const el = this.$refs['zp-n-list-top-tag'];
|
||||
if (this.usePageScroll) {
|
||||
this._getNodeClientRect('zp-page-scroll-top', false).then((node) => {
|
||||
let nodeHeight = 0;
|
||||
if (node) {
|
||||
nodeHeight = node[0].height;
|
||||
}
|
||||
weexDom.scrollToElement(el, {
|
||||
offset: -nodeHeight,
|
||||
animated: animate
|
||||
});
|
||||
});
|
||||
} else {
|
||||
if(!this.isIos && this.nvueListIs === 'scroller'){
|
||||
this._getNodeClientRect('zp-n-refresh-container', false).then((node) => {
|
||||
let nodeHeight = 0;
|
||||
if (node) {
|
||||
nodeHeight = node[0].height;
|
||||
}
|
||||
weexDom.scrollToElement(el, {
|
||||
offset: -nodeHeight,
|
||||
animated: animate
|
||||
});
|
||||
});
|
||||
}else{
|
||||
weexDom.scrollToElement(el, {
|
||||
offset: 0,
|
||||
animated: animate
|
||||
});
|
||||
}
|
||||
}
|
||||
return;
|
||||
// #endif
|
||||
if (this.usePageScroll) {
|
||||
this.$nextTick(() => {
|
||||
uni.pageScrollTo({
|
||||
scrollTop: 0,
|
||||
duration: animate ? 100 : 0,
|
||||
});
|
||||
});
|
||||
return;
|
||||
}
|
||||
this.privateScrollWithAnimation = animate ? 1 : 0;
|
||||
this.scrollTop = this.oldScrollTop;
|
||||
this.$nextTick(() => {
|
||||
this.scrollTop = 0;
|
||||
this.oldScrollTop = this.scrollTop;
|
||||
});
|
||||
},
|
||||
//滚动到底部
|
||||
async _scrollToBottom(animate = true) {
|
||||
// #ifdef APP-NVUE
|
||||
const el = this.$refs['zp-n-list-bottom-tag'];
|
||||
if (el) {
|
||||
weexDom.scrollToElement(el, {
|
||||
offset: 0,
|
||||
animated: animate
|
||||
});
|
||||
} else {
|
||||
u.consoleErr('滚动到底部失败,因为您设置了hideNvueBottomTag为true');
|
||||
}
|
||||
return;
|
||||
// #endif
|
||||
if (this.usePageScroll) {
|
||||
this.$nextTick(() => {
|
||||
uni.pageScrollTo({
|
||||
scrollTop: Number.MAX_VALUE,
|
||||
duration: animate ? 100 : 0,
|
||||
});
|
||||
});
|
||||
return;
|
||||
}
|
||||
try {
|
||||
this.privateScrollWithAnimation = animate ? 1 : 0;
|
||||
let pagingContainerH = 0;
|
||||
let scrollViewH = 0;
|
||||
const pagingContainerNode = await this._getNodeClientRect('.zp-paging-container');
|
||||
const scrollViewNode = await this._getNodeClientRect('.zp-scroll-view');
|
||||
if (pagingContainerNode) {
|
||||
pagingContainerH = pagingContainerNode[0].height;
|
||||
}
|
||||
if (scrollViewNode) {
|
||||
scrollViewH = scrollViewNode[0].height;
|
||||
}
|
||||
if (pagingContainerH > scrollViewH) {
|
||||
this.scrollTop = this.oldScrollTop;
|
||||
this.$nextTick(() => {
|
||||
this.scrollTop = pagingContainerH - scrollViewH + this.virtualPlaceholderTopHeight;
|
||||
this.oldScrollTop = this.scrollTop;
|
||||
});
|
||||
}
|
||||
} catch (e) {}
|
||||
},
|
||||
//滚动到指定view
|
||||
_scrollIntoView(sel, offset = 0, animate = false, finishCallback) {
|
||||
try {
|
||||
this.scrollTop = this.oldScrollTop;
|
||||
this.$nextTick(() => {
|
||||
// #ifdef APP-NVUE
|
||||
const refs = this.$parent.$refs;
|
||||
if (!refs) return;
|
||||
const dataType = Object.prototype.toString.call(sel);
|
||||
let el = null;
|
||||
if (dataType === '[object Number]') {
|
||||
const els = refs[`z-paging-${sel}`];
|
||||
el = els ? els[0] : null;
|
||||
} else if (dataType === '[object Array]') {
|
||||
el = sel[0];
|
||||
} else {
|
||||
el = sel;
|
||||
}
|
||||
if (el) {
|
||||
weexDom.scrollToElement(el, {
|
||||
offset: -offset,
|
||||
animated: animate
|
||||
});
|
||||
} else {
|
||||
u.consoleErr('在nvue中滚动到指定位置,cell必须设置 :ref="`z-paging-${index}`"');
|
||||
}
|
||||
return;
|
||||
// #endif
|
||||
if (sel.indexOf('#') != -1) {
|
||||
sel = sel.replace('#', '');
|
||||
}
|
||||
this._getNodeClientRect('#' + sel, false).then((node) => {
|
||||
if (node) {
|
||||
let nodeTop = node[0].top;
|
||||
this._scrollIntoViewByNodeTop(nodeTop, offset, animate);
|
||||
if (finishCallback) {
|
||||
finishCallback();
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
} catch (e) {}
|
||||
},
|
||||
//通过nodeTop滚动到指定view
|
||||
_scrollIntoViewByNodeTop(nodeTop, offset = 0, animate = false) {
|
||||
this._scrollToY(nodeTop,offset,animate,true);
|
||||
},
|
||||
//滚动到指定位置
|
||||
_scrollToY(y, offset = 0, animate = false, addScrollTop = false) {
|
||||
this.privateScrollWithAnimation = animate ? 1 : 0;
|
||||
if (this.usePageScroll) {
|
||||
uni.pageScrollTo({
|
||||
scrollTop: y - offset,
|
||||
duration: animate ? 100 : 0
|
||||
});
|
||||
} else {
|
||||
if(addScrollTop){
|
||||
y += this.oldScrollTop;
|
||||
}
|
||||
this.scrollTop = y - offset;
|
||||
this.oldScrollTop = this.scrollTop;
|
||||
}
|
||||
},
|
||||
//scroll-view滚动中
|
||||
_scroll(e) {
|
||||
this.$emit('scroll', e);
|
||||
const scrollTop = e.detail.scrollTop;
|
||||
// #ifndef APP-NVUE
|
||||
this.finalUseVirtualList && this._updateVirtualScroll(scrollTop,this.oldScrollTop - scrollTop);
|
||||
// #endif
|
||||
this.oldScrollTop = scrollTop;
|
||||
const scrollDiff = e.detail.scrollHeight - this.oldScrollTop;
|
||||
!this.isIos && this._checkScrolledToBottom(scrollDiff);
|
||||
},
|
||||
//scrollTop改变时触发
|
||||
_scrollTopChange(newVal,oldVal,isPageScrollTop){
|
||||
this.$emit('scrollTopChange', newVal);
|
||||
this.$emit('update:scrollTop', newVal);
|
||||
this._checkShouldShowBackToTop(newVal, oldVal);
|
||||
const scrollTop = this.isIos ? (newVal > 5 ? 6 : 0) : newVal;
|
||||
if (isPageScrollTop) {
|
||||
this.wxsPageScrollTop = scrollTop;
|
||||
} else {
|
||||
this.wxsScrollTop = scrollTop;
|
||||
}
|
||||
},
|
||||
//更新使用页面滚动时slot="top"或"bottom"插入view的高度
|
||||
_updatePageScrollTopOrBottomHeight(type) {
|
||||
// #ifndef APP-NVUE
|
||||
if (!this.usePageScroll) return;
|
||||
// #endif
|
||||
this._doCheckScrollViewShouldFullHeight(this.realTotalData);
|
||||
const node = `.zp-page-${type}`;
|
||||
const marginText = `margin${type.slice(0,1).toUpperCase() + type.slice(1)}`;
|
||||
let safeAreaInsetBottomAdd = this.safeAreaInsetBottom;
|
||||
// #ifdef APP-NVUE
|
||||
if (!this.usePageScroll) {
|
||||
safeAreaInsetBottomAdd = false;
|
||||
}
|
||||
// #endif
|
||||
this.$nextTick(() => {
|
||||
let delayTime = 0;
|
||||
// #ifdef MP-BAIDU || APP-NVUE
|
||||
delayTime = 10;
|
||||
// #endif
|
||||
setTimeout(() => {
|
||||
this._getNodeClientRect(node).then((res) => {
|
||||
if (res) {
|
||||
let pageScrollNodeHeight = res[0].height;
|
||||
if (type === 'bottom') {
|
||||
if (safeAreaInsetBottomAdd) {
|
||||
pageScrollNodeHeight += this.safeAreaBottom;
|
||||
}
|
||||
} else {
|
||||
this.cacheTopHeight = pageScrollNodeHeight;
|
||||
}
|
||||
this.$set(this.scrollViewStyle, marginText,
|
||||
`${pageScrollNodeHeight}px`);
|
||||
} else if (safeAreaInsetBottomAdd) {
|
||||
this.$set(this.scrollViewStyle, marginText, `${this.safeAreaBottom}px`);
|
||||
}
|
||||
});
|
||||
}, delayTime)
|
||||
})
|
||||
},
|
||||
//获取slot="left"和slot="right"宽度并且更新布局
|
||||
_updateLeftAndRightWidth(){
|
||||
if (!this.finalIsOldWebView) return;
|
||||
this.$nextTick(() => {
|
||||
let delayTime = 0;
|
||||
// #ifdef MP-BAIDU
|
||||
delayTime = 10;
|
||||
// #endif
|
||||
setTimeout(() => {
|
||||
this._getNodeClientRect('.zp-page-left').then((res) => {
|
||||
this.scrollViewContainerStyle['left'] = res ? res[0].width + 'px' : 0;
|
||||
});
|
||||
this._getNodeClientRect('.zp-page-right').then((res) => {
|
||||
this.scrollViewContainerStyle['right'] = res ? res[0].width + 'px' : 0;
|
||||
});
|
||||
}, delayTime)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default ZPScroller;
|
||||
374
components/z-paging/js/modules/virtual-list.js
Normal file
374
components/z-paging/js/modules/virtual-list.js
Normal file
@@ -0,0 +1,374 @@
|
||||
// [z-paging]虚拟列表模块
|
||||
import u from '.././z-paging-utils'
|
||||
import c from '.././z-paging-constant'
|
||||
import Enum from '.././z-paging-enum'
|
||||
|
||||
const ZPVirtualList = {
|
||||
props: {
|
||||
//是否使用虚拟列表,默认为否
|
||||
useVirtualList: {
|
||||
type: Boolean,
|
||||
default: u.gc('useVirtualList', false)
|
||||
},
|
||||
//是否在z-paging内部循环渲染列表(内置列表),默认为否。若use-virtual-list为true,则此项恒为true
|
||||
useInnerList: {
|
||||
type: Boolean,
|
||||
default: u.gc('useInnerList', false)
|
||||
},
|
||||
//强制关闭inner-list,默认为false,如果为true将强制关闭innerList,适用于开启了虚拟列表后需要强制关闭inner-list的情况
|
||||
forceCloseInnerList: {
|
||||
type: Boolean,
|
||||
default: u.gc('forceCloseInnerList', false)
|
||||
},
|
||||
//内置列表cell的key名称,仅nvue有效,在nvue中开启use-inner-list时必须填此项
|
||||
cellKeyName: {
|
||||
type: String,
|
||||
default: u.gc('cellKeyName', '')
|
||||
},
|
||||
//innerList样式
|
||||
innerListStyle: {
|
||||
type: Object,
|
||||
default: function() {
|
||||
return u.gc('innerListStyle', {});
|
||||
}
|
||||
},
|
||||
//innerCell样式
|
||||
innerCellStyle: {
|
||||
type: Object,
|
||||
default: function() {
|
||||
return u.gc('innerCellStyle', {});
|
||||
}
|
||||
},
|
||||
//预加载的列表可视范围(列表高度)页数,默认为7,即预加载当前页及上下各7页的cell。此数值越大,则虚拟列表中加载的dom越多,内存消耗越大(会维持在一个稳定值),但增加预加载页面数量可缓解快速滚动短暂白屏问题
|
||||
preloadPage: {
|
||||
type: [Number, String],
|
||||
default: u.gc('preloadPage', 7),
|
||||
validator: (value) => {
|
||||
if (value <= 0) u.consoleErr('preload-page必须大于0!');
|
||||
return value > 0;
|
||||
}
|
||||
},
|
||||
//虚拟列表cell高度模式,默认为fixed,也就是每个cell高度完全相同,将以第一个cell高度为准进行计算。可选值【dynamic】,即代表高度是动态非固定的,【dynamic】性能低于【fixed】。
|
||||
cellHeightMode: {
|
||||
type: String,
|
||||
default: u.gc('cellHeightMode', 'fixed')
|
||||
},
|
||||
//虚拟列表列数,默认为1。常用于每行有多列的情况,例如每行有2列数据,需要将此值设置为2
|
||||
virtualListCol: {
|
||||
type: [Number, String],
|
||||
default: u.gc('virtualListCol', 1)
|
||||
},
|
||||
//虚拟列表scroll取样帧率,默认为60,过高可能出现卡顿等问题
|
||||
virtualScrollFps: {
|
||||
type: [Number, String],
|
||||
default: u.gc('virtualScrollFps', 60)
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
virtualListKey: u.getInstanceId(),
|
||||
virtualPageHeight: 0,
|
||||
virtualCellHeight: 0,
|
||||
virtualScrollTimeStamp: 0,
|
||||
|
||||
virtualList: [],
|
||||
virtualPlaceholderTopHeight: 0,
|
||||
virtualPlaceholderBottomHeight: 0,
|
||||
virtualTopRangeIndex: 0,
|
||||
virtualBottomRangeIndex: 0,
|
||||
lastVirtualTopRangeIndex: 0,
|
||||
lastVirtualBottomRangeIndex: 0,
|
||||
|
||||
virtualHeightCacheList: [],
|
||||
|
||||
getCellHeightRetryCount: {
|
||||
fixed: 0,
|
||||
dynamic: 0
|
||||
},
|
||||
pagingOrgTop: -1,
|
||||
updateVirtualListFromDataChange: false
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
realTotalData(newVal) {
|
||||
// #ifndef APP-NVUE
|
||||
if (this.finalUseVirtualList) {
|
||||
this.updateVirtualListFromDataChange = true;
|
||||
this.$nextTick(() => {
|
||||
if (!newVal.length) {
|
||||
this._resetDynamicListState(!this.isUserPullDown);
|
||||
}
|
||||
this.getCellHeightRetryCount.fixed = 0;
|
||||
this.finalUseVirtualList && newVal.length && this.cellHeightMode === Enum.CellHeightMode.Fixed && this.isFirstPage && this._updateFixedCellHeight();
|
||||
this.finalUseVirtualList && this._updateVirtualScroll(this.oldScrollTop);
|
||||
})
|
||||
}
|
||||
// #endif
|
||||
},
|
||||
virtualList(newVal){
|
||||
this.$emit('update:virtualList', newVal);
|
||||
this.$emit('virtualListChange', newVal);
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
finalUseVirtualList() {
|
||||
if (this.useVirtualList && this.usePageScroll){
|
||||
u.consoleErr('使用页面滚动时,开启虚拟列表无效!');
|
||||
}
|
||||
return this.useVirtualList && !this.usePageScroll;
|
||||
},
|
||||
finalUseInnerList() {
|
||||
return this.useInnerList || (this.finalUseVirtualList && !this.forceCloseInnerList)
|
||||
},
|
||||
finalCellKeyName() {
|
||||
// #ifdef APP-NVUE
|
||||
if (this.finalUseVirtualList){
|
||||
if (!this.cellKeyName.length){
|
||||
u.consoleErr('在nvue中开启use-virtual-list必须设置cell-key-name,否则将可能导致列表渲染错误!');
|
||||
}
|
||||
}
|
||||
// #endif
|
||||
return this.cellKeyName;
|
||||
},
|
||||
finalVirtualPageHeight(){
|
||||
return this.virtualPageHeight > 0 ? this.virtualPageHeight : this.windowHeight;
|
||||
return virtualPageHeight * this.preloadPage;
|
||||
},
|
||||
virtualRangePageHeight(){
|
||||
return this.finalVirtualPageHeight * this.preloadPage;
|
||||
},
|
||||
virtualScrollDisTimeStamp() {
|
||||
return 1000 / this.virtualScrollFps;
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
//初始化虚拟列表
|
||||
_virtualListInit() {
|
||||
this.$nextTick(() => {
|
||||
setTimeout(() => {
|
||||
this._getNodeClientRect('.zp-scroll-view').then(node => {
|
||||
if (node && node.length) {
|
||||
this.pagingOrgTop = node[0].top;
|
||||
this.virtualPageHeight = node[0].height;
|
||||
}
|
||||
});
|
||||
}, 100);
|
||||
})
|
||||
},
|
||||
//cellHeightMode为fixed时获取第一个cell高度
|
||||
_updateFixedCellHeight() {
|
||||
this.$nextTick(() => {
|
||||
const updateFixedCellHeightTimeout = setTimeout(() => {
|
||||
this._getNodeClientRect(`#zp-${0}`,this.finalUseInnerList).then(cellNode => {
|
||||
const hasCellNode = cellNode && cellNode.length;
|
||||
if (!hasCellNode) {
|
||||
clearTimeout(updateFixedCellHeightTimeout);
|
||||
if (this.getCellHeightRetryCount.fixed > 10) {
|
||||
u.consoleErr('获取虚拟列表cell高度失败,可能是for循环cell处没有写:id="`zp-${item.zp_index}`",请检查您的代码!')
|
||||
return;
|
||||
}
|
||||
this.getCellHeightRetryCount.fixed++;
|
||||
this._updateFixedCellHeight();
|
||||
} else {
|
||||
this.virtualCellHeight = cellNode[0].height;
|
||||
this._updateVirtualScroll(this.oldScrollTop);
|
||||
}
|
||||
});
|
||||
}, 100);
|
||||
})
|
||||
},
|
||||
//cellHeightMode为dynamic时获取每个cell高度
|
||||
_updateDynamicCellHeight(list) {
|
||||
this.$nextTick(() => {
|
||||
const updateDynamicCellHeightTimeout = setTimeout(async () => {
|
||||
for (let i = 0; i < list.length; i++) {
|
||||
let item = list[i];
|
||||
const cellNode = await this._getNodeClientRect(`#zp-${item[c.listCellIndexKey]}`,this.finalUseInnerList);
|
||||
const hasCellNode = cellNode && cellNode.length;
|
||||
const currentHeight = hasCellNode ? cellNode[0].height : 0;
|
||||
if (!hasCellNode) {
|
||||
clearTimeout(updateDynamicCellHeightTimeout);
|
||||
this.virtualHeightCacheList = this.virtualHeightCacheList.slice(-i);
|
||||
if (this.getCellHeightRetryCount.dynamic > 10) {
|
||||
u.consoleErr('获取虚拟列表cell高度失败,可能是for循环cell处没有写:id="`zp-${item.zp_index}`",请检查您的代码!')
|
||||
return;
|
||||
}
|
||||
this.getCellHeightRetryCount.dynamic++;
|
||||
this._updateDynamicCellHeight(list);
|
||||
break;
|
||||
}
|
||||
let lastHeightCache = null;
|
||||
if (this.virtualHeightCacheList.length) {
|
||||
lastHeightCache = this.virtualHeightCacheList.slice(-1)[0];
|
||||
}
|
||||
const lastHeight = lastHeightCache ? lastHeightCache.totalHeight : 0;
|
||||
this.virtualHeightCacheList.push({
|
||||
height: currentHeight,
|
||||
lastHeight: lastHeight,
|
||||
totalHeight: lastHeight + currentHeight
|
||||
});
|
||||
}
|
||||
this._updateVirtualScroll(this.oldScrollTop);
|
||||
}, 100)
|
||||
})
|
||||
},
|
||||
//设置cellItem的index
|
||||
_setCellIndex(list, isFirstPage) {
|
||||
let lastItem = null;
|
||||
let lastItemIndex = 0;
|
||||
if (!isFirstPage) {
|
||||
lastItemIndex = this.realTotalData.length;
|
||||
if (this.realTotalData.length) {
|
||||
lastItem = this.realTotalData.slice(-1)[0];
|
||||
}
|
||||
if (lastItem && lastItem[c.listCellIndexKey] !== undefined) {
|
||||
lastItemIndex = lastItem[c.listCellIndexKey] + 1;
|
||||
}
|
||||
} else {
|
||||
this._resetDynamicListState();
|
||||
}
|
||||
for (let i = 0; i < list.length; i++) {
|
||||
let item = list[i];
|
||||
if (!item || Object.prototype.toString.call(item) !== '[object Object]') {
|
||||
item = {item};
|
||||
}
|
||||
item[c.listCellIndexKey] = lastItemIndex + i;
|
||||
item[c.listCellIndexUniqueKey] = `${this.virtualListKey}-${item[c.listCellIndexKey]}`;
|
||||
list[i] = item;
|
||||
}
|
||||
this.getCellHeightRetryCount.dynamic = 0;
|
||||
this.cellHeightMode === Enum.CellHeightMode.Dynamic && this._updateDynamicCellHeight(list);
|
||||
},
|
||||
//更新scroll滚动
|
||||
_updateVirtualScroll(scrollTop, scrollDiff = 0) {
|
||||
const currentTimeStamp = u.getTime();
|
||||
if (scrollTop === 0) {
|
||||
this._resetTopRange();
|
||||
}
|
||||
if (scrollTop !== 0 && this.virtualScrollTimeStamp && currentTimeStamp - this.virtualScrollTimeStamp <= this.virtualScrollDisTimeStamp) {
|
||||
return;
|
||||
}
|
||||
this.virtualScrollTimeStamp = Number(currentTimeStamp);
|
||||
|
||||
let scrollIndex = 0;
|
||||
const cellHeightMode = this.cellHeightMode;
|
||||
if (cellHeightMode === Enum.CellHeightMode.Fixed) {
|
||||
scrollIndex = parseInt(scrollTop / this.virtualCellHeight) || 0;
|
||||
this._updateFixedTopRangeIndex(scrollIndex);
|
||||
this._updateFixedBottomRangeIndex(scrollIndex);
|
||||
} else if(cellHeightMode === Enum.CellHeightMode.Dynamic) {
|
||||
const scrollDirection = scrollDiff > 0 ? 'top' : 'bottom';
|
||||
const rangePageHeight = this.virtualRangePageHeight;
|
||||
const topRangePageOffset = scrollTop - rangePageHeight;
|
||||
const bottomRangePageOffset = scrollTop + this.finalVirtualPageHeight + rangePageHeight;
|
||||
|
||||
let virtualBottomRangeIndex = 0;
|
||||
let virtualPlaceholderBottomHeight = 0;
|
||||
let reachedLimitBottom = false;
|
||||
let lastHeightCache = null;
|
||||
const heightCacheList = this.virtualHeightCacheList;
|
||||
if (heightCacheList.length) {
|
||||
lastHeightCache = heightCacheList.slice(-1)[0];
|
||||
}
|
||||
let startTopRangeIndex = this.virtualTopRangeIndex;
|
||||
if (scrollDirection === 'bottom') {
|
||||
for (let i = startTopRangeIndex; i < heightCacheList.length;i++){
|
||||
const heightCacheItem = heightCacheList[i];
|
||||
if (heightCacheItem && heightCacheItem.totalHeight > topRangePageOffset) {
|
||||
this.virtualTopRangeIndex = i;
|
||||
this.virtualPlaceholderTopHeight = heightCacheItem.lastHeight;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
let topRangeMatched = false;
|
||||
for (let i = startTopRangeIndex; i >= 0;i--){
|
||||
const heightCacheItem = heightCacheList[i];
|
||||
if (heightCacheItem && heightCacheItem.totalHeight < topRangePageOffset) {
|
||||
this.virtualTopRangeIndex = i;
|
||||
this.virtualPlaceholderTopHeight = heightCacheItem.lastHeight;
|
||||
topRangeMatched = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
!topRangeMatched && this._resetTopRange();
|
||||
}
|
||||
for (let i = this.virtualTopRangeIndex; i < heightCacheList.length;i++){
|
||||
const heightCacheItem = heightCacheList[i];
|
||||
if (heightCacheItem && heightCacheItem.totalHeight > bottomRangePageOffset) {
|
||||
virtualBottomRangeIndex = i;
|
||||
virtualPlaceholderBottomHeight = lastHeightCache.totalHeight - heightCacheItem.totalHeight;
|
||||
reachedLimitBottom = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!reachedLimitBottom || this.virtualBottomRangeIndex === 0) {
|
||||
this.virtualBottomRangeIndex = this.realTotalData.length ? this.realTotalData.length - 1 : this.pageSize;
|
||||
this.virtualPlaceholderBottomHeight = 0;
|
||||
} else {
|
||||
this.virtualBottomRangeIndex = virtualBottomRangeIndex;
|
||||
this.virtualPlaceholderBottomHeight = virtualPlaceholderBottomHeight;
|
||||
}
|
||||
this._updateVirtualList();
|
||||
}
|
||||
},
|
||||
//更新fixedCell模式下topRangeIndex&placeholderTopHeight
|
||||
_updateFixedTopRangeIndex(scrollIndex) {
|
||||
let virtualTopRangeIndex = this.virtualCellHeight === 0 ? 0 : scrollIndex - parseInt(this.finalVirtualPageHeight / this.virtualCellHeight) * this.preloadPage;
|
||||
virtualTopRangeIndex *= this.virtualListCol;
|
||||
virtualTopRangeIndex = Math.max(0, virtualTopRangeIndex);
|
||||
this.virtualTopRangeIndex = virtualTopRangeIndex;
|
||||
this.virtualPlaceholderTopHeight = (virtualTopRangeIndex / this.virtualListCol) * this.virtualCellHeight;
|
||||
},
|
||||
//更新fixedCell模式下bottomRangeIndex&placeholderBottomHeight
|
||||
_updateFixedBottomRangeIndex(scrollIndex) {
|
||||
let virtualBottomRangeIndex = this.virtualCellHeight === 0 ? this.pageSize : scrollIndex + parseInt(this.finalVirtualPageHeight / this.virtualCellHeight) * (this.preloadPage + 1);
|
||||
virtualBottomRangeIndex *= this.virtualListCol;
|
||||
virtualBottomRangeIndex = Math.min(this.realTotalData.length, virtualBottomRangeIndex);
|
||||
this.virtualBottomRangeIndex = virtualBottomRangeIndex;
|
||||
this.virtualPlaceholderBottomHeight = (this.realTotalData.length - virtualBottomRangeIndex) * this.virtualCellHeight / this.virtualListCol;
|
||||
this._updateVirtualList();
|
||||
},
|
||||
//更新virtualList
|
||||
_updateVirtualList() {
|
||||
const shouldUpdateList = this.updateVirtualListFromDataChange || (this.lastVirtualTopRangeIndex !== this.virtualTopRangeIndex || this.lastVirtualBottomRangeIndex !== this.virtualBottomRangeIndex);
|
||||
if (shouldUpdateList) {
|
||||
this.updateVirtualListFromDataChange = false;
|
||||
this.lastVirtualTopRangeIndex = this.virtualTopRangeIndex;
|
||||
this.lastVirtualBottomRangeIndex = this.virtualBottomRangeIndex;
|
||||
this.virtualList = this.realTotalData.slice(this.virtualTopRangeIndex, this.virtualBottomRangeIndex + 1);
|
||||
}
|
||||
},
|
||||
//重置动态cell模式下的高度缓存数据、虚拟列表和滚动状态
|
||||
_resetDynamicListState(resetVirtualList = false) {
|
||||
this.virtualHeightCacheList = [];
|
||||
if (resetVirtualList) {
|
||||
this.virtualList = [];
|
||||
}
|
||||
this.virtualTopRangeIndex = 0;
|
||||
this.virtualPlaceholderTopHeight = 0;
|
||||
},
|
||||
//重置topRangeIndex和placeholderTopHeight
|
||||
_resetTopRange() {
|
||||
this.virtualTopRangeIndex = 0;
|
||||
this.virtualPlaceholderTopHeight = 0;
|
||||
this._updateVirtualList();
|
||||
},
|
||||
//检测虚拟列表当前滚动位置,如发现滚动位置不正确则重新计算虚拟列表相关参数(为解决在App中可能出现的长时间进入后台后打开App白屏的问题)
|
||||
_checkVirtualListScroll() {
|
||||
if (this.finalUseVirtualList) {
|
||||
this.$nextTick(() => {
|
||||
this._getNodeClientRect('.zp-paging-touch-view').then(node => {
|
||||
const hasNode = node && node.length;
|
||||
const currentTop = hasNode ? node[0].top : 0;
|
||||
if (!hasNode || (currentTop === this.pagingOrgTop && this.virtualPlaceholderTopHeight !== 0)){
|
||||
this._updateVirtualScroll(0);
|
||||
}
|
||||
});
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default ZPVirtualList;
|
||||
26
components/z-paging/js/z-paging-config.js
Normal file
26
components/z-paging/js/z-paging-config.js
Normal file
@@ -0,0 +1,26 @@
|
||||
// [z-paging]处理main.js中的配置信息工具
|
||||
|
||||
let config = null;
|
||||
let getedStorage = false;
|
||||
const storageKey = 'Z-PAGING-CONFIG-STORAGE-KEY'
|
||||
|
||||
function setConfig(value) {
|
||||
try {
|
||||
uni.setStorageSync(storageKey, value);
|
||||
} catch (e) {}
|
||||
}
|
||||
|
||||
function getConfig() {
|
||||
try {
|
||||
if (getedStorage) return config;
|
||||
config = uni.getStorageSync(storageKey);
|
||||
getedStorage = true;
|
||||
} catch (e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
export default {
|
||||
setConfig,
|
||||
getConfig
|
||||
};
|
||||
21
components/z-paging/js/z-paging-constant.js
Normal file
21
components/z-paging/js/z-paging-constant.js
Normal file
@@ -0,0 +1,21 @@
|
||||
// [z-paging]常量
|
||||
|
||||
const version = '2.3.1';
|
||||
const delayTime = 100;
|
||||
const i18nUpdateKey = 'z-paging-i18n-update';
|
||||
|
||||
const errorUpdateKey = 'z-paging-error-emit';
|
||||
const completeUpdateKey = 'z-paging-complete-emit';
|
||||
|
||||
const listCellIndexKey = 'zp_index';
|
||||
const listCellIndexUniqueKey = 'zp_unique_index';
|
||||
|
||||
export default {
|
||||
version,
|
||||
delayTime,
|
||||
i18nUpdateKey,
|
||||
errorUpdateKey,
|
||||
completeUpdateKey,
|
||||
listCellIndexKey,
|
||||
listCellIndexUniqueKey
|
||||
}
|
||||
37
components/z-paging/js/z-paging-enum.js
Normal file
37
components/z-paging/js/z-paging-enum.js
Normal file
@@ -0,0 +1,37 @@
|
||||
// [z-paging]枚举
|
||||
|
||||
const Enum = {
|
||||
//当前加载类型 0.下拉刷新 1.上拉加载更多
|
||||
LoadingType: {
|
||||
Refresher: 0,
|
||||
LoadingMore: 1
|
||||
},
|
||||
//下拉刷新状态 0.默认状态 1.松手立即刷新 2.刷新中 3.刷新结束
|
||||
Refresher: {
|
||||
Default: 0,
|
||||
ReleaseToRefresh: 1,
|
||||
Loading: 2,
|
||||
Complete: 3
|
||||
},
|
||||
//底部加载更多状态 0.默认状态 1.加载中 2.没有更多数据 3.加载失败
|
||||
More: {
|
||||
Default: 0,
|
||||
Loading: 1,
|
||||
NoMore: 2,
|
||||
Fail: 3
|
||||
},
|
||||
//@query触发来源 0.用户主动下拉刷新 1.通过reload触发 2.通过refresh触发 3.通过滚动到底部加载更多或点击底部加载更多触发
|
||||
QueryFrom: {
|
||||
UserPullDown: 0,
|
||||
Reload: 1,
|
||||
Refresh: 2,
|
||||
LoadingMore: 3
|
||||
},
|
||||
//虚拟列表cell高度模式
|
||||
CellHeightMode: {
|
||||
Fixed: 'fixed',
|
||||
Dynamic: 'dynamic'
|
||||
}
|
||||
}
|
||||
|
||||
export default Enum;
|
||||
133
components/z-paging/js/z-paging-i18n.js
Normal file
133
components/z-paging/js/z-paging-i18n.js
Normal file
@@ -0,0 +1,133 @@
|
||||
// z-paging国际化(支持中文、中文繁体和英文)
|
||||
const i18nUpdateKey = 'z-paging-i18n-update';
|
||||
|
||||
const t = {
|
||||
refresherDefaultText: {
|
||||
'en': 'Pull down to refresh',
|
||||
'zh-cn': '继续下拉刷新',
|
||||
'zh-hant-cn': '繼續下拉重繪',
|
||||
},
|
||||
refresherPullingText: {
|
||||
'en': 'Release to refresh',
|
||||
'zh-cn': '松开立即刷新',
|
||||
'zh-hant-cn': '鬆開立即重繪',
|
||||
},
|
||||
refresherRefreshingText: {
|
||||
'en': 'Refreshing...',
|
||||
'zh-cn': '正在刷新...',
|
||||
'zh-hant-cn': '正在重繪...',
|
||||
},
|
||||
refresherCompleteText: {
|
||||
'en': 'Refresh succeeded',
|
||||
'zh-cn': '刷新成功',
|
||||
'zh-hant-cn': '重繪成功',
|
||||
},
|
||||
loadingMoreDefaultText: {
|
||||
'en': 'Click to load more',
|
||||
'zh-cn': '点击加载更多',
|
||||
'zh-hant-cn': '點擊加載更多',
|
||||
},
|
||||
loadingMoreLoadingText: {
|
||||
'en': 'Loading...',
|
||||
'zh-cn': '正在加载...',
|
||||
'zh-hant-cn': '正在加載...',
|
||||
},
|
||||
loadingMoreNoMoreText: {
|
||||
'en': 'No more data',
|
||||
'zh-cn': '没有更多了',
|
||||
'zh-hant-cn': '沒有更多了',
|
||||
},
|
||||
loadingMoreFailText: {
|
||||
'en': 'Load failed,click to reload',
|
||||
'zh-cn': '加载失败,点击重新加载',
|
||||
'zh-hant-cn': '加載失敗,點擊重新加載',
|
||||
},
|
||||
emptyViewText: {
|
||||
'en': 'No data',
|
||||
'zh-cn': '没有数据哦~',
|
||||
'zh-hant-cn': '沒有數據哦~',
|
||||
},
|
||||
emptyViewReloadText: {
|
||||
'en': 'Reload',
|
||||
'zh-cn': '重新加载',
|
||||
'zh-hant-cn': '重新加載',
|
||||
},
|
||||
emptyViewErrorText: {
|
||||
'en': 'Sorry,load failed',
|
||||
'zh-cn': '很抱歉,加载失败',
|
||||
'zh-hant-cn': '很抱歉,加載失敗',
|
||||
},
|
||||
refresherUpdateTimeText: {
|
||||
'en': 'Last update: ',
|
||||
'zh-cn': '最后更新:',
|
||||
'zh-hant-cn': '最後更新:',
|
||||
},
|
||||
refresherUpdateTimeNoneText: {
|
||||
'en': 'None',
|
||||
'zh-cn': '无',
|
||||
'zh-hant-cn': '無',
|
||||
},
|
||||
refresherUpdateTimeTodayText: {
|
||||
'en': 'Today',
|
||||
'zh-cn': '今天',
|
||||
'zh-hant-cn': '今天',
|
||||
},
|
||||
refresherUpdateTimeYesterdayText: {
|
||||
'en': 'Yesterday',
|
||||
'zh-cn': '昨天',
|
||||
'zh-hant-cn': '昨天',
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 获取当前语言,格式为:zh-cn、zh-hant-cn、en。followSystemLanguage:获取的结果是否是在不跟随系统语言下获取到的
|
||||
function getLanguage(followSystemLanguage = true) {
|
||||
return _getPrivateLanguage(false, followSystemLanguage);
|
||||
}
|
||||
|
||||
// 获取当前语言,格式为:简体中文、繁體中文、English。followSystemLanguage:获取的结果是否是在不跟随系统语言下获取到的
|
||||
function getLanguageName(followSystemLanguage = true) {
|
||||
const language = getLanguage(followSystemLanguage);
|
||||
const languageNameMap = {
|
||||
'zh-cn': '简体中文',
|
||||
'zh-hant-cn': '繁體中文',
|
||||
'en': 'English'
|
||||
};
|
||||
return languageNameMap[language];
|
||||
}
|
||||
|
||||
//设置当前语言,格式为:zh-cn、zh-hant-cn、en
|
||||
function setLanguage(myLanguage) {
|
||||
uni.setStorageSync(i18nUpdateKey, myLanguage);
|
||||
uni.$emit(i18nUpdateKey, myLanguage);
|
||||
}
|
||||
|
||||
// 插件内部使用,请勿直接调用
|
||||
function _getPrivateLanguage(myLanguage, followSystemLanguage = true) {
|
||||
let systemLanguage = '';
|
||||
if (followSystemLanguage) {
|
||||
systemLanguage = uni.getSystemInfoSync().language;
|
||||
}
|
||||
let language = myLanguage || uni.getStorageSync(i18nUpdateKey) || systemLanguage;
|
||||
language = language.toLowerCase();
|
||||
const reg = new RegExp('_', '');
|
||||
language = language.replace(reg, '-');
|
||||
if (language.indexOf('zh') !== -1) {
|
||||
if (language === 'zh' || language === 'zh-cn' || language.indexOf('zh-hans') !== -1) {
|
||||
return 'zh-cn';
|
||||
}
|
||||
return 'zh-hant-cn';
|
||||
}
|
||||
if (language.indexOf('en') !== -1) {
|
||||
return 'en';
|
||||
}
|
||||
return 'zh-cn';
|
||||
}
|
||||
|
||||
export default {
|
||||
t,
|
||||
getLanguage,
|
||||
getLanguageName,
|
||||
setLanguage,
|
||||
_getPrivateLanguage,
|
||||
}
|
||||
34
components/z-paging/js/z-paging-interceptor.js
Normal file
34
components/z-paging/js/z-paging-interceptor.js
Normal file
@@ -0,0 +1,34 @@
|
||||
// [z-paging]拦截器
|
||||
|
||||
//拦截&处理@query事件
|
||||
function handleQuery(callback) {
|
||||
try {
|
||||
setTimeout(function() {
|
||||
_getApp().globalData.zp_handleQueryCallback = callback;
|
||||
}, 1);
|
||||
} catch (e) {}
|
||||
}
|
||||
|
||||
//拦截&处理@query事件(私有,请勿调用)
|
||||
function _handleQuery(pageNo, pageSize, from){
|
||||
const handleQueryCallback = _getApp().globalData.zp_handleQueryCallback;
|
||||
if (handleQueryCallback) {
|
||||
return handleQueryCallback(pageNo, pageSize, from);
|
||||
}
|
||||
return [pageNo, pageSize, from];
|
||||
}
|
||||
|
||||
//获取当前app对象
|
||||
function _getApp(){
|
||||
// #ifndef APP-NVUE
|
||||
return getApp();
|
||||
// #endif
|
||||
// #ifdef APP-NVUE
|
||||
return getApp({allowDefault: true});
|
||||
// #endif
|
||||
}
|
||||
|
||||
export default {
|
||||
handleQuery,
|
||||
_handleQuery
|
||||
};
|
||||
604
components/z-paging/js/z-paging-main.js
Normal file
604
components/z-paging/js/z-paging-main.js
Normal file
@@ -0,0 +1,604 @@
|
||||
// [z-paging]核心js
|
||||
|
||||
import zStatic from './z-paging-static'
|
||||
import c from './z-paging-constant'
|
||||
import u from './z-paging-utils'
|
||||
|
||||
import zPagingRefresh from '../components/z-paging-refresh'
|
||||
import zPagingLoadMore from '../components/z-paging-load-more'
|
||||
import zPagingEmptyView from '../../z-paging-empty-view/z-paging-empty-view'
|
||||
|
||||
// modules
|
||||
import dataHandleModule from './modules/data-handle'
|
||||
import i18nModule from './modules/i18n'
|
||||
import nvueModule from './modules/nvue'
|
||||
import emptyModule from './modules/empty'
|
||||
import refresherModule from './modules/refresher'
|
||||
import loadMoreModule from './modules/load-more'
|
||||
import scrollerModule from './modules/scroller'
|
||||
import backToTopModule from './modules/back-to-top'
|
||||
import virtualListModule from './modules/virtual-list'
|
||||
|
||||
import Enum from './z-paging-enum'
|
||||
|
||||
const systemInfo = uni.getSystemInfoSync();
|
||||
|
||||
// #ifdef APP-NVUE
|
||||
const weexDom = weex.requireModule('dom');
|
||||
// #endif
|
||||
|
||||
export default {
|
||||
name: "z-paging",
|
||||
components: {
|
||||
zPagingRefresh,
|
||||
zPagingLoadMore,
|
||||
zPagingEmptyView
|
||||
},
|
||||
mixins: [
|
||||
dataHandleModule,
|
||||
i18nModule,
|
||||
nvueModule,
|
||||
emptyModule,
|
||||
refresherModule,
|
||||
loadMoreModule,
|
||||
scrollerModule,
|
||||
backToTopModule,
|
||||
virtualListModule
|
||||
],
|
||||
data() {
|
||||
return {
|
||||
//--------------静态资源---------------
|
||||
base64Arrow: zStatic.base64Arrow,
|
||||
base64Flower: zStatic.base64Flower,
|
||||
base64BackToTop: zStatic.base64BackToTop,
|
||||
|
||||
//-------------全局数据相关--------------
|
||||
//当前加载类型
|
||||
loadingType: Enum.LoadingType.Refresher,
|
||||
requestTimeStamp: 0,
|
||||
chatRecordLoadingMoreText: '',
|
||||
wxsPropType: '',
|
||||
renderPropScrollTop: -1,
|
||||
renderPropUsePageScroll: -1,
|
||||
checkScrolledToBottomTimeOut: null,
|
||||
systemInfo: null,
|
||||
cssSafeAreaInsetBottom: -1,
|
||||
cacheTopHeight: 0,
|
||||
|
||||
//--------------状态&判断---------------
|
||||
insideOfPaging: -1,
|
||||
loading: false,
|
||||
loadingForNow: false,
|
||||
isLoadFailed: false,
|
||||
isIos: systemInfo.platform === 'ios',
|
||||
disabledBounce: false,
|
||||
fromCompleteEmit: false,
|
||||
disabledCompleteEmit: false,
|
||||
|
||||
//---------------wxs相关---------------
|
||||
wxsIsScrollTopInTopRange: true,
|
||||
wxsScrollTop: 0,
|
||||
wxsPageScrollTop: 0,
|
||||
wxsOnPullingDown: false,
|
||||
};
|
||||
},
|
||||
props: {
|
||||
//调用complete后延迟处理的时间,单位为毫秒,默认0毫秒,优先级高于minDelay
|
||||
delay: {
|
||||
type: [Number, String],
|
||||
default: u.gc('delay', 0),
|
||||
},
|
||||
//触发@query后最小延迟处理的时间,单位为毫秒,默认0毫秒,优先级低于delay(假设设置为300毫秒,若分页请求时间小于300毫秒,则在调用complete后延迟[300毫秒-请求时长];若请求时长大于300毫秒,则不延迟),当show-refresher-when-reload为true或reload(true)时,其最小值为400
|
||||
minDelay: {
|
||||
type: [Number, String],
|
||||
default: u.gc('minDelay', 0),
|
||||
},
|
||||
//设置z-paging的style,部分平台(如微信小程序)无法直接修改组件的style,可使用此属性代替
|
||||
pagingStyle: {
|
||||
type: Object,
|
||||
default: function() {
|
||||
return u.gc('pagingStyle', {});
|
||||
},
|
||||
},
|
||||
//z-paging的高度,优先级低于pagingStyle中设置的height;传字符串,如100px、100rpx、100%
|
||||
height: {
|
||||
type: String,
|
||||
default: u.gc('height', '')
|
||||
},
|
||||
//z-paging的宽度,优先级低于pagingStyle中设置的width;传字符串,如100px、100rpx、100%
|
||||
width: {
|
||||
type: String,
|
||||
default: u.gc('width', '')
|
||||
},
|
||||
//z-paging的背景色,优先级低于pagingStyle中设置的background。传字符串,如"#ffffff"
|
||||
bgColor: {
|
||||
type: String,
|
||||
default: u.gc('bgColor', '')
|
||||
},
|
||||
//设置z-paging的容器(插槽的父view)的style
|
||||
pagingContentStyle: {
|
||||
type: Object,
|
||||
default: function() {
|
||||
return u.gc('pagingContentStyle', {});
|
||||
},
|
||||
},
|
||||
//z-paging是否自动高度,若自动高度则会自动铺满屏幕
|
||||
autoHeight: {
|
||||
type: Boolean,
|
||||
default: u.gc('autoHeight', false)
|
||||
},
|
||||
//z-paging是否自动高度时,附加的高度,注意添加单位px或rpx,若需要减少高度,则传负数
|
||||
autoHeightAddition: {
|
||||
type: [Number, String],
|
||||
default: u.gc('autoHeightAddition', '0px')
|
||||
},
|
||||
//loading(下拉刷新、上拉加载更多)的主题样式,支持black,white,默认black
|
||||
defaultThemeStyle: {
|
||||
type: String,
|
||||
default: function() {
|
||||
return u.gc('defaultThemeStyle', 'black');
|
||||
}
|
||||
},
|
||||
//z-paging是否使用fixed布局,若使用fixed布局,则z-paging的父view无需固定高度,z-paging高度默认为100%,默认为是(当使用内置scroll-view滚动时有效)
|
||||
fixed: {
|
||||
type: Boolean,
|
||||
default: u.gc('fixed', true)
|
||||
},
|
||||
//是否开启底部安全区域适配
|
||||
safeAreaInsetBottom: {
|
||||
type: Boolean,
|
||||
default: u.gc('safeAreaInsetBottom', false)
|
||||
},
|
||||
//开启底部安全区域适配后,是否使用placeholder形式实现,默认为否。为否时滚动区域会自动避开底部安全区域,也就是所有滚动内容都不会挡住底部安全区域,若设置为是,则滚动时滚动内容会挡住底部安全区域,但是当滚动到底部时才会避开底部安全区域
|
||||
useSafeAreaPlaceholder: {
|
||||
type: Boolean,
|
||||
default: u.gc('useSafeAreaPlaceholder', false)
|
||||
},
|
||||
//第一次加载后自动隐藏loading slot,默认为是
|
||||
autoHideLoadingAfterFirstLoaded: {
|
||||
type: Boolean,
|
||||
default: u.gc('autoHideLoadingAfterFirstLoaded', true)
|
||||
},
|
||||
//loading slot是否铺满屏幕并固定,默认为否
|
||||
loadingFullFixed: {
|
||||
type: Boolean,
|
||||
default: u.gc('loadingFullFixed', false)
|
||||
},
|
||||
//slot="top"的view的z-index,默认为99,仅使用页面滚动时有效
|
||||
topZIndex: {
|
||||
type: Number,
|
||||
default: u.gc('topZIndex', 99)
|
||||
},
|
||||
//z-paging内容容器父view的z-index,默认为1
|
||||
superContentZIndex: {
|
||||
type: Number,
|
||||
default: u.gc('superContentZIndex', 1)
|
||||
},
|
||||
//z-paging内容容器部分的z-index,默认为10
|
||||
contentZIndex: {
|
||||
type: Number,
|
||||
default: u.gc('contentZIndex', 10)
|
||||
},
|
||||
//使用页面滚动时,是否在不满屏时自动填充满屏幕,默认为是
|
||||
autoFullHeight: {
|
||||
type: Boolean,
|
||||
default: u.gc('autoFullHeight', true)
|
||||
},
|
||||
//是否监听列表触摸方向改变,默认为否
|
||||
watchTouchDirectionChange: {
|
||||
type: Boolean,
|
||||
default: u.gc('watchTouchDirectionChange', false)
|
||||
},
|
||||
//是否将错误信息打印至控制台,默认为是
|
||||
showConsoleError: {
|
||||
type: Boolean,
|
||||
default: u.gc('showConsoleError', true)
|
||||
},
|
||||
},
|
||||
created(){
|
||||
if (this.createdReload && !this.refresherOnly && (this.mountedAutoCallReload && this.auto)) {
|
||||
this._startLoading();
|
||||
this._preReload();
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.wxsPropType = u.getTime().toString();
|
||||
this.renderJsIgnore;
|
||||
if (!this.createdReload && !this.refresherOnly && (this.mountedAutoCallReload && this.auto)) {
|
||||
this.$nextTick(() => {
|
||||
this._preReload();
|
||||
})
|
||||
}
|
||||
let delay = 0;
|
||||
// #ifdef H5 || MP
|
||||
delay = 100;
|
||||
// #endif
|
||||
this.$nextTick(() => {
|
||||
this.systemInfo = uni.getSystemInfoSync();
|
||||
if (!this.usePageScroll && this.autoHeight) {
|
||||
this._setAutoHeight();
|
||||
}
|
||||
this.loaded = true;
|
||||
})
|
||||
this.updatePageScrollTopHeight();
|
||||
this.updatePageScrollBottomHeight();
|
||||
this._updateLeftAndRightWidth();
|
||||
if (this.finalRefresherEnabled && this.useCustomRefresher) {
|
||||
this.$nextTick(() => {
|
||||
this.isTouchmoving = true;
|
||||
})
|
||||
}
|
||||
this._onEmit();
|
||||
// #ifdef APP-NVUE
|
||||
if (!this.isIos && !this.useChatRecordMode) {
|
||||
this.nLoadingMoreFixedHeight = true;
|
||||
}
|
||||
this._nUpdateRefresherWidth();
|
||||
// #endif
|
||||
// #ifndef APP-NVUE
|
||||
this.finalUseVirtualList && this._virtualListInit();
|
||||
// #endif
|
||||
// #ifndef APP-PLUS
|
||||
this.$nextTick(() => {
|
||||
setTimeout(() => {
|
||||
this._getCssSafeAreaInsetBottom();
|
||||
},delay)
|
||||
})
|
||||
// #endif
|
||||
},
|
||||
destroyed() {
|
||||
this._offEmit();
|
||||
},
|
||||
// #ifdef VUE3
|
||||
unmounted() {
|
||||
this._offEmit();
|
||||
},
|
||||
// #endif
|
||||
watch: {
|
||||
loadingStatus(newVal, oldVal) {
|
||||
this.$emit('loadingStatusChange', newVal);
|
||||
this.$nextTick(()=>{
|
||||
this.loadingStatusAfterRender = newVal;
|
||||
})
|
||||
// #ifdef APP-NVUE
|
||||
if (this.useChatRecordMode) {
|
||||
if (this.pageNo === this.defaultPageNo && newVal === Enum.More.NoMore) {
|
||||
this.nIsFirstPageAndNoMore = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
this.nIsFirstPageAndNoMore = false;
|
||||
// #endif
|
||||
},
|
||||
loading(newVal){
|
||||
if(newVal){
|
||||
this.loadingForNow = newVal;
|
||||
}
|
||||
},
|
||||
defaultThemeStyle: {
|
||||
handler(newVal) {
|
||||
if (newVal.length) {
|
||||
this.finalRefresherDefaultStyle = newVal;
|
||||
}
|
||||
},
|
||||
immediate: true
|
||||
},
|
||||
autoHeight(newVal, oldVal) {
|
||||
if (this.loaded && !this.usePageScroll) {
|
||||
this._setAutoHeight(newVal);
|
||||
}
|
||||
},
|
||||
autoHeightAddition(newVal, oldVal) {
|
||||
if (this.loaded && !this.usePageScroll && this.autoHeight) {
|
||||
this._setAutoHeight(newVal);
|
||||
}
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
zScopedSlots() {
|
||||
return this.$scopedSlots;
|
||||
},
|
||||
finalPagingStyle() {
|
||||
let pagingStyle = this.pagingStyle;
|
||||
if (!this.systemInfo) return pagingStyle;
|
||||
let windowTop = this.systemInfo.windowTop;
|
||||
//暂时修复vue3中隐藏系统导航栏后windowTop获取不正确的问题,具体bug详见https://ask.dcloud.net.cn/question/141634
|
||||
//感谢litangyu!!https://github.com/SmileZXLee/uni-z-paging/issues/25
|
||||
// #ifdef VUE3 && H5
|
||||
const pageHeadNode = document.getElementsByTagName("uni-page-head");
|
||||
if (!pageHeadNode.length) windowTop = 0;
|
||||
// #endif
|
||||
const windowBottom = this.systemInfo.windowBottom;
|
||||
if (!this.usePageScroll && this.fixed) {
|
||||
if (windowTop && !pagingStyle.top) {
|
||||
pagingStyle.top = windowTop + 'px';
|
||||
}
|
||||
if (!pagingStyle.bottom) {
|
||||
let bottom = windowBottom || 0;
|
||||
if (this.safeAreaInsetBottom && !this.useSafeAreaPlaceholder) {
|
||||
bottom += this.safeAreaBottom;
|
||||
}
|
||||
if(bottom > 0){
|
||||
pagingStyle.bottom = bottom + 'px';
|
||||
}
|
||||
}
|
||||
}
|
||||
if (this.bgColor.length && !pagingStyle['background']) {
|
||||
pagingStyle['background'] = this.bgColor;
|
||||
}
|
||||
if (this.height.length && !pagingStyle['height']) {
|
||||
pagingStyle['height'] = this.height;
|
||||
}
|
||||
if (this.width.length && !pagingStyle['width']) {
|
||||
pagingStyle['width'] = this.width;
|
||||
}
|
||||
return pagingStyle;
|
||||
},
|
||||
finalLowerThreshold() {
|
||||
return u.convertTextToPx(this.lowerThreshold);
|
||||
},
|
||||
finalPagingContentStyle() {
|
||||
if (this.contentZIndex != 1) {
|
||||
this.pagingContentStyle['z-index'] = this.contentZIndex;
|
||||
this.pagingContentStyle['position'] = 'relative';
|
||||
}
|
||||
return this.pagingContentStyle;
|
||||
},
|
||||
showLoading() {
|
||||
if (this.firstPageLoaded || !this.loading || !this.loadingForNow) return false;
|
||||
if (this.autoHideLoadingAfterFirstLoaded) {
|
||||
return this.fromEmptyViewReload ? true : !this.pagingLoaded;
|
||||
} else{
|
||||
return this.loadingType === Enum.LoadingType.Refresher;
|
||||
}
|
||||
},
|
||||
safeAreaBottom() {
|
||||
if (!this.systemInfo) return 0;
|
||||
let safeAreaBottom = 0;
|
||||
// #ifdef APP-PLUS
|
||||
safeAreaBottom = this.systemInfo.safeAreaInsets.bottom || 0;
|
||||
// #endif
|
||||
// #ifndef APP-PLUS
|
||||
safeAreaBottom = this.cssSafeAreaInsetBottom === -1 ? 0 : this.cssSafeAreaInsetBottom;
|
||||
// #endif
|
||||
return safeAreaBottom;
|
||||
},
|
||||
renderJsIgnore() {
|
||||
if ((this.usePageScroll && this.useChatRecordMode) || !this.refresherEnabled || !this.useCustomRefresher) {
|
||||
this.$nextTick(() => {
|
||||
this.renderPropScrollTop = 10;
|
||||
})
|
||||
}
|
||||
return 0;
|
||||
},
|
||||
windowHeight() {
|
||||
return !this.systemInfo ? 0 : this.systemInfo.windowHeight || 0;
|
||||
},
|
||||
windowTop() {
|
||||
return !this.systemInfo ? 0 : this.systemInfo.windowTop || 0;
|
||||
},
|
||||
windowBottom() {
|
||||
if (!this.systemInfo) return 0;
|
||||
let windowBottom = this.systemInfo.windowBottom || 0;
|
||||
if (this.safeAreaInsetBottom && !this.useSafeAreaPlaceholder) {
|
||||
windowBottom += this.safeAreaBottom;
|
||||
}
|
||||
return windowBottom;
|
||||
},
|
||||
isOldWebView() {
|
||||
// #ifndef APP-NVUE
|
||||
try {
|
||||
const systemInfos = systemInfo.system.split(' ');
|
||||
const deviceType = systemInfos[0];
|
||||
const version = parseInt(systemInfos[1].slice(0,1));
|
||||
if ((deviceType === 'iOS' && version <= 10) || (deviceType === 'Android' && version <= 6)) {
|
||||
return true;
|
||||
}
|
||||
} catch(e){
|
||||
return false;
|
||||
}
|
||||
// #endif
|
||||
return false;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
//当前版本号
|
||||
getVersion() {
|
||||
return `z-paging v${zConstant.version}`;
|
||||
},
|
||||
//设置nvue List的specialEffects
|
||||
setSpecialEffects(args) {
|
||||
this.setListSpecialEffects(args);
|
||||
},
|
||||
//与setSpecialEffects等效,兼容旧版本
|
||||
setListSpecialEffects(args) {
|
||||
this.nFixFreezing = args && Object.keys(args).length;
|
||||
if (this.isIos) {
|
||||
this.privateRefresherEnabled = 0;
|
||||
}
|
||||
if (!this.usePageScroll) {
|
||||
this.$refs['zp-n-list'].setSpecialEffects(args);
|
||||
}
|
||||
},
|
||||
//处理开始加载更多状态
|
||||
_startLoading(isReload = false) {
|
||||
if ((this.showLoadingMoreWhenReload && !this.isUserPullDown) || !isReload) {
|
||||
this.loadingStatus = Enum.More.Loading;
|
||||
}
|
||||
this.loading = true;
|
||||
},
|
||||
//检测scrollView是否要铺满屏幕
|
||||
_doCheckScrollViewShouldFullHeight(totalData){
|
||||
if (this.autoFullHeight && this.usePageScroll && this.isTotalChangeFromAddData) {
|
||||
// #ifndef APP-NVUE
|
||||
this.$nextTick(() => {
|
||||
this._checkScrollViewShouldFullHeight((scrollViewNode, pagingContainerNode) => {
|
||||
this._preCheckShowLoadingMoreWhenNoMoreAndInsideOfPaging(totalData, scrollViewNode, pagingContainerNode)
|
||||
});
|
||||
})
|
||||
// #endif
|
||||
// #ifdef APP-NVUE
|
||||
this._preCheckShowLoadingMoreWhenNoMoreAndInsideOfPaging(totalData)
|
||||
// #endif
|
||||
} else {
|
||||
this._preCheckShowLoadingMoreWhenNoMoreAndInsideOfPaging(totalData)
|
||||
}
|
||||
},
|
||||
//检测z-paging是否要全屏覆盖(当使用页面滚动并且不满全屏时,默认z-paging需要铺满全屏,避免数据过少时内部的empty-view无法正确展示)
|
||||
async _checkScrollViewShouldFullHeight(callback) {
|
||||
try {
|
||||
const scrollViewNode = await this._getNodeClientRect('.zp-scroll-view');
|
||||
const pagingContainerNode = await this._getNodeClientRect('.zp-paging-container-content');
|
||||
if (!scrollViewNode || !pagingContainerNode) return;
|
||||
const scrollViewHeight = pagingContainerNode[0].height;
|
||||
const scrollViewTop = scrollViewNode[0].top;
|
||||
if (this.isAddedData && scrollViewHeight + scrollViewTop <= this.windowHeight) {
|
||||
this._setAutoHeight(true, scrollViewNode);
|
||||
callback(scrollViewNode, pagingContainerNode);
|
||||
} else {
|
||||
this._setAutoHeight(false);
|
||||
callback(null, null);
|
||||
}
|
||||
} catch (e) {
|
||||
callback(null, null);
|
||||
}
|
||||
},
|
||||
//设置z-paging高度
|
||||
async _setAutoHeight(shouldFullHeight = true, scrollViewNode = null) {
|
||||
let heightKey = 'height';
|
||||
// #ifndef APP-NVUE
|
||||
if (this.usePageScroll) {
|
||||
heightKey = 'min-height';
|
||||
}
|
||||
// #endif
|
||||
try {
|
||||
if (shouldFullHeight) {
|
||||
let finalScrollViewNode = scrollViewNode ? scrollViewNode : await this._getNodeClientRect('.scroll-view');
|
||||
let finalScrollBottomNode = await this._getNodeClientRect('.zp-page-bottom');
|
||||
if (finalScrollViewNode) {
|
||||
const scrollViewTop = finalScrollViewNode[0].top;
|
||||
let scrollViewHeight = this.windowHeight - scrollViewTop;
|
||||
if(finalScrollBottomNode){
|
||||
scrollViewHeight -= finalScrollBottomNode[0].height;
|
||||
}
|
||||
let additionHeight = u.convertTextToPx(this.autoHeightAddition);
|
||||
this.$set(this.scrollViewStyle, heightKey, scrollViewHeight + additionHeight - (this.insideMore ? 1 : 0) + 'px');
|
||||
this.$set(this.scrollViewInStyle, heightKey, scrollViewHeight + additionHeight - (this.insideMore ? 1 : 0) + 'px');
|
||||
}
|
||||
} else {
|
||||
this.$delete(this.scrollViewStyle, heightKey);
|
||||
this.$delete(this.scrollViewInStyle, heightKey);
|
||||
}
|
||||
} catch (e) {}
|
||||
},
|
||||
//通过获取css设置的底部安全区域占位view高度设置bottom距离
|
||||
_getCssSafeAreaInsetBottom(){
|
||||
this._getNodeClientRect('.zp-safe-area-inset-bottom').then((res) => {
|
||||
if (res) {
|
||||
this.cssSafeAreaInsetBottom = res[0].height;
|
||||
if (this.safeAreaInsetBottom) {
|
||||
this.updatePageScrollBottomHeight();
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
//触发更新是否超出页面状态
|
||||
_updateInsideOfPaging() {
|
||||
if (this.insideMore && this.insideOfPaging === true) {
|
||||
setTimeout(() => {
|
||||
this.doLoadMore();
|
||||
}, 200)
|
||||
}
|
||||
},
|
||||
//获取节点尺寸
|
||||
_getNodeClientRect(select, inThis = true, scrollOffset = false) {
|
||||
// #ifdef APP-NVUE
|
||||
select = select.replace('.', '').replace('#', '');
|
||||
const ref = this.$refs[select];
|
||||
return new Promise((resolve, reject) => {
|
||||
if (ref) {
|
||||
weexDom.getComponentRect(ref, option => {
|
||||
if (option && option.result) {
|
||||
resolve([option.size]);
|
||||
} else {
|
||||
resolve(false);
|
||||
}
|
||||
})
|
||||
} else {
|
||||
resolve(false);
|
||||
}
|
||||
});
|
||||
return;
|
||||
// #endif
|
||||
//#ifdef MP-ALIPAY
|
||||
inThis = false;
|
||||
//#endif
|
||||
let res = inThis ? uni.createSelectorQuery().in(this) : uni.createSelectorQuery();
|
||||
if (scrollOffset) {
|
||||
res.select(select).scrollOffset();
|
||||
} else {
|
||||
res.select(select).boundingClientRect();
|
||||
}
|
||||
return new Promise((resolve, reject) => {
|
||||
res.exec(data => {
|
||||
resolve((data && data != '' && data != undefined && data.length) ? data : false);
|
||||
});
|
||||
});
|
||||
},
|
||||
//清除timeout
|
||||
_cleanTimeout(timeout) {
|
||||
if (timeout) {
|
||||
clearTimeout(timeout);
|
||||
timeout = null;
|
||||
}
|
||||
return timeout;
|
||||
},
|
||||
//添加全局emit监听
|
||||
_onEmit() {
|
||||
uni.$on(c.i18nUpdateKey, () => {
|
||||
this.tempLanguageUpdateKey = u.getTime();
|
||||
})
|
||||
uni.$on(c.errorUpdateKey, () => {
|
||||
if (this.loading) {
|
||||
this.complete(false);
|
||||
}
|
||||
})
|
||||
uni.$on(c.completeUpdateKey, (data) => {
|
||||
setTimeout(() => {
|
||||
if (this.loading) {
|
||||
if (!this.disabledCompleteEmit) {
|
||||
const type = data.type || 'normal';
|
||||
const list = data.list || data;
|
||||
const rule = data.rule;
|
||||
this.fromCompleteEmit = true;
|
||||
switch (type){
|
||||
case 'normal':
|
||||
this.complete(list);
|
||||
break;
|
||||
case 'total':
|
||||
this.completeByTotal(list, rule);
|
||||
break;
|
||||
case 'nomore':
|
||||
this.completeByNoMore(list, rule);
|
||||
break;
|
||||
case 'key':
|
||||
this.completeByKey(list, rule);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
this.disabledCompleteEmit = false;
|
||||
}
|
||||
}
|
||||
}, 1);
|
||||
})
|
||||
},
|
||||
//销毁全局emit和listener监听
|
||||
_offEmit(){
|
||||
uni.$off(c.i18nUpdateKey);
|
||||
uni.$off(c.errorUpdateKey);
|
||||
uni.$off(c.completeUpdateKey);
|
||||
}
|
||||
},
|
||||
};
|
||||
26
components/z-paging/js/z-paging-mixin.js
Normal file
26
components/z-paging/js/z-paging-mixin.js
Normal file
@@ -0,0 +1,26 @@
|
||||
// [z-paging]使用页面滚动时引入此mixin,用于监听和处理onPullDownRefresh等页面生命周期方法
|
||||
|
||||
const ZPagingMixin = {
|
||||
onPullDownRefresh() {
|
||||
if (this.isPagingRefNotFound()) return;
|
||||
this.$refs.paging.reload();
|
||||
},
|
||||
onPageScroll(e) {
|
||||
if (this.isPagingRefNotFound()) return;
|
||||
this.$refs.paging.updatePageScrollTop(e.scrollTop);
|
||||
if (e.scrollTop < 10) {
|
||||
this.$refs.paging.doChatRecordLoadMore();
|
||||
}
|
||||
},
|
||||
onReachBottom() {
|
||||
if (this.isPagingRefNotFound()) return;
|
||||
this.$refs.paging.doLoadMore();
|
||||
},
|
||||
methods: {
|
||||
isPagingRefNotFound() {
|
||||
return !this.$refs.paging || this.$refs.paging === undefined;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default ZPagingMixin;
|
||||
23
components/z-paging/js/z-paging-static.js
Normal file
23
components/z-paging/js/z-paging-static.js
Normal file
@@ -0,0 +1,23 @@
|
||||
// [z-paging]公用的静态图片资源
|
||||
|
||||
const base64Arrow = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGQAAABkBAMAAACCzIhnAAAAD1BMVEVHcExRUVFMTExRUVFRUVE9CdWsAAAABHRSTlMAjjrY9ZnUjwAAAQFJREFUWMPt2MsNgzAMgGEEE1B1gKJmAIRYoCH7z9RCXrabh33iYktcIv35EEg5ZBh07pvxJU6MFSPOSRnjnBUjUsaciRUjMsb4xIoRCWNiYsUInzE5sWKEyxiYWDbyefqHx1zIeiYTk7mQYziTYecxHvEJjwmIT3hMQELCYSISEg4TkZj0mYTEpM8kJCU9JiMp6TEZyUmbAUhO2gxAQNJiIAKSFgMRmNQZhMCkziAEJTUGIyipMRjBSZkhCE7KDEFIUmTeGCHJxWz0zXaE0GTCG8ZFtEaS347r/1fe11YyHYVfubxayfjoHmc0YYwmmmiiiSaaaKLJ7ckyz5ve+dw3Xw2emdwm9xSbAAAAAElFTkSuQmCC';
|
||||
const base64ArrowWhite = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGQAAABkBAMAAACCzIhnAAAAElBMVEVHcEz///////////////////+IGTx/AAAABnRSTlMA/dAkXZOhASU/AAABYElEQVRYw+2YwXLCIBCGsdAHWGbyAKZ4zxi9O017rxLf/1UaWFAgA1m8dcpedNSPf/l/Vh0Ya/Wn6hN0JcGvoCqRM4C8VBFiDwBqqNuJKV0rAnCgy3AUqZE57x0iqTL8Br4U3WBf/YWaIlTKfAcELU/h9w72CSVPa3C3OCDvhpHbRp/s2vq4fHhCeiCl2A3m4Qd71DQR257mFBlMcTlbFnFWzNtHxewYEfSiaLS4el8d8nyhmKJd1CF4eOS0keLMAuSxubLBIeIGQW8YHCFFo7EH9+YDcQt9FMZEswTheaNxTHwHT8SZorJjMrEVwo4Zo0U8HSEyZvJMOg4RjnmmRr8nDYeIz3OMkbfE/QhBo+U9RnZJxjGCRh/WKmHEMWLNkfPKsGh/CWJk1JjG0kcuJggTt34VDP8aWAFhp4nybVb5+9qQhjSkIQ1pSEMa8k+Q5U9rV3dF8MpFBK+/7miVq1/HZ2qmo9D+pAAAAABJRU5ErkJggg==';
|
||||
const base64Flower = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGQAAABkBAMAAACCzIhnAAAAKlBMVEVHcEzDw8Ovr6+pqamUlJTCwsKenp61tbWxsbGysrLNzc2bm5u5ubmjo6MpovhuAAAACnRSTlMA/P79/sHDhiZS0DxZowAABBBJREFUWMPtl89rE0EUx7ctTXatB3MI1SWnDbUKPUgXqh4ED8Uf7KUVSm3ooVSpSii0Fn/gD4j4o+APiEoVmos9FO2celiqZVgwgaKHPQiCCkv+F99kM7Ozm5kxq1dfD91k9pPve9/3ZjbRNHHok/mKli4eIPNgSuRObuN9SqSEzM20iGnm0yIbqCuV7NSSSIV7uyPM6JMBYdeTOanh/QihJYZsUCSby+VkMj2AvOt0rAeQAwqE3lfKMZVlQCZk1QOCKkkVPadITCfIRNKxfoJI5+0OIFtJx14CMSg1mRSDko7VAfksRQzEbGYqxOJcVTWMCH2I1/IACNW0PWU2M8cmAVHtnH5mM1VRWtwKZjOd5JbF6s1IbaYqaotjNlPHgDAnlAizubTR6ovMYn052g/U5qcmOpi0WL8xTS/3IfSet5m8MEr5ajjF5le6dq/OJpobrdY0t3i9QgefWrxW9/1BLhk0E9m8FeUMhhXal499iD0eQRfDF+ts/tttORRerfp+oV7f4xJj82iUYm1Yzod+ZQEAlS/8mMBwKebVmCVp1f0JLS6zKd17+iwRKTARVg2SHtz3iEbBH+Q+U28zW2Jiza8Tjb1YFoYZMsJyjDqp3M9XBQdSdPLFdxEpvOB37JrHcmR/y9+LgoTlCFGZEa2sc6d4PGlweEa2JSVPoVm+IfGG3ZL037iV9oH+P+Jxc4HGVflNq1M0pivao/EopO4b/ojVCP9GjmiXOeS0DOn1o/iiccT4ORnyvBGF3yUywkQajW4Ti0SGuiy/wVSg/L8w+X/8Q+hvUx8Xd90z4oV5a1i88MbFWHz0WZZ1UrTwBGPX3Rat9AFiXRMRjoMdIdJLEOt2h7jrYOzgOamKZSWSNspOS0X8SAqRYmxRL7sg4eLzYmNehcxh3uoyud/BH2Udux4ywxFTc1xC7Mgf4vMhc5S+kSH3Y7yj+qpwIWSoPTVCOOPVthGx9FbGqrwFw6wSFxJr+17zeKcztt3u+2roAEVgUjDd+AHGuxHy2rZHaa8JMkTHEeyi85ANPO9j9BVuBRD2FY5LDMo/Sz/2hReqGIs/KiFin+CsPsYO/yvM3jL2vE8EbX7/Bf8ejtr2GLN65bioAdgLd8Bis/mD5GmP2qeqyo2ZwQEOtAjRIDH7mBKpUcMoApbZJ5UIxkEwxyMZyMxW/uKFvHCFR3SSmerHyDNQ2dF4JG6zIMpBgLfjSF9x1D6smFcYnGApjmSLICO3ecCDWrQ48geba9DI3STy2i7ax6WIB62fSyIZIiO3GFQqSURp8wCo7GhJBGwuSovJBNjb7kT6FPVnIa9qJ2Ko+l9mefGIdinaMp0yC1URYiwsdfNE45EuA5Cx9EhalfvN5s+UyItm81vaB3p4joniN+SCP7Qc1hblAAAAAElFTkSuQmCC';
|
||||
const base64FlowerWhite = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGQAAABkBAMAAACCzIhnAAAAElBMVEX///9HcEz///////////////84chYNAAAABnRSTlP/AGzCOYZj5g1nAAACfklEQVRYw+2YTVPDIBCGtza9Jw25a0bvcax30o73OOr//yvma2F3YWlpPTijXNpAHrK8LLALVPFium2vNIFSbwGKTGQA2GUiHcD29yDNy3sMIdUBQl7r2H8mOEVqAHgPkYZUS6Qc2zYhQqtjyDZEximCZwWZLIBeIgYShs2NzxKpSUehYpMJhURGb+O+w5BpMCAREKPnCDHbIY20SzhM5yxziAXpOiBXydrekT9i5XDEq4NIIHHgyU5mRGqviII4mREJJA4QJzMiILwlRJzpKxJKvCBm8OsBBbLux0tsPl4RKYm5aPu6jw1U4mGxEUR9g8M1PcqBEp/WJliNgYOXueBzS4jZSIcgY5lCtevgDSgyzE+rAfuOTQMq0yzvoGH18qju27Mayzs4fPyMziCx81NJa5RNfW7vPYK9KOfDiVkBxFHG8hAj9txuoBuSWORsFfkpBf7xKFLSeaOefEojh5jz22DJEqMP8fUyaKdQx+RnG+yXMpe8Aars8ueR1pVH/bW3FyyvPRw90upLDHwpgBDtg4aUBNkxRLXMAi03IhcZtr1m+FeI/O/JNyDmmL1djLOauSlNflBpW18RQ2bPqXI22MXXEk75KRHTnkPkYbESbdKP2ZFk0r5sIwffAjy1lx+vx7NLjB6/E7Jfv5ERKhzpN0w8IDE8IGFDv5dhz10s7GFiXRZcUeLCEG5P5nDq9k4PFDcoMpE3GY4OuxuCXhmuyNB6k0RsLIAvqp9NE5r8ZCSS8gxnUp7ODdYhZTqxuiJ9uyJJtPmpqJ7wVj+XVieS903iViHziqAhchLEJAyb7jWU647EpUofQ0ziUuXXXhDddtlllSwjgSQu7r4BRWhQqfDPMVwAAAAASUVORK5CYII='
|
||||
const base64Success = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGQAAABkBAMAAACCzIhnAAAAElBMVEVRUVFHcExTU1NRUVFRUVFRUVFOSlSUAAAABnRSTlP/AI6+VySB3ZENAAACcElEQVRYw+2YyYKCMAyGI8hdpdxdZu7gcpdZ7jL6/s8yYheSNi0aPdqbwOffpGmaFOYPD3gj4bisN7vddv17N/JVgxn5x12IWgIaWTuO/IE3PseQbwjGPo2cgRmHFLJwdm/X643zwiqOKPPJ1nj3sjEP2iiifZWj5bhopSyGaEO2HX5fbQJzwJ+W7x/jw5ZFjsEU0PMph9xE8i5EqprKALW95eJQURkgzw98uJ/JvwGecR7bIjWWsUgVrrIfFZ2HlLy3sKETD1mmRLRMRhGVssRa0xJkdn3SpJBymBkM8+pSSDXMDNyDaToVHd2fgpNt0sjwiUZO19+jGQ+gQEg9Oq+bufmAVGihomNmjQG7UG3020vrlm7lkFnKFGU3kZ0KGAdmKe821pipQ+qEKcrZeTL2g5FsUks4cStjEZWwXg0b0n4GxmEpkWwIs5VBynjgK7xZaz1/0D7OxkVuLpsY5BQNFyLS84VBjjbg0iL2r2EQHBOxBhikuUOkdxODVF1cxHoWtPPsiyXO455Iv34hssCO8EV4ZIYTjS8SR4qYSHRiTiYQ4ZFbHi0iIhhBTi6dTCgSWRcnw4h4yGTuyTAiOGBIWGoZTgSHJQl+LcOJ4OCnW6yX2bMnJ9pidCOXtkTkTrIGpYuOynAiOF14SamMiOCk5Ke+mq8BcOrrvym8d0zKIQnWT+M1WwOQNO4fFiWb18hhERxJPx2fblbPHHyC41VyiAtKBUFBIih7JMWVoIQTFIr3lKPN80WvoLSWFPC653ioTZA0I0FrQ7qU6asaK0H7JmkSJa2ooOGVtNUsc3j9FYHkIkJy3SG6VHnfXKXGP9t4N9Q4Ye98AAAAAElFTkSuQmCC';
|
||||
const base64SuccessWhite = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGQAAABkBAMAAACCzIhnAAAAGFBMVEVHcEz///////////////////////////8dS1W+AAAAB3RSTlMAiVYk6KvDHLfaegAAAo1JREFUWMPtWEtzmzAQNhCTq910ytXpiyvxTNOr60zrayepx9d02gnX4sTm7xcEiJX2gdnkGJ1A4tOnfWqXyeR1vMRYzrcPD9v5h5MBl3/Ldvx4cxIg/FWC8X0xjLjalM54uhhCfCrRuJURX0pi3EmIqZV7O59vrRZmguStHL9b7S7ftfLwOtiZDw7AHMtmquAQ12b5Wwbnordm8g9zLLO49qc/m2n6aKnhwPOGZ08hAiNHhheiHae1lOUPGZpQkPKa3q0mOUjaRzSRaGUjpy/mmWSwySSpllcEteBKAT52KEnSbblA51pJEPxBQoiH1FP4E3s5+FJv07h6/ylD6ui7B+9fq/ehrFB98ghec9EoVtyjK8pqCHLmCBOwMWSCeWFNN4MbPAk55NhsvoFHSSVR0k5TCTTEzlUGcqV/nVp7n9oIVkmtaqbAEqEgfdgHJPwsEAyZ9r4VAZXFjpEwyaw3+H2v42KYxKhs1XvY/gSSGv+IHyUSuHXCeZhLAgVI3EjgSGo1Fb3xO0tGGU9S2/KAIbtjxpJASG73qox6w5LUq0cEOa+iIONIWIilQSQ0pPa2jgaRQAgQP7c0mITRWGxpMAmEQFN2NAQJNCV0mI6GIIEO47hlQ0ORQLd0nL+hoUjg1m6I1TRr8uYEAriBHLcVFQ5UEMiBe3XkTBEG04WXlGKGxPnMS305XQPA1Ocn2JiuAZwE66fxnKwBnDTuXxZTMq85lwW6kt5ndLqZPefiU1yvmktcUSooChJF2aMprhQlnKJQ5FxRKkcVRa+itNYU8Io2oVkY14w0NMWYlqft91Bj9VHq+ca3b43BxjWJmla0sfKohlfTVpPN+93L/yLQ/IjQ/O5Q/VR5HdL4D7mlxmjwVdELAAAAAElFTkSuQmCC';
|
||||
const base64Empty = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAADIBAMAAABfdrOtAAAABGdBTUEAALGPC/xhBQAAAAFzUkdCAK7OHOkAAAAbUExURdvc3EdwTMLBwcjIyLSzs/Hx8ff39////19dXXz7IJEAAAAFdFJOU/4A6J9QDyyutAAAB5VJREFUeNrtnM1z4jYYxhUHkR4hdu9eU7Z75Ct7jgPbs9ZZmSuTrUWPmXTA186e+LMrf0uWLMtf2WkHXQgzln88et5XeiVMwPQdGrhCrpAr5Aq5Qv4TkJ07OGQFMLp1B4VYCz+kDblDQhJGeH4eEDLBYdLOHwaDWNBPIeHLYJAJ3meQ83IoCMTHDBKOBoKYGOeM8G0gyD0LObnDQB5ZSCtTNCBfsM9AboaBPLCQcDAIM1zht/dQEkMsd1DjI4hpw2YzMtBJeBbydWpCTJs3YDKGX62YgfGoVwi9KwtZJAzcYHHRm7sYCKD390nQSIoO5JGZIEOYxNoZ4+deISYLyeL5hLHbJ2QK98W0kudMgJe9Qh73odhO+KZHyNYGvgQS9gmJKhUigwSj3iBPUhXxePWmxBqHw0Mej9WQ3qILVjLC177yxNxXQ/7uK+Mn1aNVLsGsBTaWrSAPobYl0aUHt2fIs2Rgz7c9QYL0pSTkSzILLFtAJMH1cidN998T9E0/Sg73/pEEwrgkYRh86wlC949gJsR6EobBcz8hHOVgKYi2m6kZtodIkjEQvF3QjbGpmplB4/lRgJhxgRS2N15iijAvPmByDtCxfQhPJ8J4CR82rgCCBILarScw6X0OcMUyYrFVmbxErl0ZacFIoloOLdJAO42qY+NMDss2kKS8xmiZxcCpFKXWvpRGbQqJp5ixyRfJMmR6x0Fk+z29kmgWDYI5ziFbdug/84HxvduhWhLOJ2StPDQrMJPSjNANklh8QhB7dBO0yTGRwn1fkOk8rbQjiB8Ymww+JuiuN0icmSccK4naLMWYa/euL0+m23GyM8kgAc6sYeL4z04Qa4WjGepcKIliO8EUGSk7d9OGWOsoK31OSdy8TQZ59Y/hWbaV1IVs5/Ed6UzGK4nANAJiyGhRsZPUg2yzLe9hLyiJIyCaDU7udC2uy9pnkKvidlBUEltzFAqxRhBrBZm7HfZnjEQI3boqTsJq15PUDEaKZLgiJYc8OZtCtnM/4G93OFYooXpvdy0guwWWNQkEHl/j7Jw1XRmtlS9HYJkSPjk1IUnyyRqUKQn45NSDlP1mcg9i6En1ZU2IADnEtHF1Q+JwIcS/d5YakPuDUamEShGUHHikAz9oQCaE0CsrpYjDBVkEHQYdyK+EkKPhVErxqh1xbJ/oQf4gEeVsOIEc41WJNAwcd9GBfCZJezXsJhAvH+ImEEIOzlwXgpw5wQ0gH3MIOcsiQAahZuSD69/UQyxcQEggiQARQseVFO/ASAMCgM9gjkHZmhLENzi1AOhA7ullkMWUrfHKfpMiDBHtDIx6yCS6jseEnDUe7zcT6DGCtnrIY3olZw1hrPHkfucIAJa1EDu/lsVEyVmGGA67coKijeogFnMxlEaAV5ghRdDm1kDuuatZTJBGgJdOthIzsvZbDWRRuh6ScgR4EQLgagQvRQIxxQ4sxqcR4GE+c4CkjZQQW9YF89Y4OFAjOCki5KmiDxsBL3PlSJWlAFVogaoIePlYi2ClCJAHRa/cmre5eqTii4uvisqQJxqnip6pNd68DhEvyEs5xIyHBNdh4thCKhU++10kD7Gy1Up1A/o56FKuRJQWSFCuf8dpbisxhqHSKlSSgvG7VTaFKO5TzYD5VMPUxEB2YJNiqq3xYJ0KrroH8mq7xpoXqEZgfgNRUQsDtTVvUOk3sLUKbqrBr7YGvkCkQNC/9SA+vTYtvERrxiKEmcogk4ZqCLUd59MIEiFYHlIoxelCaJWDMmtOPIa80XVLbkb6hzaEwwTcPEmV4AIRlBGNIEmuJBFwLAZoHClJ36J8h+wxihpCqJosAnJrSKwEcQOFAFeWN4RQMYc0Ao4Jhg5gpASzyWcDvjpuDIlTkrGGJEro1rHIjHKR3wJCAj+z5oyi11gJBkXy9QFJIiAu78d+pgSjuWhGN0gUAZAcEncSJf4LRrZ8I94WEmcNCJJqBWYjVbE9bg2JxiyrViBWty6QvO56D8jPVWLA4ZX8dfkxvJJPl8t8aCX+pU/Iz1SCf7lc4OBK0OWfQaKLP0TKjj96VvIp+/BDZjwNKF2ItV2vN7sWStAl87oWkm3dZ+k3lEMoYXe8cT1eq2TOePJDD8KfQdxu6iEPxanUZa4HmZRq3dunGsj3BzFq6yD3wnZNX4n2emI2hXyXQpi6RRZdfSgxHNuxVZBFdyVeBPDmCsiksxKUiDAUEKuzkvRUEs0V08pjVyU2/yqFmF2VZGYop3peitdUiQd1pnrL7qTE01tPzE6eaEKm23dQwh2jNlbiay+/245zl94abw45CzNPyqYQ2++kxHGV1crWzg4A2yvR+BY7wziwnRLN7+O36aA54+ZKGjxZYK3txJpxQyUNn5GwtquII4+ACiWtnvawduu1A3SVtH5uhTvAVSpBG7fDYz6RQ+M6JWjmKm6g+RvTla9UMtspu+s+37VbVCupNqPx43CsNawSb1PbtcmDfQWmUILW7rRXSPHtSq5k5ur0a/hb7DQCUiW3G71ejX/wvV1kSoyNbp8Wvyqn1lCIKvl6gNDkNBYzt0GHdr+Pt9xGl1//ncAVcoVcIVfIFXKFXCFXyP8I8i8SyTW4yTz2lwAAAABJRU5ErkJggg=='
|
||||
const base64Error = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAADIBAMAAABfdrOtAAAAJFBMVEVHcEzo6Oibm5ukpKSbm5uampqbm5ubm5u5ubnn5+fm5ub6+vpGpDPdAAAAC3RSTlMA/v4hb+u20dq8aQhnHL4AAATwSURBVHja7ZvNb+JGGMbdjjdVe3NPodzeMhj1ZMUGujkh28B9wKR7iwwBqafWSbPqsbm0uTWtVlrTS9v0Et9yqLQS/1zHNiTZMMB4bO92d+dRUITt8c/PvPPx2h4URUpKSkpKSkpK6m3K6lFN73Q+S/+es3W3fzabTh2Dl0FAXEM+BgrgeXxRsdILTDU9n7J0vz/+EsCYC9KEiSFc06pf5zouqAkjkGWo0OG5Fq6j2IwZ6I4/4DhyTxc20oUjAj5PRTTrwvGAZ9p+ADzlD4RDctCoLhb7JUP87xeLxS3BZUIQ+YNCFi8wRwc4GIqGRK/GkM+5ILV8kFflOmkkkH/LddJ4c05eSSfSyTvrZPEmnCw+UCeuk84QvTSnUF0uCL68fBle/swF+RL1QZ/EpU6gHtOsAM64pnjPwxgTLsjoBM58ODNaAXYBT5QeGdr0KwcEA8He0TkPBLCjUDNHpG4qlg8eTCzXht1FVd1MxTPHj5LTtUiSrKK+7iDf8wBGxk4If3arLv/HF4Tox0A2nlFIGp+CIA+LzSamgbp4TNvZjECtDAjyMcB5HybLO6NxsRA1vmFCNjguNXDGWygbRPXh/B+zn9zPWK5RCkT18QxA57YgAqE+HGS6/tAoD4JO0ts+M2tbyQJpc95a5oI0xXNhCZGQ/x8E0VSCkUZY6Z6CIE/qdO5eL+yPlW6tMMgefPs3o7Bdt8iguJj4DThlZSY/rJ0yB+RraLDK2jAQCHyr4zIhT9mQ7vowygMZjpgQG+CYUV2E1EWqixyzICr8eFFnBB5ba1Y4IIfeKQvysW7ssZrwQLEFmvCBM2U6oRkdI5Wgm1QnO8RUTDlASoiESIiESMh7BDHKhlhu/LbSNUuEqL3lu1p945vO3BArADiaum7vBGDUKQfSIjBykooyrRPQnTIglHFfSagHeqd4iErwa9duEebpckGQjx/VT4v5fC0XhJHAd1mPRvJAVMZiAeQzTpgHYrPKqkGnUEiX+dCoNS4UgniHMTnUS4iESIiE7IS0x+mnVAidglDwVcmQJpy2WQ8VC4UgogfbA1RE4Nuw3UghEBV2rKl7V5ygAJPSY9KGQbP01mVjA5Fa2f1kQN2U3k+M9POWB8gnJUNMZJioWTMzKwOklyxgDrCXVcMMEF90tXM9C2TiCqmfCdIRi/jeewNpyerKok9WkGuzfCdYC+fXRsmBxxpVGG2zY0ZBbieJKvPrDQce3lxppBhIjGFWGkVoxUEoZt0Mukn2XBQH0bTHZpaMIp2sU/6qasU70W6/eHjM09VmYSc6C6Jpvz+orKvVxot8kL3HkMr9IZ9qeZ2o6RrO9mOI9ufdIR9peZ2gNIW31yC/MpyI9ngUDNIsezPks3vIsWDGdYA7cZa9pbqUVeCr/neiaR3U3R4BfXPg75vwb8I/b7HjxChobDZCO+Ny4wuxxaVxPPowcoNnrzPmzGFlX3RJHz2FafbhJ41n8PLx2DCM7KkwQgpqka1DVzKdJNHfJwBe9l/n0eSZFsIPjVSY8xZKZpSXnogwled98wAx3xRcdBNq1f1fhFVdIcL5tvaDolC7XaqaWStEtLOJHkbhlSauMLrma4yHEa03AVUoIUs/M2NQFkchBZiGUPeKonAnqhLOo4hrKf0WTyZ1FcU0Ki0hVrSr+Mucnvya7jYUKSkpKSkpKSmpD0f/AXq+Umj5XnXDAAAAAElFTkSuQmCC';
|
||||
const base64BackToTop = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAADIBAMAAABfdrOtAAAAElBMVEVRUVH+/v5HcEyZmZlRUVFRUVGm1ByOAAAABnRSTlPMzADMTZAJBBGsAAAEnElEQVR42t2cS27jMAyGf7/2U+QCQeDsbeQCgZDujaC5/1UmkzaJn+JDFGcw3LdfflKibJkkDnxrL7dbg7sNt6+L4O8OYBM+B0ys+QrGkHZG+OEEQ8g6go8Bx1GIGMdpNOQyIG6XdMgnSPtKhLQDGEZFBgYMkhKFtGBb0EIEjDgFRowoBVaMGAWpMedEfxMiZtwpUsgZCqtlkCNUdpVAWigtCCCDFtLwIWeoreZCWiRYYEKGFEjDg+yRZCUH0iLRAgNyToXUNCRZyMqWhGnUN2IPm3wSlwJ7IUspyCBkIQUZhCykIIeQuRTkEDKXAuM9srrtYbrZN7Y98giZSoFd+t1OxmMITG0dcrSFXFchZ1tIvQZpYWxhBbK3hpQrkMEa0iwh5t4a+QvZvDXyF7J5a+Qv5PPW21/I5623v5DPW29/IaO3Xv5Clrw1y1/Ikrdm+Qs5svw83yNnSJ5BQb4F/F7EIEJSnThGBAXxkFQfLOviQUE8JAUPsosHBfGQfDAtHhREQ1JxIV00KIgmrnRI84S0yAd5BAXxxJUck0f6Qnwr9qmr6xF5xLMjcwn/iudIEAdWnyjkEXlQKZiRVzoqRyLbgeUKKR8Q4alY7cSnoxzSf2ggsqehKr6YVpcXpOd7H93f60cKhOd7Re2LteUF4eLqiVS1mr0ge4io6C2+soaFkJ7MuuuQs1yITEp9hwwKISIpzR2iESKSIoT0rLNwuVHQqoSIpAQJpGce60vIUSdEIuUqgPTsJ5QFZK8UIpBS8iG94GFrDjlrhfCl8CG96Llxmle4kEr6vKWBPIVo9kqDQSRk9/3cWoikcCFPAd33v4dIChPyEvLzBA6RlEYWke4JEUnhKXkLeUEKxRHJFfKCQHGucIW8IdZSRkLeEGMpYyEjiK2UsZARxFTKRMgYYillImQMMZQyFTKB2EmZCplAuFLIHT8TMoWwpQwiIVMIUwqpZP5bp5CCvCTiQKr5f5lCQN+tPCBn2ZvVDFJwIDUP0m1BYAfZYRNSsCB7BqTbhoARePIxtZ9tgwWkoJcwCalmv3MBAemtO4R6dah2HaKQqj8Zvp9sQDjvJ21+SPCBHPJDDk6QITekEV7gqCC19CpKAym9IMfckKv4olMBCeIrWwVEfvkshzQekO9r9P1/ALk+IG1eSPCDiCJfyG+FyU+A6ZCa/piZDinpz7LpkCv5gdkAEshP5emQhv7onw6pGeULyZCSUYiRDAmMkpJkCKs4JhFSq8p8hJBSVbAkhARV6ZUQoisik0FqXTmcDHLVFfbJIEFXoiiCNMpiSxGkVJaNiiBBWQArgTTaUl4JpNQWJUsgQVteXQg+AKkLxQWFGKW+5J2+eVp4S168X3CF1CltCKdTJ8lb84YK2bUBO+wZW0Pqv9nk4tKu49N45NJC5dMM5tLW5tOg59Jq6NM06dL+abFXwr/RkuvTXJwae1abtE/Dt0/ruksTvs84AZ/BCC4jHnyGVfiM3VBQFANEXEah+Ax18RlP4zNox2dkkM/wI58xTn8yDCXGYCDV3W5RGSajtXyGhG1jbpbjzpwGt/0MJft8jqC7iUbQ/QZaxdnKqcIftwAAAABJRU5ErkJggg==';
|
||||
|
||||
export default {
|
||||
base64Arrow,
|
||||
base64ArrowWhite,
|
||||
base64Flower,
|
||||
base64FlowerWhite,
|
||||
base64Success,
|
||||
base64SuccessWhite,
|
||||
base64Empty,
|
||||
base64Error,
|
||||
base64BackToTop
|
||||
}
|
||||
244
components/z-paging/js/z-paging-utils.js
Normal file
244
components/z-paging/js/z-paging-utils.js
Normal file
@@ -0,0 +1,244 @@
|
||||
// [z-paging]工具类
|
||||
|
||||
import zI18n from './z-paging-i18n'
|
||||
import zConfig from './z-paging-config'
|
||||
import zLocalConfig from '../config/index'
|
||||
|
||||
const storageKey = 'Z-PAGING-REFRESHER-TIME-STORAGE-KEY'
|
||||
let config = null;
|
||||
|
||||
/*
|
||||
当z-paging未使用uni_modules管理时,控制台会有警告:WARNING: Module not found: Error: Can't resolve '@/uni_modules/z-paging'...
|
||||
此时注释下方try中的代码即可
|
||||
*/
|
||||
// #ifdef VUE2
|
||||
try {
|
||||
const contextKeys = require.context('@/uni_modules/z-paging', false, /\z-paging-config$/).keys();
|
||||
if (contextKeys.length) {
|
||||
const suffix = '.js';
|
||||
config = require('@/uni_modules/z-paging/z-paging-config' + suffix);
|
||||
}
|
||||
} catch (e) {}
|
||||
// #endif
|
||||
|
||||
//获取默认配置信息
|
||||
function gc(key, defaultValue) {
|
||||
if (!config) {
|
||||
if (zLocalConfig && Object.keys(zLocalConfig).length) {
|
||||
config = zLocalConfig;
|
||||
} else {
|
||||
const temConfig = zConfig.getConfig();
|
||||
if (zConfig && temConfig) {
|
||||
config = temConfig;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!config) return defaultValue;
|
||||
const value = config[_toKebab(key)];
|
||||
return value === undefined ? defaultValue : value;
|
||||
}
|
||||
|
||||
//判断两个数组是否相等
|
||||
function arrayIsEqual(arr1, arr2) {
|
||||
if (arr1 === arr2) return true;
|
||||
if (arr1.length !== arr2.length) return false;
|
||||
for (let i = 0; i < arr1.length; i++) {
|
||||
if (arr1[i] !== arr2[i]) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//获取最终的touch位置
|
||||
function getTouch(e) {
|
||||
let touch = null;
|
||||
if (e.touches && e.touches.length) {
|
||||
touch = e.touches[0];
|
||||
} else if (e.changedTouches && e.changedTouches.length) {
|
||||
touch = e.changedTouches[0];
|
||||
} else if (e.datail && e.datail != {}) {
|
||||
touch = e.datail;
|
||||
} else {
|
||||
return {
|
||||
touchX: 0,
|
||||
touchY: 0
|
||||
}
|
||||
}
|
||||
return {
|
||||
touchX: touch.clientX,
|
||||
touchY: touch.clientY
|
||||
};
|
||||
}
|
||||
|
||||
//判断当前手势是否在z-paging内触发
|
||||
function getTouchFromZPaging(target) {
|
||||
if (target && target.tagName && target.tagName !== 'BODY' && target.tagName !== 'UNI-PAGE-BODY') {
|
||||
var classList = target.classList;
|
||||
if (classList && classList.contains('zp-paging-touch-view')) {
|
||||
return true;
|
||||
} else {
|
||||
return getTouchFromZPaging(target.parentNode);
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
//获取z-paging所在的parent
|
||||
function getParent(parent) {
|
||||
if (!parent) return null;
|
||||
if (parent.$refs.paging) return parent;
|
||||
return getParent(parent.$parent);
|
||||
}
|
||||
|
||||
//打印错误信息
|
||||
function consoleErr(err) {
|
||||
console.error(`[z-paging]${err}`);
|
||||
}
|
||||
|
||||
//打印警告信息
|
||||
function consoleWarn(warn) {
|
||||
console.warn(`[z-paging]${warn}`);
|
||||
}
|
||||
|
||||
//设置下拉刷新时间
|
||||
function setRefesrherTime(time, key) {
|
||||
try {
|
||||
let datas = getRefesrherTime();
|
||||
if (!datas) {
|
||||
datas = {};
|
||||
}
|
||||
datas[key] = time;
|
||||
uni.setStorageSync(storageKey, datas);
|
||||
} catch (e) {}
|
||||
}
|
||||
|
||||
//获取下拉刷新时间
|
||||
function getRefesrherTime() {
|
||||
try {
|
||||
const datas = uni.getStorageSync(storageKey);
|
||||
return datas;
|
||||
} catch (e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
//通过下拉刷新标识key获取下拉刷新时间
|
||||
function getRefesrherTimeByKey(key) {
|
||||
const datas = getRefesrherTime();
|
||||
if (datas) {
|
||||
const data = datas[key];
|
||||
if (data) return data;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
//通过下拉刷新标识key获取下拉刷新时间(格式化之后)
|
||||
function getRefesrherFormatTimeByKey(key) {
|
||||
const time = getRefesrherTimeByKey(key);
|
||||
let timeText = zI18n.t['refresherUpdateTimeNoneText'][zI18n.getLanguage()];
|
||||
if (time) {
|
||||
timeText = _timeFormat(time);
|
||||
}
|
||||
return `${zI18n.t['refresherUpdateTimeText'][zI18n.getLanguage()]}${timeText}`;
|
||||
}
|
||||
|
||||
//将文本的px或者rpx转为px的值
|
||||
function convertTextToPx(text) {
|
||||
const dataType = Object.prototype.toString.call(text);
|
||||
if (dataType === '[object Number]') {
|
||||
return text;
|
||||
}
|
||||
let isRpx = false;
|
||||
if (text.indexOf('rpx') !== -1 || text.indexOf('upx') !== -1) {
|
||||
text = text.replace('rpx', '').replace('upx', '');
|
||||
isRpx = true;
|
||||
} else if (text.indexOf('px') !== -1) {
|
||||
text = text.replace('px', '');
|
||||
}
|
||||
if (!isNaN(text)) {
|
||||
if (isRpx) return Number(uni.upx2px(text));
|
||||
return Number(text);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//获取当前时间
|
||||
function getTime() {
|
||||
return (new Date()).getTime();
|
||||
}
|
||||
|
||||
//获取z-paging实例id
|
||||
function getInstanceId() {
|
||||
let s = [];
|
||||
const hexDigits = "0123456789abcdef";
|
||||
for (let i = 0; i < 10; i++) {
|
||||
s[i] = hexDigits.substr(Math.floor(Math.random() * 0x10), 1);
|
||||
}
|
||||
return s.join('') + getTime();
|
||||
}
|
||||
|
||||
//------------------ 私有方法 ------------------------
|
||||
//时间格式化
|
||||
function _timeFormat(time) {
|
||||
const date = new Date(time);
|
||||
const currentDate = new Date();
|
||||
const dateDay = new Date(time).setHours(0, 0, 0, 0);
|
||||
const currentDateDay = new Date().setHours(0, 0, 0, 0);
|
||||
const disTime = dateDay - currentDateDay;
|
||||
let dayStr = '';
|
||||
const timeStr = _dateTimeFormat(date);
|
||||
if (disTime === 0) {
|
||||
dayStr = zI18n.t['refresherUpdateTimeTodayText'][zI18n.getLanguage()];
|
||||
} else if (disTime === -86400000) {
|
||||
dayStr = zI18n.t['refresherUpdateTimeYesterdayText'][zI18n.getLanguage()];
|
||||
} else {
|
||||
dayStr = _dateDayFormat(date, date.getFullYear() !== currentDate.getFullYear());
|
||||
}
|
||||
return `${dayStr} ${timeStr}`;
|
||||
}
|
||||
|
||||
//date格式化为年月日
|
||||
function _dateDayFormat(date, showYear = true) {
|
||||
const year = date.getFullYear();
|
||||
const month = date.getMonth() + 1;
|
||||
const day = date.getDate();
|
||||
if (showYear) {
|
||||
return `${year}-${_fullZeroToTwo(month)}-${_fullZeroToTwo(day)}`;
|
||||
} else {
|
||||
return `${_fullZeroToTwo(month)}-${_fullZeroToTwo(day)}`;
|
||||
}
|
||||
}
|
||||
|
||||
//data格式化为时分
|
||||
function _dateTimeFormat(date) {
|
||||
const hour = date.getHours();
|
||||
const minute = date.getMinutes();
|
||||
return `${_fullZeroToTwo(hour)}:${_fullZeroToTwo(minute)}`;
|
||||
}
|
||||
|
||||
//不满2位在前面填充0
|
||||
function _fullZeroToTwo(str) {
|
||||
str = str.toString();
|
||||
if (str.length === 1) return '0' + str;
|
||||
return str;
|
||||
}
|
||||
|
||||
//驼峰转短横线
|
||||
function _toKebab(value) {
|
||||
return value.replace(/([A-Z])/g, "-$1").toLowerCase();
|
||||
}
|
||||
|
||||
export default {
|
||||
gc,
|
||||
setRefesrherTime,
|
||||
getRefesrherFormatTimeByKey,
|
||||
arrayIsEqual,
|
||||
getTouch,
|
||||
getTouchFromZPaging,
|
||||
getParent,
|
||||
convertTextToPx,
|
||||
getTime,
|
||||
getInstanceId,
|
||||
consoleErr,
|
||||
consoleWarn
|
||||
};
|
||||
Reference in New Issue
Block a user