第一次提交

This commit is contained in:
@fawn-nine
2024-05-22 13:42:15 +08:00
commit bb53af8bde
2133 changed files with 129959 additions and 0 deletions

View File

@@ -0,0 +1,14 @@
## 2.0.12021-08-16
1.自定义下拉刷新view无需设置`refresher-threshold`将根据view自动计算高度。
2.修复在iOS 13中下拉刷新抖动的问题。
3.新增`inside-more`,支持在分页未满一屏时自动加载下一页。
4.修复z-paging prop代码自动补全无效的问题完善代码自动补全文档注释。
5.修复在微信小程序中提示uni is not defined的bug。
6.修复在某些情况下下拉刷新页面会跟着下拉的bug。
7.其他细节优化。
## 2.0.02021-08-16
1.自定义下拉刷新view无需设置`refresher-threshold`将根据view自动计算高度。
2.修复在iOS 13中下拉刷新抖动的问题。
3.新增`inside-more`,支持在分页未满一屏时自动加载下一页。
4.修复z-paging prop代码自动补全无效的问题完善代码自动补全文档注释。
5.其他细节优化。

View File

@@ -0,0 +1,170 @@
<!-- z-paging -->
<!-- github地址:https://github.com/SmileZXLee/uni-z-paging -->
<!-- dcloud地址:https://ext.dcloud.net.cn/plugin?id=3935 -->
<!-- 反馈QQ群790460711 -->
<!-- 空数据占位view此组件支持easycom规范可以在项目中直接引用 -->
<template>
<view class="zp-container" :style="[finalEmptyViewStyle]">
<view class="zp-main">
<image v-if="!emptyViewImg.length" class="zp-main-image" :style="[emptyViewImgStyle]" :src="emptyImg"></image>
<image v-else class="zp-main-image" mode="aspectFit" :style="[emptyViewImgStyle]" :src="emptyViewImg"></image>
<text class="zp-main-title" :style="[emptyViewTitleStyle]">{{emptyViewText}}</text>
<text v-if="showEmptyViewReload" class="zp-main-error-btn" :style="[emptyViewReloadStyle]"
@click="reloadClick">{{emptyViewReloadText}}</text>
</view>
</view>
</template>
<script>
import zStatic from '../z-paging/js/z-paging-static'
export default {
data() {
return {
base64Empty: zStatic.base64Empty,
base64Error: zStatic.base64Error
};
},
props: {
//空数据描述文字
emptyViewText: {
type: String,
default: function() {
return '没有数据哦~'
}
},
//空数据图片
emptyViewImg: {
type: String,
default: function() {
return ''
}
},
//是否显示空数据图重新加载按钮
showEmptyViewReload: {
type: Boolean,
default: function() {
return false
}
},
//空数据点击重新加载文字
emptyViewReloadText: {
type: String,
default: function() {
return '重新加载'
}
},
//是否是加载失败
isLoadFailed: {
type: Boolean,
default: function() {
return false
}
},
//空数据图样式
emptyViewStyle: {
type: Object,
default: function() {
return {}
}
},
//空数据图img样式
emptyViewImgStyle: {
type: Object,
default: function() {
return {}
}
},
//空数据图描述文字样式
emptyViewTitleStyle: {
type: Object,
default: function() {
return {}
}
},
//空数据图重新加载按钮样式
emptyViewReloadStyle: {
type: Object,
default: function() {
return {}
}
},
//空数据图z-index
emptyViewZIndex: {
type: Number,
default: function() {
return 9
}
}
},
computed: {
emptyImg() {
if (this.isLoadFailed) {
return this.base64Error;
} else {
return this.base64Empty;
}
},
finalEmptyViewStyle(){
this.emptyViewStyle['z-index'] = this.emptyViewZIndex;
return this.emptyViewStyle;
}
},
methods: {
reloadClick() {
this.$emit('reload');
}
}
}
</script>
<style scoped>
.zp-container {
/* #ifndef APP-NVUE */
/* position: absolute;
top: 0;
left: 0; */
width: 100%;
height: 600rpx;
display: flex;
/* #endif */
/* #ifdef APP-NVUE */
/* flex: 1; */
/* #endif */
align-items: center;
justify-content: center;
}
.zp-main {
/* #ifndef APP-NVUE */
display: flex;
margin-top: -150rpx;
/* #endif */
/* #ifdef APP-NVUE */
margin-top: -100rpx;
/* #endif */
flex-direction: column;
align-items: center;
}
.zp-main-image {
width: 200rpx;
height: 200rpx;
}
.zp-main-title {
font-size: 26rpx;
color: #aaaaaa;
text-align: center;
margin-top: 10rpx;
}
.zp-main-error-btn {
font-size: 26rpx;
padding: 8rpx 24rpx;
border: solid 1px #dddddd;
border-radius: 6rpx;
color: #aaaaaa;
margin-top: 50rpx;
}
</style>

View File

@@ -0,0 +1,86 @@
<!-- z-paging -->
<!-- github地址:https://github.com/SmileZXLee/uni-z-paging -->
<!-- dcloud地址:https://ext.dcloud.net.cn/plugin?id=3935 -->
<!-- 反馈QQ群790460711 -->
<!-- 滑动切换选项卡swiper-item此组件支持easycom规范可以在项目中直接引用 -->
<template>
<view class="zp-swiper-item-container">
<z-paging ref="paging" :fixed="false" @query="_queryList" @listChange="_updateList" :mounted-auto-call-reload="false"
style="height: 100%;">
<slot></slot>
</z-paging>
</view>
</template>
<script>
import zPaging from '../z-paging/z-paging'
export default {
name: "z-paging-swiper-item",
components: {
zPaging
},
data() {
return {
firstLoaded: false
}
},
props: {
//当前组件的index也就是当前组件是swiper中的第几个
tabIndex: {
type: Number,
default: function() {
return 0
}
},
//当前swiper切换到第几个index
currentIndex: {
type: Number,
default: function() {
return 0
}
},
},
watch: {
currentIndex: {
handler(newVal, oldVal) {
if (newVal === this.tabIndex) {
//懒加载当滑动到当前的item时才去加载
if (!this.firstLoaded) {
setTimeout(() => {
this.$refs.paging.reload();
}, 5);
}
}
},
immediate: true
}
},
methods: {
reload(data) {
this.$refs.paging.reload(data);
},
complete(data) {
this.firstLoaded = true;
this.$refs.paging.complete(data);
},
_queryList(pageNo, pageSize) {
this.$emit('query', pageNo, pageSize);
},
_updateList(list) {
this.$emit('updateList', list);
}
}
}
</script>
<style scoped>
.zp-swiper-item-container {
/* #ifndef APP-NVUE */
height: 100%;
/* #endif */
/* #ifdef APP-NVUE */
flex: 1;
/* #endif */
}
</style>

View File

@@ -0,0 +1,126 @@
<!-- z-paging -->
<!-- github地址:https://github.com/SmileZXLee/uni-z-paging -->
<!-- dcloud地址:https://ext.dcloud.net.cn/plugin?id=3935 -->
<!-- 反馈QQ群790460711 -->
<!-- 滑动切换选项卡swiper此组件支持easycom规范可以在项目中直接引用 -->
<template>
<view :class="fixed?'zp-swiper-container zp-swiper-container-fixed':'zp-swiper-container'" :style="[swiperStyle]">
<slot v-if="$slots.top" name="top"></slot>
<view class="zp-swiper-super">
<view class="zp-swiper">
<slot/></slot>
</view>
</view>
<slot v-if="$slots.bottom" name="bottom"></slot>
</view>
</template>
<script>
export default {
name: "z-paging-swiper",
data() {
return {
systemInfo: null
};
},
props: {
//是否使用fixed布局默认为是
fixed: {
type: Boolean,
default: true
},
//是否开启底部安全区域适配
safeAreaInsetBottom: {
type: Boolean,
default: false
}
},
mounted() {
this.$nextTick(() => {
this.systemInfo = uni.getSystemInfoSync();
})
},
computed: {
swiperStyle() {
if (!this.systemInfo) {
return {};
}
let swiperStyle = {};
const windowTop = this.systemInfo.windowTop;
const windowBottom = this.systemInfo.windowBottom;
if (this.fixed) {
if (windowTop && windowTop !== undefined) {
swiperStyle.top = windowTop + 'px';
}
let bottom = 0;
if (windowBottom && windowBottom !== undefined) {
bottom = windowBottom;
}
if (this.safeAreaInsetBottom) {
bottom += this.safeAreaBottom;
}
swiperStyle.bottom = bottom + 'px';
}
return swiperStyle;
},
safeAreaBottom() {
if (!this.systemInfo) {
return 0;
}
let safeAreaBottom = 0;
// #ifdef MP-WEIXIN
safeAreaBottom = this.systemInfo.screenHeight - this.systemInfo.safeArea.bottom;
// #endif
// #ifdef APP-PLUS || H5
safeAreaBottom = this.systemInfo.safeAreaInsets.bottom || 0;
// #endif
return Math.abs(safeAreaBottom);
}
}
}
</script>
<style scoped>
.zp-swiper-container {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-direction: column;
flex: 1;
}
.zp-swiper-container-fixed {
position: fixed;
/* #ifndef APP-NVUE */
height: auto;
width: auto;
/* #endif */
top: 0;
left: 0;
bottom: 0;
right: 0;
}
.zp-swiper-super {
flex: 1;
position: relative;
}
.zp-swiper {
/* #ifndef APP-NVUE */
height: 100%;
width: 100%;
position: absolute;
top: 0;
left: 0;
/* #endif */
/* #ifdef APP-NVUE */
flex: 1;
/* #endif */
}
.zp-swiper-item {
height: 100%;
}
</style>

View File

@@ -0,0 +1,161 @@
<!-- z-paging -->
<!-- github地址:https://github.com/SmileZXLee/uni-z-paging -->
<!-- dcloud地址:https://ext.dcloud.net.cn/plugin?id=3935 -->
<!-- 反馈QQ群790460711 -->
<!-- 上拉加载更多view -->
<template>
<view class="zp-load-more-container" :style="[zConfig.loadingMoreCustomStyle]">
<text
:class="zConfig.defaultThemeStyle==='white'?'zp-loading-more-line zp-loading-more-line-white':'zp-loading-more-line zp-loading-more-line-black'"
:style="[zConfig.loadingMoreNoMoreLineCustomStyle]"
v-if="zConfig.showLoadingMoreNoMoreLine&&zConfig.loadingStatus===2"></text>
<!-- #ifndef APP-NVUE -->
<image v-if="zConfig.loadingStatus===1&&zConfig.loadingMoreLoadingIconCustomImage.length"
:src="zConfig.loadingMoreLoadingIconCustomImage" :class="{'zp-loading-more-line-loading-custom-image':true,'zp-loading-more-line-loading-custom-image-animated':zConfig.loadingMoreLoadingAnimated}">
</image>
<image
v-if="zConfig.loadingStatus===1&&zConfig.loadingMoreLoadingIconType==='flower'&&!zConfig.loadingMoreLoadingIconCustomImage.length"
class="zp-loading-more-line-loading-image" :style="[zConfig.loadingMoreLoadingIconCustomStyle]"
:src="zConfig.defaultThemeStyle==='white'?base64FlowerWhite:base64Flower">
</image>
<!-- #endif -->
<!-- #ifdef APP-NVUE -->
<view>
<loading-indicator v-if="zConfig.loadingStatus===1"
:style="[{color:zConfig.defaultThemeStyle==='white'?'white':'#777777'}]" :animating="true"
class="zp-loading-more-line-loading-image">
</loading-indicator>
</view>
<!-- #endif -->
<text
v-if="zConfig.loadingStatus===1&&zConfig.loadingMoreLoadingIconType==='circle'&&!zConfig.loadingMoreLoadingIconCustomImage.length"
:class="zConfig.defaultThemeStyle==='white'?'zp-loading-more-line-loading-view zp-loading-more-line-loading-view-white':'zp-loading-more-line-loading-view zp-loading-more-line-loading-view-black'"
:style="[zConfig.loadingMoreLoadingIconCustomStyle]"></text>
<text
:class="zConfig.defaultThemeStyle==='white'?'zp-loading-more-text zp-loading-more-text-white':'zp-loading-more-text zp-loading-more-text-black'">{{ownLoadingMoreText}}</text>
<text
:class="zConfig.defaultThemeStyle==='white'?'zp-loading-more-line zp-loading-more-line-white':'zp-loading-more-line zp-loading-more-line-black'"
:style="[zConfig.loadingMoreNoMoreLineCustomStyle]"
v-if="zConfig.showLoadingMoreNoMoreLine&&zConfig.loadingStatus===2"></text>
</view>
</template>
<script>
import zStatic from '../js/z-paging-static'
export default {
name: 'z-paging-load-more',
data() {
return {
base64Arrow: zStatic.base64Arrow,
base64Flower: zStatic.base64Flower,
base64FlowerWhite: zStatic.base64FlowerWhite,
};
},
props: ['zConfig'],
computed: {
ownLoadingMoreText() {
const loadingMoreText = this.loadingStatusTextMap[this.zConfig.loadingStatus];
return loadingMoreText;
},
loadingStatusTextMap() {
return {
0: this.zConfig.loadingMoreDefaultText,
1: this.zConfig.loadingMoreLoadingText,
2: this.zConfig.loadingMoreNoMoreText,
3: this.zConfig.loadingMoreFailText,
}
}
}
}
</script>
<style scoped>
@import "../css/z-paging-static.css";
.zp-load-more-container {
height: 80rpx;
font-size: 27rpx;
/* #ifndef APP-NVUE */
clear: both;
display: flex;
/* #endif */
flex-direction: row;
align-items: center;
justify-content: center;
}
.zp-loading-more-line-loading-custom-image {
color: #a4a4a4;
margin-right: 8rpx;
width: 28rpx;
height: 28rpx;
}
.zp-loading-more-line-loading-custom-image-animated{
/* #ifndef APP-NVUE */
animation: loading-circle 1s linear infinite;
/* #endif */
}
.zp-loading-more-line-loading-view {
margin-right: 8rpx;
width: 22rpx;
height: 23rpx;
border: 3rpx solid #dddddd;
border-radius: 50%;
/* #ifndef APP-NVUE */
animation: loading-circle 1s linear infinite;
/* #endif */
}
.zp-loading-more-line-loading-view-black {
border-color: #c8c8c8;
border-top-color: #444444;
}
.zp-loading-more-line-loading-view-white {
border-color: #aaaaaa;
border-top-color: #ffffff;
}
.zp-loading-more-text {
/* #ifdef APP-NVUE */
font-size: 30rpx;
margin: 0rpx 10rpx;
/* #endif */
}
.zp-loading-more-text-black {
color: #a4a4a4;
}
.zp-loading-more-text-white {
color: #efefef;
}
.zp-loading-more-line {
height: 1px;
width: 100rpx;
margin: 0rpx 10rpx;
}
.zp-loading-more-line-black {
background-color: #eeeeee;
}
.zp-loading-more-line-white {
background-color: #efefef;
}
@keyframes loading-circle {
0% {
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
}
100% {
-webkit-transform: rotate(360deg);
transform: rotate(360deg);
}
}
</style>

View File

@@ -0,0 +1,259 @@
<!-- z-paging -->
<!-- github地址:https://github.com/SmileZXLee/uni-z-paging -->
<!-- dcloud地址:https://ext.dcloud.net.cn/plugin?id=3935 -->
<!-- 反馈QQ群790460711 -->
<!-- 下拉刷新view -->
<template>
<view style="height: 100%;">
<view
:class="['zp-custom-refresher-container',{'zp-custom-refresher-container-padding':showRefresherUpdateTime}]"
style="height: 100%;">
<view class="zp-custom-refresher-left">
<image v-if="refresherStatus!==2" :class="refresherLeftImageClass"
:style="[{width: showRefresherUpdateTime?'36rpx':'30rpx',height: showRefresherUpdateTime?'36rpx':'30rpx','margin-right': showRefresherUpdateTime?'20rpx':'8rpx'}]"
:src="defaultThemeStyle==='white'?base64ArrowWhite:base64Arrow">
</image>
<!-- #ifndef APP-NVUE -->
<image v-else class="zp-loading-more-line-loading-image zp-custom-refresher-left-image"
:style="[{width: showRefresherUpdateTime?'36rpx':'30rpx',height: showRefresherUpdateTime?'36rpx':'30rpx','margin-right': showRefresherUpdateTime?'20rpx':'8rpx'}]"
:src="defaultThemeStyle==='white'?base64FlowerWhite:base64Flower">
</image>
<!-- #endif -->
<!-- #ifdef APP-NVUE -->
<view v-else :style="[{'margin-right':showRefresherUpdateTime?'18rpx':'12rpx'}]">
<loading-indicator
:class="systemInfo.platform==='ios'?'zp-loading-image-ios':'zp-loading-image-android'"
:style="[{color:defaultThemeStyle==='white'?'white':'#777777'}]" :animating="true">
</loading-indicator>
</view>
<!-- #endif -->
</view>
<view class="zp-custom-refresher-right">
<text class="zp-custom-refresher-right-text"
:style="[refresherRightTextStyle]">{{refresherStatusTextMap[refresherStatus]||refresherDefaultText}}
</text>
<text class="zp-custom-refresher-right-text zp-custom-refresher-right-time-text"
:style="[refresherRightTextStyle]"
v-if="showRefresherUpdateTime&&refresherTimeText.length">{{refresherTimeText}}
</text>
</view>
</view>
</view>
</template>
<script>
const systemInfo = uni.getSystemInfoSync();
import zStatic from '../js/z-paging-static'
import {
getRefesrherFormatTimeByKey
} from '../js/z-paging-utils'
export default {
name: 'z-paging-refresh',
data() {
return {
systemInfo: systemInfo,
base64Arrow: zStatic.base64Arrow,
base64ArrowWhite: zStatic.base64ArrowWhite,
base64Flower: zStatic.base64Flower,
base64FlowerWhite: zStatic.base64FlowerWhite,
refresherTimeText: '',
isRefresherLeftImageClassLoaded: false
};
},
props: {
'refresherStatus': {
default: 0
},
'defaultThemeStyle': {},
'refresherDefaultText': {},
'refresherPullingText': {},
'refresherPullingText': {},
'refresherRefreshingText': {},
'showRefresherUpdateTime': {
default: false
},
'refresherUpdateTimeKey': {}
},
computed: {
refresherStatusTextMap() {
this.updateTime(this.refresherUpdateTimeKey);
return {
0: this.refresherDefaultText,
1: this.refresherPullingText,
2: this.refresherRefreshingText
};
},
refresherLeftImageClass() {
let refresherLeftImageClass = '';
if (this.refresherStatus === 0) {
if (this.isRefresherLeftImageClassLoaded) {
refresherLeftImageClass = 'zp-custom-refresher-left-image zp-custom-refresher-arrow-down';
} else {
this.isRefresherLeftImageClassLoaded = true;
refresherLeftImageClass =
'zp-custom-refresher-left-image zp-custom-refresher-arrow-down-no-duration';
}
} else {
refresherLeftImageClass = 'zp-custom-refresher-left-image zp-custom-refresher-arrow-top';
}
return refresherLeftImageClass;
},
refresherRightTextStyle() {
let refresherRightTextStyle = {};
let color = '#555555';
if (this.defaultThemeStyle === 'white') {
color = '#efefef';
}
// #ifdef APP-NVUE
if (this.showRefresherUpdateTime) {
refresherRightTextStyle = {
'height': '40rpx',
'line-height': '40rpx'
};
} else {
refresherRightTextStyle = {
'height': '80rpx',
'line-height': '80rpx'
};
}
// #endif
refresherRightTextStyle['color'] = color;
return refresherRightTextStyle;
}
},
methods: {
updateTime(refresherUpdateTimeKey) {
if (!refresherUpdateTimeKey) {
refresherUpdateTimeKey = this.refresherUpdateTimeKey;
}
if (this.showRefresherUpdateTime) {
this.refresherTimeText = getRefesrherFormatTimeByKey(refresherUpdateTimeKey);
}
}
}
}
</script>
<style scoped>
@import "../css/z-paging-static.css";
.zp-custom-refresher-container {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-direction: row;
justify-content: center;
align-items: center;
}
.zp-custom-refresher-container-padding {
/* #ifdef APP-NVUE */
padding: 15rpx 0rpx;
/* #endif */
}
.zp-custom-refresher-left {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-direction: row;
align-items: center;
overflow: hidden;
}
.zp-custom-refresher-left-image {
/* #ifndef APP-NVUE */
transform: rotate(180deg);
margin-top: 2rpx;
/* #endif */
/* #ifdef MP-ALIPAY */
margin-top: 0rpx;
/* #endif */
/* #ifdef APP-NVUE */
transition-duration: .2s;
transition-property: transform;
color: #666666;
/* #endif */
}
.zp-custom-refresher-arrow-top {
/* #ifndef APP-NVUE */
animation: refresher-arrow-top .2s linear;
-webkit-animation: refresher-arrow-top .2s linear;
animation-fill-mode: forwards;
-webkit-animation-fill-mode: forwards;
/* #endif */
/* #ifdef APP-NVUE */
transform: rotate(0deg);
/* #endif */
}
.zp-custom-refresher-arrow-down {
/* #ifndef APP-NVUE */
animation: refresher-arrow-down .2s linear;
-webkit-animation: refresher-arrow-down .2s linear;
animation-fill-mode: forwards;
-webkit-animation-fill-mode: forwards;
/* #endif */
/* #ifdef APP-NVUE */
transform: rotate(180deg);
/* #endif */
}
.zp-custom-refresher-arrow-down-no-duration {
/* #ifndef APP-NVUE */
animation: refresher-arrow-down 0s linear;
-webkit-animation: refresher-arrow-down 0s linear;
animation-fill-mode: forwards;
-webkit-animation-fill-mode: forwards;
/* #endif */
/* #ifdef APP-NVUE */
transform: rotate(180deg);
/* #endif */
}
.zp-custom-refresher-right {
font-size: 27rpx;
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-direction: column;
align-items: center;
justify-content: center;
}
.zp-custom-refresher-right-text {
/* #ifdef APP-NVUE */
font-size: 28rpx;
/* #endif */
}
.zp-custom-refresher-right-time-text {
margin-top: 10rpx;
font-size: 24rpx;
}
@keyframes refresher-arrow-top {
0% {
-webkit-transform: rotate(180deg);
transform: rotate(180deg);
}
100% {
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
}
}
@keyframes refresher-arrow-down {
0% {
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
}
100% {
-webkit-transform: rotate(180deg);
transform: rotate(180deg);
}
}
</style>

View File

@@ -0,0 +1,161 @@
/* z-paging
github地址:https://github.com/SmileZXLee/uni-z-paging
dcloud地址:https://ext.dcloud.net.cn/plugin?id=3935
反馈QQ群790460711
*/
.z-paging-content {
position: relative;
/* #ifndef APP-NVUE */
display: flex;
width: 100%;
height: 100%;
/* #endif */
flex-direction: column;
}
.z-paging-content-fixed {
position: fixed;
/* #ifndef APP-NVUE */
height: auto;
width: auto;
/* #endif */
top: 0;
left: 0;
bottom: 0;
right: 0;
}
.zp-page-scroll-top,
.zp-page-scroll-bottom {
/* #ifndef APP-NVUE */
width: auto;
/* #endif */
position: fixed;
left: 0;
right: 0;
z-index: 999;
}
.zp-scroll-view-super {
flex: 1;
position: relative;
}
.zp-custom-refresher-container {
overflow: hidden;
}
.zp-scroll-view {
height: 100%;
width: 100%;
}
.zp-scroll-view-absolute {
position: absolute;
top: 0;
left: 0;
}
.zp-paging-touch-view {
width: 100%;
height: 100%;
position: relative;
}
.zp-fixed-bac-view {
position: absolute;
width: 100%;
top: 0;
left: 0;
height: 200px;
}
.zp-paging-main {
height: 100%;
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-direction: column;
}
.zp-paging-container {
flex: 1;
position: relative;
}
.zp-chat-record-loading-container {
/* #ifndef APP-NVUE */
display: flex;
width: 100%;
/* #endif */
/* #ifdef APP-NVUE */
width: 750rpx;
/* #endif */
align-items: center;
justify-content: center;
height: 60rpx;
font-size: 26rpx;
}
.zp-chat-record-loading-custom-image {
width: 35rpx;
height: 35rpx;
/* #ifndef APP-NVUE */
animation: loading-flower 1s linear infinite;
/* #endif */
}
.zp-custom-refresher-container {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-direction: row;
justify-content: center;
align-items: center;
}
.zp-back-to-top {
width: 76rpx;
height: 76rpx;
z-index: 999;
position: absolute;
bottom: 0rpx;
right: 25rpx;
transition-duration: .3s;
transition-property: opacity;
}
.zp-back-to-top-show {
opacity: 1;
}
.zp-back-to-top-hide {
opacity: 0;
}
.zp-back-to-top-img {
/* #ifndef APP-NVUE */
width: 100%;
height: 100%;
/* #endif */
/* #ifdef APP-NVUE */
flex: 1;
/* #endif */
z-index: 999;
}
.zp-empty-view {
/* #ifdef APP-NVUE */
height: 100%;
/* #endif */
flex: 1;
}
.zp-n-refresh-container {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
justify-content: center;
width: 750rpx;
}

View File

@@ -0,0 +1,38 @@
/* z-paging
github地址:https://github.com/SmileZXLee/uni-z-paging
dcloud地址:https://ext.dcloud.net.cn/plugin?id=3935
反馈QQ群790460711
公用的静态css资源 */
.zp-loading-more-line-loading-image {
margin-right: 8rpx;
width: 28rpx;
height: 28rpx;
/* #ifndef APP-NVUE */
animation: loading-flower 1s steps(12) infinite;
/* #endif */
color: #666666;
}
.zp-loading-image-ios{
width: 20px;
height: 20px;
}
.zp-loading-image-android{
width: 32rpx;
height: 32rpx;
}
@keyframes loading-flower {
0% {
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
}
to {
-webkit-transform: rotate(1turn);
transform: rotate(1turn);
}
}

View File

@@ -0,0 +1,32 @@
// z-paging
// github地址:https://github.com/SmileZXLee/uni-z-paging
// dcloud地址:https://ext.dcloud.net.cn/plugin?id=3935
// 反馈QQ群790460711
// z-paging配置文件
let config = null;
let getedStorage = false;
const storageKey = 'Z-PAGING-CONFIG-STORAGE-KEY'
function setConfig(value) {
try {
uni.setStorageSync(storageKey, value);
} catch {}
}
function getConfig() {
try {
if (getedStorage) {
return config;
}
config = uni.getStorageSync(storageKey);
getedStorage = true;
} catch {
return null;
}
}
module.exports = {
setConfig,
getConfig
};

View File

@@ -0,0 +1,150 @@
// z-paging
// github地址:https://github.com/SmileZXLee/uni-z-paging
// dcloud地址:https://ext.dcloud.net.cn/plugin?id=3935
// 反馈QQ群790460711
// z-paging国际化(支持中文、中文繁体和英文)
const i18nUpdateKey = 'z-paging-i18n-update';
const refresherDefaultText = {
'en': 'Pull down to refresh',
'zh-cn': '继续下拉刷新',
'zh-hant-cn': '繼續下拉重繪',
}
const refresherPullingText = {
'en': 'Release to refresh',
'zh-cn': '松开立即刷新',
'zh-hant-cn': '鬆開立即重繪',
}
const refresherRefreshingText = {
'en': 'Refreshing...',
'zh-cn': '正在刷新...',
'zh-hant-cn': '正在重繪...',
}
const loadingMoreDefaultText = {
'en': 'Click to load more',
'zh-cn': '点击加载更多',
'zh-hant-cn': '點擊加載更多',
}
const loadingMoreLoadingText = {
'en': 'Loading...',
'zh-cn': '正在加载...',
'zh-hant-cn': '正在加載...',
}
const loadingMoreNoMoreText = {
'en': 'No more data',
'zh-cn': '没有更多了',
'zh-hant-cn': '沒有更多了',
}
const loadingMoreFailText = {
'en': 'Load failed,click to reload',
'zh-cn': '加载失败,点击重新加载',
'zh-hant-cn': '加載失敗,點擊重新加載',
}
const emptyViewText = {
'en': 'No data',
'zh-cn': '没有数据哦~',
'zh-hant-cn': '沒有數據哦~',
}
const emptyViewReloadText = {
'en': 'Reload',
'zh-cn': '重新加载',
'zh-hant-cn': '重新加載',
}
const emptyViewErrorText = {
'en': 'Sorry,load failed',
'zh-cn': '很抱歉,加载失败',
'zh-hant-cn': '很抱歉,加載失敗',
}
const refresherUpdateTimeText = {
'en': 'Last update: ',
'zh-cn': '最后更新:',
'zh-hant-cn': '最後更新:',
}
const refresherUpdateTimeNoneText = {
'en': 'None',
'zh-cn': '无',
'zh-hant-cn': '無',
}
const refresherUpdateTimeTodayText = {
'en': 'Today',
'zh-cn': '今天',
'zh-hant-cn': '今天',
}
const refresherUpdateTimeYesterdayText = {
'en': 'Yesterday',
'zh-cn': '昨天',
'zh-hant-cn': '昨天',
}
// 插件内部使用,请勿直接调用
function getPrivateLanguage(myLanguage, followSystemLanguage = true) {
let systemLanguage = '';
if (followSystemLanguage) {
systemLanguage = uni.getSystemInfoSync().language;
}
let language = myLanguage || uni.getStorageSync(i18nUpdateKey) || systemLanguage;
language = language.toLowerCase();
var 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';
}
// 获取当前语言,格式为: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];
}
function setLanguage(myLanguage) {
uni.setStorageSync(i18nUpdateKey, myLanguage);
uni.$emit(i18nUpdateKey, myLanguage);
}
module.exports = {
refresherDefaultText,
refresherPullingText,
refresherRefreshingText,
loadingMoreDefaultText,
loadingMoreLoadingText,
loadingMoreNoMoreText,
loadingMoreFailText,
emptyViewText,
emptyViewReloadText,
emptyViewErrorText,
getPrivateLanguage,
getLanguage,
getLanguageName,
setLanguage,
refresherUpdateTimeText,
refresherUpdateTimeNoneText,
refresherUpdateTimeTodayText,
refresherUpdateTimeYesterdayText
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,36 @@
// z-paging
// github地址:https://github.com/SmileZXLee/uni-z-paging
// dcloud地址:https://ext.dcloud.net.cn/plugin?id=3935
// 反馈QQ群790460711
// 使用页面滚动时引入此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;

View File

@@ -0,0 +1,25 @@
// z-paging
// github地址:https://github.com/SmileZXLee/uni-z-paging
// dcloud地址:https://ext.dcloud.net.cn/plugin?id=3935
// 反馈QQ群790460711
// 公用的静态图片资源
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 base64Empty = 'data:image/png;base64,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'
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==';
module.exports = {
base64Arrow,
base64ArrowWhite,
base64Flower,
base64FlowerWhite,
base64Empty,
base64Error,
base64BackToTop
}

View File

@@ -0,0 +1,179 @@
// z-paging
// github地址:https://github.com/SmileZXLee/uni-z-paging
// dcloud地址:https://ext.dcloud.net.cn/plugin?id=3935
// 反馈QQ群790460711
// z-paging工具类
import zI18n from './z-paging-i18n'
const storageKey = 'Z-PAGING-REFRESHER-TIME-STORAGE-KEY'
//判断两个数组是否相等
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 getCommonTouch(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 {}
}
//获取下拉刷新时间
function getRefesrherTime() {
try {
const datas = uni.getStorageSync(storageKey);
return datas;
} catch {
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['refresherUpdateTimeNoneText'][zI18n.getLanguage()];
if (time) {
timeText = _timeFormat(time);
}
return `${zI18n['refresherUpdateTimeText'][zI18n.getLanguage()]}${timeText}`;
}
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['refresherUpdateTimeTodayText'][zI18n.getLanguage()];
} else if (disTime === -86400000) {
dayStr = zI18n['refresherUpdateTimeYesterdayText'][zI18n.getLanguage()];
} else {
dayStr = _dateDayFormat(date, date.getFullYear() !== currentDate.getFullYear());
}
return `${dayStr} ${timeStr}`;
}
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)}`;
}
}
function _dateTimeFormat(date) {
const hour = date.getHours();
const minute = date.getMinutes();
return `${_fullZeroToTwo(hour)}:${_fullZeroToTwo(minute)}`;
}
function _fullZeroToTwo(str) {
str = str.toString();
if (str.length === 1) {
return '0' + str;
}
return str;
}
module.exports = {
setRefesrherTime,
getRefesrherFormatTimeByKey,
arrayIsEqual,
getCommonTouch,
getTouchFromZPaging,
getParent,
consoleErr,
consoleWarn
};

View File

@@ -0,0 +1,205 @@
// z-paging
// github地址:https://github.com/SmileZXLee/uni-z-paging
// dcloud地址:https://ext.dcloud.net.cn/plugin?id=3935
// 反馈QQ群790460711
//微信小程序、QQ小程序、app-vue、h5上使用wxs实现自定义下拉刷新降低逻辑层与视图层的通信折损提升性能
function propObserver(newValue, oldValue, ownerInstance, instance) {
var state = ownerInstance.getState();
state.currentInstance = instance;
var dataset = instance.getDataset();
var loading = dataset.loading == true;
if (newValue.indexOf('end') != -1) {
_setTransform('translateY(0px)', instance)
state.moveDistance = 0;
} else if (newValue.indexOf('begin') != -1) {
var refresherThreshold = instance.getDataset().refresherthreshold
_setTransformValue(refresherThreshold, instance, state);
}
}
function touchstart(e, ownerInstance) {
var instance = ownerInstance.getState().currentInstance;
var state = instance.getState();
if (_getRefresherTouchDisabled(e, instance)) {
return;
}
var touch = _getCommonTouch(e);
state.startY = touch.touchY;
state.lastRefresherTouchmove = touch;
ownerInstance.callMethod('_handleRefresherTouchstart', touch);
}
function touchmove(e, ownerInstance) {
var touch = _getCommonTouch(e);
var instance = ownerInstance.getState().currentInstance;
var dataset = instance.getDataset();
var refresherThreshold = dataset.refresherthreshold;
var isTouchmoving = _getIsTrue(instance.getDataset().istouchmoving);
var state = instance.getState();
if (_getRefresherTouchDisabled(e, instance)) {
return;
}
if (!_getAngleIsInRange(e, touch, state, dataset)) {
return;
}
var moveDistance = _getMoveDistance(e, instance);
if (moveDistance < 0) {
return;
}
if (e.preventDefault) {
e.preventDefault();
}
_setTransformValue(moveDistance, instance, state);
var oldRefresherStatus = state.refresherStatus;
if (moveDistance >= refresherThreshold) {
state.refresherStatus = 1;
} else {
state.refresherStatus = 0;
}
if (oldRefresherStatus == undefined || oldRefresherStatus != state.refresherStatus || !isTouchmoving) {
ownerInstance.callMethod('_handleRefresherTouchmove', moveDistance, touch);
}
return false;
}
function touchend(e, ownerInstance) {
var touch = _getCommonTouch(e);
var instance = ownerInstance.getState().currentInstance;
var dataset = instance.getDataset();
var state = instance.getState();
if (_getRefresherTouchDisabled(e, instance)) {
return;
}
state.refresherReachMaxAngle = true;
var isTouchmoving = _getIsTrue(instance.getDataset().istouchmoving);
if (!isTouchmoving) {
return;
}
var oldMoveDistance = state.moveDistance;
var refresherThreshold = instance.getDataset().refresherthreshold
var moveDistance = _getMoveDistance(e, instance);
ownerInstance.callMethod('_handleRefresherTouchend', moveDistance);
if (oldMoveDistance < refresherThreshold) {
return;
}
if (moveDistance >= refresherThreshold) {
moveDistance = refresherThreshold;
}
_setTransformValue(moveDistance, instance, state)
}
function _setTransformValue(value, instance, state) {
value = value || 0;
state.moveDistance = value;
_setTransform('translateY(' + value + 'px)', instance);
}
function _setTransform(transform, instance) {
instance.requestAnimationFrame(function() {
instance.setStyle({
transform: transform,
'-webkit-transform': transform
})
})
}
function _getMoveDistance(e, instance) {
var state = instance.getState()
var refresherThreshold = instance.getDataset().refresherthreshold
var touch = _getCommonTouch(e);
var moveDistance = touch.touchY - state.startY;
moveDistance = _getFinalRefresherMoveDistance(moveDistance, refresherThreshold);
return moveDistance;
}
function _getCommonTouch(e) {
var 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
};
}
function _getFinalRefresherMoveDistance(moveDistance, refresherThreshold) {
refresherThreshold = parseFloat(refresherThreshold);
moveDistance = moveDistance * 0.7;
if (moveDistance >= refresherThreshold) {
moveDistance = refresherThreshold + (moveDistance - refresherThreshold) * 0.3;
}
return moveDistance;
}
function _getRefresherTouchDisabled(e, instance) {
var dataset = instance.getDataset();
var loading = _getIsTrue(dataset.loading);
var useChatRecordMode = _getIsTrue(dataset.usechatrecordmode);
var refresherEnabled = _getIsTrue(dataset.refresherenabled);
var useCustomRefresher = _getIsTrue(dataset.usecustomrefresher);
var usePageScroll = _getIsTrue(dataset.usepagescroll);
var pageScrollTop = parseFloat(dataset.pagescrolltop);
var wxsIsScrollTopInTopRange = _getIsTrue(dataset.wxsisscrolltopintoprange);
var scrollTop = parseFloat(dataset.scrolltop);
var res = loading || useChatRecordMode || !refresherEnabled || !useCustomRefresher || (
usePageScroll && useCustomRefresher && pageScrollTop > 10) || (!(
usePageScroll && useCustomRefresher) && !wxsIsScrollTopInTopRange);
return res;
}
function _getAngleIsInRange(e, touch, state, dataset) {
var refresherMaxAngle = dataset.refreshermaxangle;
var refresherAecc = _getIsTrue(dataset.refresheraecc);
var lastRefresherTouchmove = state.lastRefresherTouchmove;
var moveDistance = state.moveDistance;
var refresherReachMaxAngle = state.refresherReachMaxAngle;
if (!lastRefresherTouchmove) {
return true;
}
if (refresherMaxAngle >= 0 && refresherMaxAngle <= 90 && lastRefresherTouchmove) {
if (!refresherAecc && refresherReachMaxAngle != null && !refresherReachMaxAngle) {
return false;
}
var x = Math.abs(touch.touchX - lastRefresherTouchmove.touchX);
var y = Math.abs(touch.touchY - lastRefresherTouchmove.touchY);
var z = Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2));
if (x && y) {
var angle = Math.asin(y / z) / Math.PI * 180;
if (angle < refresherMaxAngle) {
state.lastRefresherTouchmove = touch;
state.refresherReachMaxAngle = false;
return false;
}
}
}
state.lastRefresherTouchmove = touch;
return true;
}
function _getIsTrue(value) {
value = (typeof(value) === 'string' ? JSON.parse(value) : value) || false;
return value == true || value == 'true';
}
module.exports = {
touchstart: touchstart,
touchmove: touchmove,
touchend: touchend,
propObserver: propObserver
}

View File

@@ -0,0 +1,58 @@
// z-paging
// github地址:https://github.com/SmileZXLee/uni-z-paging
// dcloud地址:https://ext.dcloud.net.cn/plugin?id=3935
// 反馈QQ群790460711
// 使用renderjs在app-vue和h5中对touchmove事件冒泡进行处理
import zUtils from '../js/z-paging-utils'
var data = {
renderScrollTop: 0,
renderUsePageScroll: false,
renderIsIos: uni.getSystemInfoSync().platform === 'ios',
startY: 0,
isTouchFromZPaging: false
}
export default {
mounted() {
this._handleTouch();
},
methods: {
//接收逻辑层发送的数据
renderPropScrollTopChange(newVal, oldVal, ownerVm, vm) {
data.renderScrollTop = newVal;
},
renderPropUsePageScrollChange(newVal, oldVal, ownerVm, vm) {
if(newVal !== -1){
data.renderUsePageScroll = newVal;
}
},
//拦截处理touch事件
_handleTouch() {
if (window && !window.$zPagingRenderJsInited) {
window.$zPagingRenderJsInited = true;
window.addEventListener('touchstart', this._handleTouchstart, {
passive: true
})
window.addEventListener('touchmove', this._handleTouchmove, {
passive: false
})
}
},
_handleTouchstart(e) {
const touch = zUtils.getCommonTouch(e);
data.startY = touch.touchY;
data.isTouchFromZPaging = zUtils.getTouchFromZPaging(e.target);
},
_handleTouchmove(e) {
const touch = zUtils.getCommonTouch(e);
var moveY = touch.touchY - data.startY;
if ((data.isTouchFromZPaging && data.renderScrollTop < 1 && moveY > 0) || (data.isTouchFromZPaging && data.renderIsIos && !data.renderUsePageScroll && moveY < 0)) {
if (e.cancelable && !e.defaultPrevented) {
e.preventDefault();
}
}
},
}
};

View File

@@ -0,0 +1,346 @@
// z-paging
// github地址:https://github.com/SmileZXLee/uni-z-paging
// dcloud地址:https://ext.dcloud.net.cn/plugin?id=3935
// 反馈QQ群790460711
// 微信小程序、QQ小程序、app-vue、h5上使用wxs实现自定义下拉刷新降低逻辑层与视图层的通信折损提升性能
var currentMoveDistance = 0;
function propObserver(newValue, oldValue, ownerInstance, instance) {
var state = ownerInstance.getState();
state.currentInstance = instance;
var dataset = instance.getDataset();
var loading = dataset.loading == true;
if (newValue.indexOf('end') != -1) {
_setTransform('translateY(0px)', instance)
state.moveDistance = 0;
state.oldMoveDistance = 0;
currentMoveDistance = 0;
} else if (newValue.indexOf('begin') != -1) {
var refresherThreshold = instance.getDataset().refresherthreshold
_setTransformValue(refresherThreshold, instance, state);
}
}
function touchstart(e, ownerInstance) {
var instance = ownerInstance.getState().currentInstance;
var state = instance.getState();
var dataset = instance.getDataset();
var isTouchEnded = state.isTouchEnded;
if (_getRefresherTouchDisabled(e, instance, 0)) {
return;
}
state.oldMoveDistance = 0;
var touch = _getCommonTouch(e);
var loading = _getIsTrue(dataset.loading);
state.startY = touch.touchY;
state.lastRefresherTouchmove = touch;
if (!loading && isTouchEnded) {
state.isTouchmoving = false;
}
state.isTouchEnded = false;
ownerInstance.callMethod('_handleRefresherTouchstart', touch);
}
function touchmove(e, ownerInstance) {
var touch = _getCommonTouch(e);
var instance = ownerInstance.getState().currentInstance;
var dataset = instance.getDataset();
var refresherThreshold = dataset.refresherthreshold;
var state = instance.getState();
if (_getRefresherTouchDisabled(e, instance, 1)) {
_handleTouchMovePullingDown(state, ownerInstance, false);
return true;
}
if (!_getAngleIsInRange(e, touch, state, dataset)) {
_handleTouchMovePullingDown(state, ownerInstance, false);
return true;
}
var moveDistanceObj = _getMoveDistance(e, instance);
var moveDistance = moveDistanceObj.currentMoveDistance;
var prevent = moveDistanceObj.isDown;
if (moveDistance < 0) {
_setTransformValue(0, instance, state);
_handleTouchMovePullingDown(state, ownerInstance, false);
return true;
}
if (prevent && !state.disabledBounce) {
ownerInstance.callMethod('_handleScrollViewDisableBounce', {
bounce: false
});
state.disabledBounce = true;
_handleTouchMovePullingDown(state, ownerInstance, prevent);
return !prevent;
}
_setTransformValue(moveDistance, instance, state);
var oldRefresherStatus = state.refresherStatus;
var dataset = instance.getDataset();
var oldIsTouchmoving = _getIsTrue(dataset.oldistouchmoving);
var isTouchmoving = state.isTouchmoving;
if (moveDistance >= refresherThreshold) {
state.refresherStatus = 1;
} else {
state.refresherStatus = 0;
}
if (!isTouchmoving) {
state.isTouchmoving = true;
isTouchmoving = true;
}
if (state.isTouchEnded) {
state.isTouchEnded = false;
}
if (oldRefresherStatus == undefined || oldRefresherStatus != state.refresherStatus || oldIsTouchmoving !=
isTouchmoving) {
ownerInstance.callMethod('_handleRefresherTouchmove', moveDistance, touch);
}
_handleTouchMovePullingDown(state, ownerInstance, prevent);
return !prevent;
}
function touchend(e, ownerInstance) {
var touch = _getCommonTouch(e);
var instance = ownerInstance.getState().currentInstance;
var dataset = instance.getDataset();
var state = instance.getState();
if (_getRefresherTouchDisabled(e, instance, 2)) {
return;
}
state.refresherReachMaxAngle = true;
state.hitReachMaxAngleCount = 0;
state.disabledBounce = false;
state.fixedIsTopHitCount = 0;
//ownerInstance.callMethod('_handleScrollViewDisableBounce', {bounce:true});
var isTouchmoving = state.isTouchmoving;
if (!isTouchmoving) {
return;
}
var oldRefresherStatus = state.refresherStatus;
var oldMoveDistance = state.moveDistance;
var refresherThreshold = instance.getDataset().refresherthreshold
var moveDistance = _getMoveDistance(e, instance).currentMoveDistance;
if (!(moveDistance >= refresherThreshold && oldRefresherStatus === 1)) {
state.isTouchmoving = false;
}
ownerInstance.callMethod('_handleRefresherTouchend', moveDistance);
state.isTouchEnded = true;
if (oldMoveDistance < refresherThreshold) {
return;
}
var animate = false;
if (moveDistance >= refresherThreshold) {
moveDistance = refresherThreshold;
var isIos13 = _getIsTrue(dataset.isios13);
if (isIos13) {
animate = true;
}
}
_setTransformValue(moveDistance, instance, state, animate);
}
// #ifdef H5
function isPC() {
var userAgentInfo = navigator.userAgent;
var Agents = ["Android", "iPhone", "SymbianOS", "Windows Phone", "iPad", "iPod"];
var flag = true;
for (var v = 0; v < Agents.length - 1; v++) {
if (userAgentInfo.indexOf(Agents[v]) > 0) {
flag = false;
break;
}
}
return flag;
}
var movable = false;
function mousedown(e, ins) {
if (!isPC()) return;
touchstart(e, ins);
movable = true;
}
function mousemove(e, ins) {
if (!isPC()) return;
if (!movable) return;
touchmove(e, ins);
}
function mouseup(e, ins) {
if (!isPC()) return;
touchend(e, ins);
movable = false;
}
function mouseleave(e, ins) {
if (!isPC()) return;
movable = false;
}
// #endif
function _setTransformValue(value, instance, state, animate = false) {
value = value || 0;
if (state.moveDistance == value) {
return;
}
state.moveDistance = value;
_setTransform('translateY(' + value + 'px)', instance, animate);
}
function _setTransform(transform, instance, animate = false) {
if (transform == 'translateY(0px)') {
transform = 'none';
}
instance.requestAnimationFrame(function() {
if (animate) {
instance.setStyle({
'transform': transform,
'transition': 'transform .1s linear',
})
} else {
instance.setStyle({
'transform': transform
})
}
})
}
function _getMoveDistance(e, instance) {
var state = instance.getState();
var refresherThreshold = instance.getDataset().refresherthreshold;
var refresherOutRate = instance.getDataset().refresheroutrate;
refresherThreshold = parseFloat(refresherThreshold);
refresherOutRate = parseFloat(refresherOutRate);
var touch = _getCommonTouch(e);
var moveDistance = touch.touchY - state.startY;
var oldMoveDistance = state.oldMoveDistance || 0;
state.oldMoveDistance = moveDistance;
var diffDis = moveDistance - oldMoveDistance;
if (diffDis > 0) {
diffDis = diffDis * 0.85;
if (currentMoveDistance > refresherThreshold) {
diffDis = diffDis * (1 - refresherOutRate);
}
}
currentMoveDistance += diffDis;
if (currentMoveDistance < 0) {
currentMoveDistance = 0;
}
return {
currentMoveDistance: currentMoveDistance,
isDown: diffDis > 0
};
}
function _getCommonTouch(e) {
var 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 {
touch = e;
}
return {
touchX: touch.clientX,
touchY: touch.clientY
};
}
function _getRefresherTouchDisabled(e, instance, processTag) {
var dataset = instance.getDataset();
var state = instance.getState();
var loading = _getIsTrue(dataset.loading);
var useChatRecordMode = _getIsTrue(dataset.usechatrecordmode);
var refresherEnabled = _getIsTrue(dataset.refresherenabled);
var useCustomRefresher = _getIsTrue(dataset.usecustomrefresher);
var usePageScroll = _getIsTrue(dataset.usepagescroll);
var pageScrollTop = parseFloat(dataset.pagescrolltop);
var scrollTop = parseFloat(dataset.scrolltop);
var finalScrollTop = usePageScroll ? pageScrollTop : scrollTop;
var fixedIsTop = false;
var isIos = _getIsTrue(dataset.isios);
if (!isIos && finalScrollTop == (state.startScrollTop || 0) && finalScrollTop <= 105) {
fixedIsTop = true;
}
var fixedIsTopHitCount = state.fixedIsTopHitCount || 0;
if (fixedIsTop) {
fixedIsTopHitCount++;
if (fixedIsTopHitCount <= 3) {
fixedIsTop = false;
}
state.fixedIsTopHitCount = fixedIsTopHitCount;
} else {
state.fixedIsTopHitCount = 0;
}
if (!isIos && processTag === 0) {
state.startScrollTop = finalScrollTop || 0;
}
if (!isIos && processTag === 2) {
fixedIsTop = true;
}
var res = loading || useChatRecordMode || !refresherEnabled || !useCustomRefresher || ((
usePageScroll && useCustomRefresher && pageScrollTop > 5) && !fixedIsTop) || ((
!usePageScroll && useCustomRefresher && scrollTop > 5) && !fixedIsTop);
return res;
}
function _getAngleIsInRange(e, touch, state, dataset) {
var refresherMaxAngle = dataset.refreshermaxangle;
var refresherAecc = _getIsTrue(dataset.refresheraecc);
var lastRefresherTouchmove = state.lastRefresherTouchmove;
var refresherReachMaxAngle = state.refresherReachMaxAngle;
var moveDistance = state.oldMoveDistance;
if (!lastRefresherTouchmove) {
return true;
}
if (refresherMaxAngle >= 0 && refresherMaxAngle <= 90 && lastRefresherTouchmove) {
if ((!moveDistance || moveDistance < 1) && !refresherAecc && refresherReachMaxAngle != null && !
refresherReachMaxAngle) {
return false;
}
var x = Math.abs(touch.touchX - lastRefresherTouchmove.touchX);
var y = Math.abs(touch.touchY - lastRefresherTouchmove.touchY);
var z = Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2));
if ((x || y) && x > 1) {
var angle = Math.asin(y / z) / Math.PI * 180;
if (angle < refresherMaxAngle) {
var hitReachMaxAngleCount = state.hitReachMaxAngleCount || 0;
state.hitReachMaxAngleCount = ++hitReachMaxAngleCount;
if (state.hitReachMaxAngleCount > 2) {
state.lastRefresherTouchmove = touch;
state.refresherReachMaxAngle = false;
}
return false;
}
}
}
state.lastRefresherTouchmove = touch;
return true;
}
function _handleTouchMovePullingDown(state, instance, onPullingDown) {
var oldOnPullingDown = state.onPullingDown || false;
if (oldOnPullingDown != onPullingDown) {
instance.callMethod('_handleWxsOnPullingDown', onPullingDown);
}
state.onPullingDown = onPullingDown;
}
function _getIsTrue(value) {
value = (typeof(value) === 'string' ? JSON.parse(value) : value) || false;
return value == true || value == 'true';
}
module.exports = {
touchstart: touchstart,
touchmove: touchmove,
touchend: touchend,
mousedown: mousedown,
mousemove: mousemove,
mouseup: mouseup,
mouseleave: mouseleave,
propObserver: propObserver
}

View File

@@ -0,0 +1,156 @@
<!-- z-paging -->
<!-- github地址:https://github.com/SmileZXLee/uni-z-paging -->
<!-- dcloud地址:https://ext.dcloud.net.cn/plugin?id=3935 -->
<!-- 反馈QQ群790460711 -->
<!-- 上拉加载更多view -->
<template>
<view class="zp-load-more-container" :style="[config.loadingMoreCustomStyle]">
<text
:class="config.defaultThemeStyle==='white'?'zp-loading-more-line zp-loading-more-line-white':'zp-loading-more-line zp-loading-more-line-black'"
:style="[config.loadingMoreNoMoreLineCustomStyle]"
v-if="config.showLoadingMoreNoMoreLine&&config.loadingStatus===2"></text>
<!-- #ifndef APP-NVUE -->
<image v-if="config.loadingStatus===1&&config.loadingMoreLoadingIconCustomImage.length"
:src="config.loadingMoreLoadingIconCustomImage" class="zp-loading-more-line-loading-custom-image">
</image>
<image
v-if="config.loadingStatus===1&&config.loadingMoreLoadingIconType==='flower'&&!config.loadingMoreLoadingIconCustomImage.length"
class="zp-loading-more-line-loading-image" :style="[config.loadingMoreLoadingIconCustomStyle]"
:src="base64Flower">
</image>
<!-- #endif -->
<!-- #ifdef APP-NVUE -->
<view>
<loading-indicator v-if="config.loadingStatus===1" :animating="true"
class="zp-loading-more-line-loading-image">
</loading-indicator>
</view>
<!-- #endif -->
<text
v-if="config.loadingStatus===1&&config.loadingMoreLoadingIconType==='circle'&&!config.loadingMoreLoadingIconCustomImage.length"
:class="config.defaultThemeStyle==='white'?'zp-loading-more-line-loading-view zp-loading-more-line-loading-view-white':'zp-loading-more-line-loading-view zp-loading-more-line-loading-view-black'"
:style="[config.loadingMoreLoadingIconCustomStyle]"></text>
<text
:class="config.defaultThemeStyle==='white'?'zp-loading-more-text zp-loading-more-text-white':'zp-loading-more-text zp-loading-more-text-black'">{{ownLoadingMoreText}}</text>
<text
:class="config.defaultThemeStyle==='white'?'zp-loading-more-line zp-loading-more-line-white':'zp-loading-more-line zp-loading-more-line-black'"
:style="[config.loadingMoreNoMoreLineCustomStyle]"
v-if="config.showLoadingMoreNoMoreLine&&config.loadingStatus===2"></text>
</view>
</template>
<script>
import zStatic from './z-paging-static'
export default {
name: 'z-paging-refresh',
data() {
return {
base64Arrow: zStatic.base64Arrow,
base64Flower: zStatic.base64Flower,
loadingStatusTextMap: {
0: this.config.loadingMoreDefaultText,
1: this.config.loadingMoreLoadingText,
2: this.config.loadingMoreNoMoreText,
3: this.config.loadingMoreFailText,
},
};
},
props: ['config'],
computed: {
ownLoadingMoreText() {
if (this.config.loadingMoreText.length) {
return this.config.loadingMoreText;
}
return this.loadingStatusTextMap[this.config.loadingStatus];
},
}
}
</script>
<style scoped>
@import "./z-paging-static.css";
.zp-load-more-container {
height: 80rpx;
font-size: 26rpx;
/* #ifndef APP-NVUE */
clear: both;
display: flex;
/* #endif */
flex-direction: row;
align-items: center;
justify-content: center;
}
.zp-loading-more-line-loading-custom-image {
color: #a4a4a4;
margin-right: 8rpx;
width: 28rpx;
height: 28rpx;
/* #ifndef APP-NVUE */
animation: loading-circle 1s linear infinite;
/* #endif */
}
.zp-loading-more-line-loading-view {
margin-right: 8rpx;
width: 22rpx;
height: 23rpx;
border: 3rpx solid #dddddd;
border-radius: 50%;
/* #ifndef APP-NVUE */
animation: loading-circle 1s linear infinite;
/* #endif */
}
.zp-loading-more-line-loading-view-black {
border-color: #c8c8c8;
border-top-color: #444444;
}
.zp-loading-more-line-loading-view-white {
border-color: #aaaaaa;
border-top-color: #ffffff;
}
.zp-loading-more-text {
/* #ifdef APP-NVUE */
font-size: 30rpx;
margin: 0rpx 10rpx;
/* #endif */
}
.zp-loading-more-text-black {
color: #a4a4a4;
}
.zp-loading-more-text-white {
color: #efefef;
}
.zp-loading-more-line {
height: 1px;
width: 100rpx;
margin: 0rpx 10rpx;
}
.zp-loading-more-line-black {
background-color: #eeeeee;
}
.zp-loading-more-line-white {
background-color: #cccccc;
}
@keyframes loading-circle {
0% {
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
}
100% {
-webkit-transform: rotate(360deg);
transform: rotate(360deg);
}
}
</style>

View File

@@ -0,0 +1,35 @@
// z-paging
// github地址:https://github.com/SmileZXLee/uni-z-paging
// dcloud地址:https://ext.dcloud.net.cn/plugin?id=3935
// 反馈QQ群790460711
// 使用页面滚动时引入此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);
},
onReachBottom() {
if(this.isPagingRefNotFound()){
return;
}
this.$refs.paging.doLoadMore();
},
methods: {
isPagingRefNotFound(){
return !this.$refs.paging || this.$refs.paging === undefined;
}
}
}
export default ZPagingMixin;

View File

@@ -0,0 +1,173 @@
<!-- z-paging -->
<!-- github地址:https://github.com/SmileZXLee/uni-z-paging -->
<!-- dcloud地址:https://ext.dcloud.net.cn/plugin?id=3935 -->
<!-- 反馈QQ群790460711 -->
<!-- 下拉刷新view -->
<template>
<view style="height: 100%;">
<view class="zp-custom-refresher-container" style="height: 100%;">
<view class="zp-custom-refresher-left">
<image v-if="refresherStatus!==2" :class="refresherLeftImageClass"
:style="[{'filter' :defaultThemeStyle==='white'?'brightness(10)':''}]" :src="base64Arrow">
</image>
<!-- #ifndef APP-NVUE -->
<image v-else class="zp-loading-more-line-loading-image zp-custom-refresher-left-image" :src="base64Flower">
</image>
<!-- #endif -->
<!-- #ifdef APP-NVUE -->
<view v-else>
<loading-indicator class="zp-custom-refresher-left-image" :animating="true"></loading-indicator>
</view>
<!-- #endif -->
</view>
<view
:class="defaultThemeStyle==='white'?'zp-custom-refresher-right zp-custom-refresher-right-white':'zp-custom-refresher-right zp-custom-refresher-right-black'">
<text class="zp-custom-refresher-right-text">{{refresherStatusTextMap[refresherStatus]}}
</text>
</view>
</view>
</view>
</template>
<script>
import zStatic from './z-paging-static'
export default {
name: 'z-paging-refresh',
data() {
return {
base64Arrow: zStatic.base64Arrow,
base64Flower: zStatic.base64Flower,
refresherStatusTextMap: {
0: this.refresherDefaultText,
1: this.refresherPullingText,
2: this.refresherRefreshingText
},
refresherLeftImageClass: 'zp-custom-refresher-left-image',
};
},
props: ['refresherStatus', 'defaultThemeStyle', 'refresherDefaultText', 'refresherPullingText',
'refresherPullingText', 'refresherRefreshingText'
],
watch: {
refresherStatus(newVal, oldVal) {
if (newVal === 0 && oldVal !== 0) {
this.refresherLeftImageClass = 'zp-custom-refresher-left-image zp-custom-refresher-arrow-down';
}
if (newVal !== 0 && oldVal === 0) {
this.refresherLeftImageClass = 'zp-custom-refresher-left-image zp-custom-refresher-arrow-top';
}
}
}
}
</script>
<style scoped>
@import "./z-paging-static.css";
.zp-custom-refresher-container {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-direction: row;
justify-content: center;
align-items: center;
}
.zp-custom-refresher-left {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-direction: row;
align-items: center;
}
.zp-custom-refresher-left-image {
width: 30rpx;
height: 30rpx;
transform: rotate(180deg);
margin-right: 8rpx;
/* #ifdef APP-NVUE */
width: 35rpx;
height: 35rpx;
transition-duration: .2s;
transition-property: transform;
color: #666666;
/* #endif */
}
.zp-custom-refresher-arrow-top {
/* #ifndef APP-NVUE */
animation: refresher-arrow-top 0.25s linear;
-webkitanimation: refresher-arrow-top 0.25s linear;
animation-fill-mode: forwards;
-webkit-animation-fill-mode: forwards;
/* #endif */
/* #ifdef APP-NVUE */
transform: rotate(0deg);
/* #endif */
}
.zp-custom-refresher-arrow-down {
/* #ifndef APP-NVUE */
animation: refresher-arrow-down 0.25s linear;
-webkit-animation: refresher-arrow-down 0.25s linear;
animation-fill-mode: forwards;
-webkit-animation-fill-mode: forwards;
/* #endif */
/* #ifdef APP-NVUE */
transform: rotate(180deg);
/* #endif */
}
.zp-custom-refresher-right {
font-size: 26rpx;
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-direction: row;
align-items: center;
justify-content: center;
}
.zp-custom-refresher-right-text {
/* #ifdef APP-NVUE */
font-size: 28rpx;
height: 40px;
line-height: 40px;
/* #endif */
color: #555555
}
.zp-custom-refresher-right-black {
color: #666666;
}
.zp-custom-refresher-right-white {
color: #efefef;
}
@keyframes refresher-arrow-top {
0% {
-webkit-transform: rotate(180deg);
transform: rotate(180deg);
}
100% {
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
}
}
@keyframes refresher-arrow-down {
0% {
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
}
100% {
-webkit-transform: rotate(180deg);
transform: rotate(180deg);
}
}
</style>

View File

@@ -0,0 +1,205 @@
// z-paging
// github地址:https://github.com/SmileZXLee/uni-z-paging
// dcloud地址:https://ext.dcloud.net.cn/plugin?id=3935
// 反馈QQ群790460711
//微信小程序、QQ小程序、app-vue、h5上使用wxs实现自定义下拉刷新降低逻辑层与视图层的通信折损提升性能
function propObserver(newValue, oldValue, ownerInstance, instance) {
var state = ownerInstance.getState();
state.currentInstance = instance;
var dataset = instance.getDataset();
var loading = dataset.loading == true;
if (newValue.indexOf('end') != -1) {
_setTransform('translateY(0px)', instance)
state.moveDistance = 0;
} else if (newValue.indexOf('begin') != -1) {
var refresherThreshold = instance.getDataset().refresherthreshold
_setTransformValue(refresherThreshold, instance, state);
}
}
function touchstart(e, ownerInstance) {
var instance = ownerInstance.getState().currentInstance;
var state = instance.getState();
if (_getRefresherTouchDisabled(e, instance)) {
return;
}
var touch = _getCommonTouch(e);
state.startY = touch.touchY;
state.lastRefresherTouchmove = touch;
ownerInstance.callMethod('_handleRefresherTouchstart', touch);
}
function touchmove(e, ownerInstance) {
var touch = _getCommonTouch(e);
var instance = ownerInstance.getState().currentInstance;
var dataset = instance.getDataset();
var refresherThreshold = dataset.refresherthreshold;
var isTouchmoving = _getIsTrue(instance.getDataset().istouchmoving);
var state = instance.getState();
if (_getRefresherTouchDisabled(e, instance)) {
return;
}
if (!_getAngleIsInRange(e, touch, state, dataset)) {
return;
}
var moveDistance = _getMoveDistance(e, instance);
if (moveDistance < 0) {
return;
}
if (e.preventDefault) {
e.preventDefault();
}
_setTransformValue(moveDistance, instance, state);
var oldRefresherStatus = state.refresherStatus;
if (moveDistance >= refresherThreshold) {
state.refresherStatus = 1;
} else {
state.refresherStatus = 0;
}
if (oldRefresherStatus == undefined || oldRefresherStatus != state.refresherStatus || !isTouchmoving) {
ownerInstance.callMethod('_handleRefresherTouchmove', moveDistance, touch);
}
return false;
}
function touchend(e, ownerInstance) {
var touch = _getCommonTouch(e);
var instance = ownerInstance.getState().currentInstance;
var dataset = instance.getDataset();
var state = instance.getState();
if (_getRefresherTouchDisabled(e, instance)) {
return;
}
state.refresherReachMaxAngle = true;
var isTouchmoving = _getIsTrue(instance.getDataset().istouchmoving);
if (!isTouchmoving) {
return;
}
var oldMoveDistance = state.moveDistance;
var refresherThreshold = instance.getDataset().refresherthreshold
var moveDistance = _getMoveDistance(e, instance);
ownerInstance.callMethod('_handleRefresherTouchend', moveDistance);
if (oldMoveDistance < refresherThreshold) {
return;
}
if (moveDistance >= refresherThreshold) {
moveDistance = refresherThreshold;
}
_setTransformValue(moveDistance, instance, state)
}
function _setTransformValue(value, instance, state) {
value = value || 0;
state.moveDistance = value;
_setTransform('translateY(' + value + 'px)', instance);
}
function _setTransform(transform, instance) {
instance.requestAnimationFrame(function() {
instance.setStyle({
transform: transform,
'-webkit-transform': transform
})
})
}
function _getMoveDistance(e, instance) {
var state = instance.getState()
var refresherThreshold = instance.getDataset().refresherthreshold
var touch = _getCommonTouch(e);
var moveDistance = touch.touchY - state.startY;
moveDistance = _getFinalRefresherMoveDistance(moveDistance, refresherThreshold);
return moveDistance;
}
function _getCommonTouch(e) {
var 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
};
}
function _getFinalRefresherMoveDistance(moveDistance, refresherThreshold) {
refresherThreshold = parseFloat(refresherThreshold);
moveDistance = moveDistance * 0.7;
if (moveDistance >= refresherThreshold) {
moveDistance = refresherThreshold + (moveDistance - refresherThreshold) * 0.3;
}
return moveDistance;
}
function _getRefresherTouchDisabled(e, instance) {
var dataset = instance.getDataset();
var loading = _getIsTrue(dataset.loading);
var useChatRecordMode = _getIsTrue(dataset.usechatrecordmode);
var refresherEnabled = _getIsTrue(dataset.refresherenabled);
var useCustomRefresher = _getIsTrue(dataset.usecustomrefresher);
var usePageScroll = _getIsTrue(dataset.usepagescroll);
var pageScrollTop = parseFloat(dataset.pagescrolltop);
var wxsIsScrollTopInTopRange = _getIsTrue(dataset.wxsisscrolltopintoprange);
var scrollTop = parseFloat(dataset.scrolltop);
var res = loading || useChatRecordMode || !refresherEnabled || !useCustomRefresher || (
usePageScroll && useCustomRefresher && pageScrollTop > 10) || (!(
usePageScroll && useCustomRefresher) && !wxsIsScrollTopInTopRange);
return res;
}
function _getAngleIsInRange(e, touch, state, dataset) {
var refresherMaxAngle = dataset.refreshermaxangle;
var refresherAecc = _getIsTrue(dataset.refresheraecc);
var lastRefresherTouchmove = state.lastRefresherTouchmove;
var moveDistance = state.moveDistance;
var refresherReachMaxAngle = state.refresherReachMaxAngle;
if (!lastRefresherTouchmove) {
return true;
}
if (refresherMaxAngle >= 0 && refresherMaxAngle <= 90 && lastRefresherTouchmove) {
if (!refresherAecc && refresherReachMaxAngle != null && !refresherReachMaxAngle) {
return false;
}
var x = Math.abs(touch.touchX - lastRefresherTouchmove.touchX);
var y = Math.abs(touch.touchY - lastRefresherTouchmove.touchY);
var z = Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2));
if (x && y) {
var angle = Math.asin(y / z) / Math.PI * 180;
if (angle < refresherMaxAngle) {
state.lastRefresherTouchmove = touch;
state.refresherReachMaxAngle = false;
return false;
}
}
}
state.lastRefresherTouchmove = touch;
return true;
}
function _getIsTrue(value) {
value = (typeof(value) === 'string' ? JSON.parse(value) : value) || false;
return value == true || value == 'true';
}
module.exports = {
touchstart: touchstart,
touchmove: touchmove,
touchend: touchend,
propObserver: propObserver
}

View File

@@ -0,0 +1,28 @@
/* z-paging
github地址:https://github.com/SmileZXLee/uni-z-paging
dcloud地址:https://ext.dcloud.net.cn/plugin?id=3935
反馈QQ群790460711
公用的静态css资源 */
.zp-loading-more-line-loading-image {
margin-right: 8rpx;
width: 28rpx;
height: 28rpx;
/* #ifndef APP-NVUE */
animation: loading-flower 1s steps(12) infinite;
/* #endif */
color: #666666;
}
@keyframes loading-flower {
0% {
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
}
to {
-webkit-transform: rotate(1turn);
transform: rotate(1turn);
}
}

View File

@@ -0,0 +1,18 @@
// z-paging
// github地址:https://github.com/SmileZXLee/uni-z-paging
// dcloud地址:https://ext.dcloud.net.cn/plugin?id=3935
// 反馈QQ群790460711
// 公用的静态图片资源
const base64Arrow =
'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGQAAABkBAMAAACCzIhnAAAAD1BMVEVHcExRUVFMTExRUVFRUVE9CdWsAAAABHRSTlMAjjrY9ZnUjwAAAQFJREFUWMPt2MsNgzAMgGEEE1B1gKJmAIRYoCH7z9RCXrabh33iYktcIv35EEg5ZBh07pvxJU6MFSPOSRnjnBUjUsaciRUjMsb4xIoRCWNiYsUInzE5sWKEyxiYWDbyefqHx1zIeiYTk7mQYziTYecxHvEJjwmIT3hMQELCYSISEg4TkZj0mYTEpM8kJCU9JiMp6TEZyUmbAUhO2gxAQNJiIAKSFgMRmNQZhMCkziAEJTUGIyipMRjBSZkhCE7KDEFIUmTeGCHJxWz0zXaE0GTCG8ZFtEaS347r/1fe11YyHYVfubxayfjoHmc0YYwmmmiiiSaaaKLJ7ckyz5ve+dw3Xw2emdwm9xSbAAAAAElFTkSuQmCC';
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 base64Empty = 'data:image/png;base64,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'
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==';
module.exports = {
base64Arrow: base64Arrow,
base64Flower: base64Flower,
base64Empty: base64Empty,
base64BackToTop: base64BackToTop
}

View File

@@ -0,0 +1,462 @@
<!-- _
____ _ __ __ _ __ _(_)_ __ __ _
|_ /____| '_ \ / _` |/ _` | | '_ \ / _` |
/ /_____| |_) | (_| | (_| | | | | | (_| |
/___| | .__/ \__,_|\__, |_|_| |_|\__, |
|_| |___/ |___/
V2.0.1
by ZXLee 2021-08-17
-- >
<!-- API文档地址http://z-paging.com -->
<!-- github地址:https://github.com/SmileZXLee/uni-z-paging -->
<!-- dcloud地址:https://ext.dcloud.net.cn/plugin?id=3935 -->
<!-- 反馈QQ群790460711 -->
<template name="z-paging">
<!-- #ifndef APP-NVUE -->
<view :class="!usePageScroll&&fixed?'z-paging-content z-paging-content-fixed':'z-paging-content'"
:style="[finalPagingStyle]">
<!-- 顶部固定的slot -->
<slot v-if="!usePageScroll&&$slots.top" name="top"></slot>
<view class="zp-page-scroll-top" v-else-if="usePageScroll&&$slots.top" :style="[{'top':`${windowTop}px`,'z-index':topZIndex}]">
<slot name="top"></slot>
</view>
<view :class="{'zp-scroll-view-super':!usePageScroll}" :style="[finalScrollViewStyle]">
<scroll-view
:class="{'zp-scroll-view':true,'zp-scroll-view-absolute':!usePageScroll}"
:scroll-top="scrollTop"
:scroll-y="scrollable&&!usePageScroll&&scrollEnable" :enable-back-to-top="finalEnableBackToTop"
:show-scrollbar="showScrollbar" :scroll-with-animation="finalScrollWithAnimation"
:scroll-into-view="scrollIntoView" :lower-threshold="finalLowerThreshold" :upper-threshold="5"
:refresher-enabled="finalRefresherEnabled&&!useCustomRefresher" :refresher-threshold="finalRefresherThreshold"
:refresher-default-style="finalRefresherDefaultStyle" :refresher-background="refresherBackground"
:refresher-triggered="refresherTriggered" @scroll="_scroll" @scrolltolower="_onLoadingMore('toBottom')"
@scrolltoupper="_scrollToUpper" @refresherrestore="_onRestore" @refresherrefresh="_onRefresh"
>
<view class="zp-paging-touch-view"
<!-- #ifndef APP-VUE || MP-WEIXIN || MP-QQ || H5 -->
@touchstart="_refresherTouchstart" @touchmove="_refresherTouchmove" @touchend="_refresherTouchend" @touchcancel="_refresherTouchend"
<!-- #endif -->
<!-- #ifdef APP-VUE || MP-WEIXIN || MP-QQ || H5 -->
@touchstart="pagingWxs.touchstart" @touchmove="pagingWxs.touchmove" @touchend="pagingWxs.touchend" @touchcancel="pagingWxs.touchend"
@mousedown="pagingWxs.mousedown" @mousemove="pagingWxs.mousemove" @mouseup="pagingWxs.mouseup" @mouseleave="pagingWxs.mouseleave"
<!-- #endif -->
>
<view v-if="finalRefresherFixedBacHeight>0" class="zp-fixed-bac-view" :style="[{'background-color': refresherFixedBackground,'height': `${finalRefresherFixedBacHeight}px`}]"></view>
<view class="zp-paging-main" :style="[{'transform': finalRefresherTransform,'transition': refresherTransition}]"
<!-- #ifdef APP-VUE || MP-WEIXIN || MP-QQ || H5 -->
:change:prop="pagingWxs.propObserver" :prop="wxsPropType"
:data-refresherThreshold="finalRefresherThreshold" :data-isIos="isIos" :data-isIos13="isIos13"
:data-loading="loading" :data-useChatRecordMode="useChatRecordMode"
:data-refresherEnabled="refresherEnabled" :data-useCustomRefresher="useCustomRefresher" :data-pageScrollTop="wxsPageScrollTop"
:data-scrollTop="wxsScrollTop" :data-refresherMaxAngle="refresherMaxAngle"
:data-refresherAecc="refresherAngleEnableChangeContinued" :data-usePageScroll="usePageScroll"
:data-oldIsTouchmoving="isTouchmoving" :data-refresherOutRate="finalRefresherOutRate"
<!-- #endif -->
<!-- #ifdef APP-VUE || H5 -->
:change:renderPropScrollTop="pagingRenderjs.renderPropScrollTopChange" :renderPropScrollTop="renderPropScrollTop"
:change:renderPropUsePageScroll="pagingRenderjs.renderPropUsePageScrollChange" :renderPropUsePageScroll="renderPropUsePageScroll"
<!-- #endif -->
>
<view v-if="showRefresher" class="zp-custom-refresher-view"
:style="[{'margin-top': `-${finalRefresherThreshold}px`,'background-color': refresherBackground}]">
<view class="zp-custom-refresher-container" :style="[{'height': `${finalRefresherThreshold}px`,'background-color': refresherBackground}]">
<!-- 下拉刷新view -->
<view
class="zp-custom-refresher-slot-view">
<slot
<!-- #ifndef MP-QQ -->
:refresherStatus="refresherStatus"
<!-- #endif -->
name="refresher" />
</view>
<z-paging-refresh ref="refresh" v-if="!showCustomRefresher" :style="[{'height': `${finalRefresherThreshold}px`}]" :refresherStatus="refresherStatus"
:defaultThemeStyle="finalRefresherThemeStyle" :refresherDefaultText="finalRefresherDefaultText"
:refresherPullingText="finalRefresherPullingText" :refresherRefreshingText="finalRefresherRefreshingText"
:showRefresherUpdateTime="showRefresherUpdateTime" :refresherUpdateTimeKey="refresherUpdateTimeKey"></z-paging-refresh>
</view>
</view>
<view class="zp-paging-container">
<slot v-if="useChatRecordMode&&$slots.chatLoading&&loadingStatus!==2&&realTotalData.length"
name="chatLoading" />
<view v-else-if="useChatRecordMode&&loadingStatus!==2&&realTotalData.length"
class="zp-chat-record-loading-container">
<text v-if="loadingStatus!==1" @click="_scrollToUpper()"
:class="defaultThemeStyle==='white'?'zp-loading-more-text zp-loading-more-text-white':'zp-loading-more-text zp-loading-more-text-black'">{{chatRecordLoadingMoreText}}</text>
<image v-else :src="base64Flower" class="zp-chat-record-loading-custom-image">
</image>
</view>
<slot v-if="$slots.loading&&!firstPageLoaded&&(autoHideLoadingAfterFirstLoaded?!pagingLoaded:true)&&loading" name="loading" />
<!-- 主体内容 -->
<view class="zp-paging-container-content" :style="[finalPagingContentStyle]">
<slot />
</view>
<!-- 上拉加载更多view -->
<!-- #ifndef MP-ALIPAY -->
<slot v-if="_shouldShowLoading('loadingMoreDefault')" name="loadingMoreDefault" />
<slot v-else-if="_shouldShowLoading('loadingMoreLoading')" name="loadingMoreLoading" />
<slot v-else-if="_shouldShowLoading('loadingMoreNoMore')" name="loadingMoreNoMore" />
<slot v-else-if="_shouldShowLoading('loadingMoreFail')" name="loadingMoreFail" />
<z-paging-load-more @click.native="_onLoadingMore('click')"
v-else-if="_shouldShowLoading('loadingMoreCustom')" :zConfig="zPagingLoadMoreConfig">
</z-paging-load-more>
<!-- #endif -->
<!-- #ifdef MP-ALIPAY -->
<slot v-if="loadingStatus===0&&$slots.loadingMoreDefault&&showLoadingMore&&loadingMoreEnabled&&!useChatRecordMode"
name="loadingMoreDefault" />
<slot v-else-if="loadingStatus===1&&$slots.loadingMoreLoading&&showLoadingMore&&loadingMoreEnabled"
name="loadingMoreLoading" />
<slot v-else-if="loadingStatus===2&&$slots.loadingMoreNoMore&&showLoadingMore&&showLoadingMoreNoMoreView&&loadingMoreEnabled&&!useChatRecordMode"
name="loadingMoreNoMore" />
<slot v-else-if="loadingStatus===3&&$slots.loadingMoreFail&&showLoadingMore&&loadingMoreEnabled&&!useChatRecordMode"
name="loadingMoreFail" />
<z-paging-load-more @click.native="_onLoadingMore('click')" v-else-if="showLoadingMore&&showDefaultLoadingMoreText&&!(loadingStatus===2&&!showLoadingMoreNoMoreView)&&loadingMoreEnabled&&!useChatRecordMode" :zConfig="zPagingLoadMoreConfig">
</z-paging-load-more>
<!-- #endif -->
<!-- 空数据图 -->
<view class="zp-empty-view"
v-if="showEmpty">
<slot v-if="$slots.empty" name="empty" />
<z-paging-empty-view v-else :emptyViewImg="finalEmptyViewImg" :emptyViewText="finalEmptyViewText" :showEmptyViewReload="finalShowEmptyViewReload" :emptyViewReloadText="finalEmptyViewReloadText" :isLoadFailed="isLoadFailed" :emptyViewStyle="emptyViewStyle" :emptyViewTitleStyle="emptyViewTitleStyle" :emptyViewImgStyle="emptyViewImgStyle" :emptyViewReloadStyle="emptyViewReloadStyle" :emptyViewZIndex="emptyViewZIndex" @reload="_emptyViewReload">
</z-paging-empty-view>
</view>
</view>
</view>
</view>
</scroll-view>
</view>
<slot v-if="!usePageScroll&&$slots.bottom" name="bottom"></slot>
<view class="zp-page-scroll-bottom" v-else-if="usePageScroll&&$slots.bottom" :style="[{'bottom': `${windowBottom}px`}]">
<slot name="bottom"></slot>
</view>
<view v-if="showBackToTopClass" :class="backToTopClass" :style="[finalBackToTopStyle]" @click.stop="_backToTopClick">
<slot v-if="$slots.backToTop" name="backToTop" />
<image v-else class="zp-back-to-top-img" :src="backToTopImg.length?backToTopImg:base64BackToTop"></image>
</view>
</view>
<!-- #endif -->
<!-- #ifdef APP-NVUE -->
<view :is="finalNvueSuperListIs">
<view ref="zp-page-scroll-top" :is="nViewIs" class="zp-page-scroll-top" v-if="$slots.top" :style="[{'top':`${windowTop}px`,'z-index':topZIndex}]">
<slot name="top"></slot>
</view>
<view ref="n-list" id="z-paging-nlist" :style="[scrollViewStyle,useChatRecordMode ? {transform: nIsFirstPageAndNoMore?'rotate(0deg)':'rotate(180deg)'}:{}]" :is="finalNvueListIs" alwaysScrollableVertical="true"
:fixFreezing="nFixFreezing" :show-scrollbar="showScrollbar" :loadmoreoffset="finalLowerThreshold"
:scrollable="scrollable&&scrollEnable" :bounce="nvueBounce" :column-count="nWaterfallColumnCount" :column-width="nWaterfallColumnWidth"
:column-gap="nWaterfallColumnGap" :left-gap="nWaterfallLeftGap" :right-gap="nWaterfallRightGap"
@loadmore="_nOnLoadmore" @scroll="_nOnScroll">
<refresh class="zp-n-refresh" v-if="finalNvueListIs!=='view'&&refresherEnabled&&!nShowRefresherReveal&&!useChatRecordMode" :display="nRefresherLoading?'show':'hide'" @refresh="_nOnRrefresh"
@pullingdown="_nOnPullingdown">
<view ref="zp-n-refresh-container" class="zp-n-refresh-container">
<!-- 下拉刷新view -->
<slot v-if="zScopedSlots.refresher" :refresherStatus="refresherStatus" name="refresher" />
<z-paging-refresh ref="refresh" v-else :refresherStatus="refresherStatus" :defaultThemeStyle="finalRefresherThemeStyle"
:refresherDefaultText="finalRefresherDefaultText" :refresherPullingText="finalRefresherPullingText" :refresherRefreshingText="finalRefresherRefreshingText"
:showRefresherUpdateTime="showRefresherUpdateTime" :refresherUpdateTimeKey="refresherUpdateTimeKey"></z-paging-refresh>
</view>
</refresh>
<view ref="zp-n-list-top-tag" class="zp-n-list-top-tag" :is="nViewIs"></view>
<view v-if="nShowRefresherReveal" ref="zp-n-list-refresher-reveal" :style="[{transform:`translateY(-${nShowRefresherRevealHeight}px)`,height:'0px'}]" :is="nViewIs">
<slot v-if="zScopedSlots.refresher" :refresherStatus="refresherStatus" name="refresher" />
<z-paging-refresh ref="refresh" v-else :refresherStatus="refresherStatus" :defaultThemeStyle="finalRefresherThemeStyle"
:refresherDefaultText="finalRefresherDefaultText" :refresherPullingText="finalRefresherPullingText" :refresherRefreshingText="finalRefresherRefreshingText"
:showRefresherUpdateTime="showRefresherUpdateTime" :refresherUpdateTimeKey="refresherUpdateTimeKey"></z-paging-refresh>
</view>
<slot />
<view ref="zp-n-list-bottom-tag" class="zp-n-list-bottom-tag" is="header"></view>
<!-- 全屏 -->
<view style="flex: 1;" :style="[scrollViewStyle,useChatRecordMode ? {transform: nIsFirstPageAndNoMore?'rotate(0deg)':'rotate(180deg)'}:{}]" v-if="$slots.loading&&!firstPageLoaded&&(autoHideLoadingAfterFirstLoaded?!pagingLoaded:true)&&loading" :is="finalNvueListIs==='scroller'?'view':finalNvueListIs==='waterfall'?'header':'cell'">
<slot name="loading" />
</view>
<!-- 上拉加载更多view -->
<view :is="nViewIs">
<view v-if="useChatRecordMode">
<view v-if="loadingStatus!==2&&realTotalData.length">
<slot v-if="$slots.chatLoading"
name="chatLoading" />
<view v-else class="zp-chat-record-loading-container">
<text v-if="loadingStatus!==1" @click="_scrollToUpper()"
:class="defaultThemeStyle==='white'?'zp-loading-more-text zp-loading-more-text-white':'zp-loading-more-text zp-loading-more-text-black'">{{chatRecordLoadingMoreText}}</text>
<view>
<loading-indicator v-if="loadingStatus===1" :animating="true"
class="zp-loading-more-line-loading-image">
</loading-indicator>
</view>
</view>
</view>
</view>
<view :style="nLoadingMoreFixedHeight?{height:loadingMoreCustomStyle&&loadingMoreCustomStyle.height?loadingMoreCustomStyle.height:'80rpx'}:{}">
<slot v-if="_shouldShowLoading('loadingMoreDefault')" name="loadingMoreDefault" />
<slot v-else-if="_shouldShowLoading('loadingMoreLoading')" name="loadingMoreLoading" />
<slot v-else-if="_shouldShowLoading('loadingMoreNoMore')" name="loadingMoreNoMore" />
<slot v-else-if="_shouldShowLoading('loadingMoreFail')" name="loadingMoreFail" />
<z-paging-load-more @click.native="_onLoadingMore('click')"
v-else-if="_shouldShowLoading('loadingMoreCustom')" :zConfig="zPagingLoadMoreConfig">
</z-paging-load-more>
</view>
</view>
<!-- 空数据图 -->
<view style="flex: 1;" key="z-paging-empty-view" :style="[scrollViewStyle,useChatRecordMode ? {transform: nIsFirstPageAndNoMore?'rotate(0deg)':'rotate(180deg)'}:{}]" v-if="showEmpty" :is="finalNvueListIs==='scroller'?'view':finalNvueListIs==='waterfall'?'header':'cell'">
<view class="zp-empty-view">
<slot v-if="$slots.empty" name="empty" />
<z-paging-empty-view v-else :emptyViewImg="finalEmptyViewImg" :emptyViewText="finalEmptyViewText" :showEmptyViewReload="finalShowEmptyViewReload" :emptyViewReloadText="finalEmptyViewReloadText" :isLoadFailed="isLoadFailed" :emptyViewStyle="emptyViewStyle" :emptyViewTitleStyle="emptyViewTitleStyle" :emptyViewImgStyle="emptyViewImgStyle" :emptyViewReloadStyle="emptyViewReloadStyle" :emptyViewZIndex="emptyViewZIndex" @reload="_emptyViewReload">
</z-paging-empty-view>
</view>
</view>
</view>
<slot name="bottom"></slot>
<view v-if="showBackToTopClass" :class="backToTopClass" :style="[finalBackToTopStyle]" @click.stop="_backToTopClick">
<slot v-if="$slots.backToTop" name="backToTop" />
<image v-else class="zp-back-to-top-img" :src="backToTopImg.length?backToTopImg:base64BackToTop"></image>
</view>
</view>
<!-- #endif -->
</template>
<!-- #ifdef APP-VUE || MP-WEIXIN || MP-QQ || H5 -->
<script
src="./wxs/z-paging-wxs.wxs"
module="pagingWxs"
lang="wxs"
></script>
<!-- #endif -->
<script module="pagingRenderjs" lang="renderjs">
import pagingRenderjs from './wxs/z-paging-renderjs.js';
/**
* z-paging 分页组件
* @description 【uni-app自动分页器】超简单低耦合仅需两步轻松完成完整分页逻辑(下拉刷新、上拉加载更多)分页全自动处理。支持自定义加载更多的文字或整个view自定义下拉刷新样式自动管理空数据view等。
* @tutorial http://z-paging.com
* @property {Number|String} default-page-no 自定义pageNo默认为1
* @property {Number|String} default-page-size 自定义pageSize默认为10
* @property {Number|Object} data-key 为保证数据一致设置当前tab切换时的标识key并在complete中传递相同key若二者不一致则complete将不会生效
* @property {String} autowire-list-name 【极简写法】自动注入的list名可自动修改父view(包含ref="paging")中对应name的list值(z-paging标签必须设置`ref="paging"`)
* @property {String} autowire-query-name 【极简写法】自动注入的query名可自动调用父view(包含ref="paging")中的query方法(z-paging标签必须设置`ref="paging"`)
* @property {Number|Object} delay 调用complete后延迟处理的时间单位为毫秒
* @property {String} language i18n国际化设置语言支持简体中文(zh-cn)、繁体中文(zh-hant-cn)和英文(en)
* @property {Boolean} follow-system-language i18n国际化默认是否跟随系统语言默认为是
* @property {Object} paging-style 设置z-paging的style部分平台可能无法直接修改组件的style可使用此属性代替
* @property {Object} paging-content-style 设置z-paging的容器(插槽的父view)的style
* @property {Boolean} auto-height z-paging是否自动高度若自动高度则会自动铺满屏幕默认为否
* @property {Number|String} auto-height-addition z-paging是否自动高度时附加的高度注意添加单位px或rpx默认为px若需要减少高度请传负数
* @property {String} default-theme-style loading(下拉刷新、上拉加载更多)的主题样式支持blackwhite默认black
* @property {String} refresher-theme-style 下拉刷新的主题样式支持blackwhite默认black
* @property {String} loading-more-theme-style 底部加载更多的主题样式支持blackwhite默认black
* @property {Boolean} refresher-only 是否只使用下拉刷新设置为true后将关闭mounted自动请求数据、关闭滚动到底部加载更多强制隐藏空数据图。默认为否
* @property {Boolean} use-page-scroll 使用页面滚动默认为否当设置为是时则使用页面的滚动而非此组件内部的scroll-view的滚动使用页面滚动时z-paging无需设置确定的高度且对于长列表展示性能更高但配置会略微繁琐
* @property {Boolean} fixed z-paging是否使用fixed布局若使用fixed布局则z-paging的父view无需固定高度z-paging高度默认为100%,默认为否(当使用内置scroll-view滚动时有效)
* @property {Boolean} safe-area-inset-bottom 是否开启底部安全区域适配,默认为否
* @property {Boolean} scrollable 是否可以滚动使用内置scroll-view和nvue时有效默认为是
* @property {Boolean} auto [z-paging]mounted后自动调用reload方法(mounted后自动调用接口),默认为是
* @property {Boolean} auto-scroll-to-top-when-reload reload时自动滚动到顶部默认为是
* @property {Boolean} auto-clean-list-when-reload reload时立即自动清空原list默认为是若立即自动清空则在reload之后、请求回调之前页面是空白的
* @property {Boolean} show-refresher-when-reload 调用reload方法时是否自动显示下拉刷新view默认为否
* @property {Boolean} show-loading-more-when-reload 调用reload方法时自动显示加载更多view且为加载中状态(仅初始设置有效,不可动态修改)
* @property {Boolean} refresher-update-time-key 如果需要区别不同页面的最后更新时间请为不同页面的z-paging的`refresher-update-time-key`设置不同的字符串
* @property {Boolean} use-custom-refresher 是否使用自定义的下拉刷新默认为是即使用z-paging的下拉刷新。设置为false即代表使用uni scroll-view自带的下拉刷新h5、App、微信小程序以外的平台不支持uni scroll-view自带的下拉刷新
* @property {Number|String} refresher-fps 自定义下拉刷新下拉帧率默认为40过高可能会出现抖动问题(use-custom-refresher为true时生效)
* @property {Number|String} refresher-max-angle 自定义下拉刷新允许触发的最大下拉角度默认为40度当下拉角度小于设定值时自定义下拉刷新动画不会被触发
* @property {Boolean} refresher-angle-enable-change-continued 自定义下拉刷新的角度由未达到最大角度变到达到最大角度时,是否继续下拉刷新手势,默认为否
* @property {String|Object} refresher-default-text 自定义下拉刷新默认状态下的文字(use-custom-refresher为true时生效)
* @property {String|Object} refresher-pulling-text 自定义下拉刷新松手立即刷新状态下的文字(use-custom-refresher为true时生效)
* @property {String|Object} refresher-refreshing-text 自定义下拉刷新刷新中状态下的文字(use-custom-refresher为true时生效)
* @property {Boolean} refresher-end-bounce-enabled 是否开启自定义下拉刷新刷新结束回弹效果,默认为是(use-custom-refresher为true时生效)
* @property {Object} loading-more-custom-style 自定义底部加载更多样式
* @property {Object} loading-more-loading-icon-custom-style 自定义底部加载更多加载中动画样式
* @property {String} loading-more-loading-icon-type 自定义底部加载更多加载中动画图标类型可选circle或flower默认为circle
* @property {String} loading-more-loading-icon-custom-image 自定义底部加载更多加载中动画图标图片
* @property {Boolean} loading-more-loading-animated 底部加载更多加载中view是否展示旋转动画(loading-more-loading-icon-custom-image有值时有效nvue无效)
* @property {Boolean} loading-more-enabled 是否启用加载更多数据(含滑动到底部加载更多数据和点击加载更多数据),默认为是
* @property {Boolean} to-bottom-loading-more-enabled 是否启用滑动到底部加载更多数据
* @property {String|Object} loading-more-default-text 滑动到底部"默认"文字,默认为【点击加载更多】
* @property {String|Object} loading-more-loading-text 滑动到底部"加载中"文字,默认为【正在加载...】
* @property {String|Object} loading-more-no-more-text 滑动到底部"没有更多"文字,默认为【没有更多了】
* @property {String|Object} loading-more-fail-text 滑动到底部"加载失败"文字,默认为【加载失败,点击重新加载】
* @property {Boolean} hide-loading-more-when-no-more-and-inside-of-paging 当没有更多数据且分页内容未超出z-paging时是否隐藏没有更多数据的view默认为是
* @property {Boolean} hide-loading-more-when-no-more-and-inside-of-paging 当没有更多数据且分页内容未超出z-paging时是否隐藏没有更多数据的view默认为是
* @property {Boolean} inside-more 当分页未满一屏时,是否自动加载更多(nvue无效),默认为否
* @property {Boolean} show-default-loading-more-text 是否显示默认的加载更多text默认为是
* @property {Boolean} show-loading-more-no-more-line 是否显示没有更多数据的分割线,默认为是
* @property {Object} loading-more-no-more-line-custom-style 自定义底部没有更多数据的分割线样式
* @property {Boolean} hide-empty-view 是否强制隐藏空数据图,默认为否
* @property {String|Object} empty-view-text 空数据图描述文字,默认为“没有数据哦~”
* @property {Boolean} show-empty-view-reload 是否显示空数据图重新加载按钮(无数据时),默认为否
* @property {Boolean} show-empty-view-reload-when-error 加载失败时是否显示空数据图重新加载按钮,默认为是
* @property {String} empty-view-img 空数据图图片默认使用z-paging内置的图片
* @property {String|Object} empty-view-reload-text 空数据图点击重新加载文字
* @property {String|Object} empty-view-error-text 空数据图“加载失败”描述文字
* @property {String} empty-view-error-img 空数据图“加载失败”图片默认使用z-paging内置的图片(建议使用绝对路径)
* @property {Object} empty-view-style 空数据图样式
* @property {Object} empty-view-img-style 空数据图img样式
* @property {Object} empty-view-title-style 空数据图描述文字样式
* @property {Object} empty-view-reload-style 空数据图重新加载按钮样式
* @property {Boolean} auto-hide-empty-view-when-loading 加载中时是否自动隐藏空数据图,默认为是
* @property {Boolean} auto-hide-loading-after-first-loaded 第一次加载后自动隐藏loading slot默认为是
* @property {Boolean} auto-show-back-to-top 自动显示点击返回顶部按钮,默认为否
* @property {Number|String} back-to-top-threshold 点击返回顶部按钮显示/隐藏的阈值(滚动距离)单位为px默认为400rpx
* @property {String} back-to-top-img 点击返回顶部按钮的自定义图片地址默认使用z-paging内置的图片
* @property {Boolean} back-to-top-with-animate 点击返回顶部按钮返回到顶部时是否展示过渡动画,默认为是
* @property {Number|String} back-to-top-bottom 点击返回顶部按钮与底部的距离注意添加单位px或rpx默认为160rpx
* @property {Object} back-to-top-style 点击返回顶部按钮的自定义样式
* @property {Boolean} show-scrollbar 在设置滚动条位置时使用动画过渡,默认为否
* @property {Boolean} scroll-to-top-bounce-enabled iOS设备上滚动到顶部时是否允许回弹效果默认为否。关闭回弹效果后可使滚动到顶部与下拉刷新更连贯但是有吸顶view时滚动到顶部时可能出现抖动。
* @property {Boolean} scroll-with-animation 控制是否出现滚动条,默认为否
* @property {String} scroll-into-view 值应为某子元素idid不能以数字开头。设置哪个方向可滚动则在哪个方向滚动到该元素
* @property {Number|String} lower-threshold 距底部/右边多远时单位px触发 scrolltolower 事件默认为100rpx
* @property {Boolean} enable-back-to-top iOS点击顶部状态栏、安卓双击标题栏时滚动条返回顶部只支持竖向默认为是
* @property {Boolean} refresher-enabled 是否开启自定义下拉刷新,默认为是
* @property {Number|String} refresher-threshold 设置自定义下拉刷新阈值默认为80rpx
* @property {String} refresher-default-style 设置自定义下拉刷新默认样式,支持设置 blackwhitenonenone 表示不使用默认样式默认为black
* @property {String} refresher-background 设置自定义下拉刷新区域背景颜色
* @property {Boolean} show-refresher-update-time 是否显示上次下拉刷新更新时间,默认为否
* @property {String} refresher-update-time-key 上次下拉刷新更新时间的key用于区别不同的上次更新时间
* @property {Number|String} local-paging-loading-time 本地分页时上拉加载更多延迟时间单位为毫秒默认200毫秒
* @property {Boolean} use-chat-record-mode 使用聊天记录模式,默认为否
* @property {Number} top-z-index slot="top"的view的z-index仅使用页面滚动时有效默认为99
* @property {Number} super-content-z-index z-paging内容容器父view的z-index默认为1
* @property {Number} content-z-index z-paging内容容器部分的z-index默认为10
* @property {Number} empty-view-z-index 空数据view的z-index默认为9
* @property {Boolean} auto-full-height 使用页面滚动时,是否在不满屏时自动填充满屏幕,默认为是
* @property {Boolean} concat 自动拼接complete中传过来的数组(使用聊天记录模式时无效),默认为是
* @property {String} nvue-list-is nvue中修改列表类型可选值有list、waterfall和scroller默认为list
* @property {Object} nvue-waterfall-config nvue waterfall配置仅在nvue中且nvueListIs=waterfall时有效配置参数详情参见https://uniapp.dcloud.io/component/waterfall
* @property {Boolean} nvue-bounce nvue 控制是否回弹效果iOS不支持动态修改(若禁用回弹效果,下拉刷新将失效),默认为是
* @property {Boolean} nvue-fast-scroll nvue中通过代码滚动到顶部/底部时,是否加快动画效果(无滚动动画时无效),默认为否
* @property {Boolean} show-console-error 是否将错误信息打印至控制台,默认为是
* @event {Function} query 组件加载时会自动触发此方法因此默认页面加载时会自动触发无需手动调用。pageNo和pageSize会自动计算好直接传给服务器即可。
* @event {Function} refresherStatusChange 自定义下拉刷新状态改变(use-custom-refresher为true时生效)【注:通过`:refresher-status.sync`绑定当前data中的指定变量亦可】
* @event {Function} loadingStatusChange 上拉加载更多状态改变
* @event {Function} refresherTouchstart 自定义下拉刷新下拉开始(use-custom-refresher为true时生效)【注:当需要更细致定制自定义下拉刷新时使用,如果只需监听下拉刷新各个状态改变,使用`refresherStatusChange`即可】
* @event {Function} refresherTouchmove 自定义下拉刷新下拉中开始(use-custom-refresher为true时生效)【注:当需要更细致定制自定义下拉刷新时使用,如果只需监听下拉刷新各个状态改变,使用`refresherStatusChange`即可】
* @event {Function} refresherTouchend 自定义下拉刷新下拉结束(use-custom-refresher为true时生效)【注:当需要更细致定制自定义下拉刷新时使用,如果只需监听下拉刷新各个状态改变,使用`refresherStatusChange`即可】
* @event {Function} onRefresh 自定义下拉刷新被触发
* @event {Function} onRestore 自定义下拉刷新被复位
* @event {Function} scroll `z-paging`内置的scroll-view滚动时触发
* @event {Function} scrollTopChange scrollTop改变时触发使用点击返回顶部时需要获取scrollTop时可使用此事件【注通过`:scroll-top.sync`绑定当前data中的指定变量亦可】(@scrolltoupper触发时也会自动触发此方法且scrollTop=0)
* @event {Function} scrolltolower `z-paging`内置的scroll-view滚动底部时触发
* @event {Function} scrolltoupper `z-paging`内置的scroll-view滚动顶部时触发
* @event {Function} listChange 分页渲染的数组改变时触发
* @event {Function} emptyViewReload 点击了空数据图中的重新加载按钮
* @example <z-paging ref="paging" v-model="dataList" @query="queryList"></z-paging>
*/
export default {
name:"z-paging",
// #ifdef APP-VUE || H5
mixins: [pagingRenderjs],
// #endif
// 以下代码是为了欺骗编译器使props的代码提示功能生效不会被编译到项目中
// #ifdef QUICKAPP-WEBVIEW-UNION
props: {
defaultPageNo: {type: [Number, String]},
defaultPageSize: {type: [Number, String]},
dataKey: {type: [Number, Object]},
autowireListName: {type: String},
autowireQueryName: {type: String},
delay: {type: [Number, String]},
language: {type: String},
followSystemLanguage: {type: Boolean},
pagingStyle: {type: Object},
pagingContentStyle: {type: Object},
autoHeight: {type: Boolean},
autoHeightAddition: {type: [Number, String]},
defaultThemeStyle: {type: String},
refresherThemeStyle: {type: String},
loadingMoreThemeStyle: {type: String},
refresherOnly: {type: Boolean},
usePageScroll: {type: Boolean},
fixed: {type: Boolean},
safeAreaInsetBottom: {type: Boolean},
scrollable: {type: Boolean},
mountedAutoCallReload: {type: Boolean},
auto: {type: Boolean},
autoScrollToTopWhenReload: {type: Boolean},
autoCleanListWhenReload: {type: Boolean},
showRefresherWhenReload: {type: Boolean},
showLoadingMoreWhenReload: {type: Boolean},
useCustomRefresher: {type: Boolean},
refresherFps: {type: [Number, String]},
refresherMaxAngle: {type: [Number, String]},
refresherAngleEnableChangeContinued: {type: Boolean},
refresherDefaultText: {type: [String, Object]},
refresherPullingText: {type: [String, Object]},
refresherRefreshingText: {type: [String, Object]},
refresherEndBounceEnabled: {type: Boolean},
loadingMoreCustomStyle: {type: Object},
loadingMoreLoadingIconCustomStyle: {type: Object},
loadingMoreLoadingIconType: {type: String},
loadingMoreLoadingIconCustomImage: {type: String},
loadingMoreLoadingAnimated: {type: Boolean},
loadingMoreEnabled: {type: Boolean},
toBottomLoadingMoreEnabled: {type: Boolean},
loadingMoreDefaultText: {type: [String, Object]},
loadingMoreLoadingText: {type: [String, Object]},
loadingMoreNoMoreText: {type: [String, Object]},
loadingMoreFailText: {type: [String, Object]},
hideLoadingMoreWhenNoMoreAndInsideOfPaging: {type: Boolean},
hideLoadingMoreWhenNoMoreByLimit: {type: Number},
insideMore: {type: Boolean},
showDefaultLoadingMoreText: {type: Boolean},
showLoadingMoreNoMoreView: {type: Boolean},
showLoadingMoreNoMoreLine: {type: Boolean},
loadingMoreNoMoreLineCustomStyle: {type: Object},
hideEmptyView: {type: Boolean},
emptyViewText: {type: [String, Object]},
showEmptyViewReload: {type: Boolean},
showEmptyViewReloadWhenError: {type: Boolean},
emptyViewReloadText: {type: [String, Object]},
emptyViewImg: {type: String},
emptyViewErrorText: {type: [String, Object]},
emptyViewErrorImg: {type: String},
emptyViewStyle: {type: Object},
emptyViewImgStyle: {type: Object},
emptyViewTitleStyle: {type: Object},
emptyViewReloadStyle: {type: Object},
autoHideEmptyViewWhenLoading: {type: Boolean},
autoHideLoadingAfterFirstLoaded: {type: Boolean},
autoShowBackToTop: {type: Boolean},
backToTopThreshold: {type: [Number, String]},
backToTopImg: {type: String},
backToTopWithAnimate: {type: Boolean},
backToTopBottom: {type: [Number, String]},
backToTopStyle: {type: Object},
showScrollbar: {type: Boolean},
scrollToTopBounceEnabled: {type: Boolean},
scrollToBottomBounceEnabled: {type: Boolean},
scrollWithAnimation: {type: Boolean},
scrollIntoView: {type: String},
lowerThreshold: {type: [Number, String]},
enableBackToTop: {type: Boolean},
refresherEnabled: {type: Boolean},
refresherThreshold: {type: [Number, String]},
refresherDefaultStyle: {type: String},
refresherBackground: {type: String},
refresherFixedBackground: {type: String},
refresherFixedBacHeight: {type: [Number, String]},
refresherOutRate: {type: Number},
showRefresherUpdateTime: {type: Boolean},
refresherUpdateTimeKey: {type: String},
localPagingLoadingTime: {type: [Number, String]},
useChatRecordMode: {type: Boolean},
topZIndex: {type: Number},
superContentZIndex: {type: Number},
contentZIndex: {type: Number},
emptyViewZIndex: {type: Number},
autoFullHeight: {type: Boolean},
concat: {type: Boolean},
nvueListIs: {type: String},
nvueWaterfallConfig: {type: Object},
nvueBounce: {type: Boolean},
nvueFastScroll: {type: Boolean},
showConsoleError: {type: Boolean},
value: {type: Array}
}
// #endif
}
</script>
<script
src="./js/z-paging-main.js"></script>
<style scoped>
@import "./css/z-paging-main.css";
@import "./css/z-paging-static.css";
</style>

View File

@@ -0,0 +1,80 @@
{
"id": "z-paging",
"displayName": "【z-paging下拉刷新、上拉加载更多】超简单、低耦合仅需两步轻松完成完整分页逻辑",
"version": "2.0.1",
"description": "【支持nvue使用wxs+renderjs实现】全平台兼容支持自定义下拉刷新、上拉加载更多支持自动管理空数据图、点击返回顶部支持聊天分页、本地分页支持展示最后更新时间支持国际化等等",
"keywords": [
"下拉刷新",
"上拉加载",
"分页器",
"nvue",
"wxs"
],
"repository": "https://github.com/SmileZXLee/uni-z-paging",
"engines": {
"HBuilderX": "^3.0.7"
},
"dcloudext": {
"category": [
"前端组件",
"通用组件"
],
"sale": {
"regular": {
"price": "0.00"
},
"sourcecode": {
"price": "0.00"
}
},
"contact": {
"qq": "393727164"
},
"declaration": {
"ads": "无",
"data": "无",
"permissions": "无"
},
"npmurl": ""
},
"uni_modules": {
"dependencies": [],
"encrypt": [],
"platforms": {
"cloud": {
"tcb": "y",
"aliyun": "y"
},
"client": {
"App": {
"app-vue": "y",
"app-nvue": "y"
},
"H5-mobile": {
"Safari": "y",
"Android Browser": "y",
"微信浏览器(Android)": "y",
"QQ浏览器(Android)": "y"
},
"H5-pc": {
"Chrome": "y",
"IE": "y",
"Edge": "y",
"Firefox": "y",
"Safari": "y"
},
"小程序": {
"微信": "y",
"阿里": "y",
"百度": "y",
"字节跳动": "y",
"QQ": "y"
},
"快应用": {
"华为": "u",
"联盟": "u"
}
}
}
}
}

View File

@@ -0,0 +1,237 @@
# z-paging
***
## 【注意】由V1.9.0起fixed属性默认值为truez-paging默认会铺满屏幕。老项目更新请注意使用侧滑滚动切换选项卡或需要局部使用z-paging请设置:fixed="false"。如果您希望fixed属性默认为false请参考文档z-paging.com将fixed默认值设置为false。
***
> 【uni-app自动分页器】超简单低耦合仅需两步轻松完成完整分页逻辑(下拉刷新、上拉加载更多)分页全自动处理。支持自定义加载更多的文字或整个view自定义下拉刷新样式自动管理空数据view支持吸顶效果支持国际化等。
### API文档地址[http://z-paging.com](http://z-paging.com)
### 备用API文档地址[https://www.kancloud.cn/zxlee/z-paging/content](https://www.kancloud.cn/zxlee/z-paging/content)
### 功能&特点
* 【配置简单】仅需两步(绑定网络请求方法、绑定分页结果数组)轻松完成完整下拉刷新,上拉加载更多功能。
* 【低耦合低侵入】分页自动管理。在page中无需处理任何分页相关逻辑无需在data中定义任何分页相关变量全由z-paging内部处理。
* 【超灵活,支持各种类型自定义】支持自定义下拉刷新,自定义上拉加载更多,自带自定义下拉刷新效果,及其他数十种自定义属性。
* 【功能丰富】支持国际化支持自定义且自动管理空数据图支持主题模式切换支持本地分页支持聊天分页模式支持展示最后更新时间支持吸顶效果支持内部scroll-view滚动与页面滚动支持一键滚动到顶部等诸多功能。
* 【多平台兼容细致流畅】支持nvue支持h5、app及各家小程序在app-vue、h5、微信小程序、QQ小程序上使用wxs实现下拉刷新大幅提升性能。多处细节优化给您精致流畅的体验。
### 反馈qq群(点击加群)[790460711](https://jq.qq.com/?_wv=1027&k=vU2fKZZH)
#### 关于自动引入组件
> `z-paging` 支持[easycom组件规范](https://uniapp.dcloud.io/component/README?id=easycom组件规范),无需引用和注册组件即可直接使用,在正在运行的项目中导入`z-paging`可能会提示:`Unknown custom element<z-paging> - did you register the component corrently?... `,此时需要重新运行项目即可。
### 预览
***
| 自定义下拉刷新效果+分页演示 | 吸顶效果+分页演示 |
| :----------------------------------------------------------: | :----------------------------------------------------------: |
| ![](http://www.zxlee.cn/github/uni-z-paging/uni-z-paging.gif) | ![](http://www.zxlee.cn/github/uni-z-paging/uni-z-paging2.gif) |
| 滑动切换选项卡+分页演示 | 聊天记录模式+分页演示 |
| :----------------------------------------------------------: | :----------------------------------------------------------: |
| ![](http://www.zxlee.cn/github/uni-z-paging/z-paging-demo3.gif) | ![](http://www.zxlee.cn/github/uni-z-paging/z-paging-demo4.gif) |
### 在线demo体验地址
* [http://www.zxlee.cn/github/uni-z-paging/demo/index.html](http://www.zxlee.cn/github/uni-z-paging/demo/index.html)
| 扫码体验 |
| ------------------------------------------------------------ |
| ![](http://www.zxlee.cn/github/uni-z-paging/z-paging-demo.png) |
### 此组件已支持`uni_modules`,下载完整示例时组件在`uni_modules`目录下。
## 基本使用
* ①在`<template>` 中使用@query绑定js中分页请求的方法(`z-paging`会将计算好的pageNo和pageSize两个参数传递到此方法中),然后通过` v-model`绑定列表for循环的list。
* ②在请求结果回调中,通过调用`z-paging``complete()`方法,将请求返回的数组传递给`z-paging`处理,如:`this.$refs.paging.complete(服务器返回的数组);`;若请求失败,调用:`this.$refs.paging.complete(false);`即可。
* 当tab切换或搜索时可以通过`this.$refs.paging.reload()`刷新整个列表。
* 在nvue中z-paging中插入的列表item(z-paging的直接子view)必须是cell必须使用cell包住因为在nvue中z-paging使用的是nvue的list组件具体请查阅demo中的`common-demo-n.vue`示例。
```html
<template>
<view class="content">
<z-paging ref="paging" v-model="dataList" @query="queryList">
<!-- list数据建议像下方这样在item外层套一个view而非直接for循环item因为slot插入有数量限制 -->
<view>
<view class="item" v-for="(item,index) in dataList">
<view class="item-title">{{item.title}}</view>
</view>
</view>
</z-paging>
</view>
</template>
<script>
export default {
data() {
return {
dataList: [],
};
},
methods: {
queryList(pageNo, pageSize) {
//这里的pageNo和pageSize会自动计算好直接传给服务器即可
//这里的请求只是演示,请替换成自己的项目的网络请求,请在网络请求回调中
//通过this.$refs.paging.complete(请求回来的数组);将请求结果传给z-paging
this.$request.queryList(pageNo, pageSize, (data) => {
this.$refs.paging.complete(data);
});
},
},
};
</script>
<style scoped>
</style>
```
## 设置自定义emptyView组件示例
* 设置自定义emptyView组件非必须。空数据时会自动展示空数据组件不需要自己处理
```html
<z-paging ref="paging" v-model="dataList" @query="queryList">
<!-- 设置自己的emptyView组件非必须。空数据时会自动展示空数据组件不需要自己处理 -->
<empty-view slot="empty"></empty-view>
<view>
<view class="item" v-for="(item,index) in dataList">
<view class="item-title">{{item.title}}</view>
</view>
</view>
</z-paging>
```
## 自定义加载更多各个状态的描述文字示例
* 以修改【没有更多了】状态描述文字为例(将默认的"没有更多了"修改为"我也是有底线的!")
```html
<z-paging ref="paging" v-model="dataList" loading-more-no-more-text="我也是有底线的!" @query="queryList">
<!-- 设置自己的emptyView组件非必须。空数据时会自动展示空数据组件不需要自己处理 -->
<view>
<view class="item" v-for="(item,index) in dataList">
<view class="item-title">{{item.title}}</view>
</view>
</view>
</z-paging>
```
## 自定义下拉刷新view示例
* `use-custom-refresher`需要设置为true(默认为true)此时将不会使用uni自带的下拉刷新转为使用z-paging自定义的下拉刷新通过slot可以插入开发者自定义的下拉刷新view。
```html
<z-paging ref="paging" v-model="dataList" :refresher-threshold="80" @query="queryList">
<!-- 自定义下拉刷新view -->
<!-- 注意注意注意QQ小程序或字节跳动小程序中自定义下拉刷新不支持slot-scope将导致custom-refresher无法显示 -->
<!-- 如果是QQ小程序或字节跳动小程序请参照demo中的sticky-demo.vue中的写法此处使用slot-scope是为了减少data中无关变量声明降低依赖 -->
<custom-refresher slot="refresher" slot-scope="{refresherStatus}" :status="refresherStatus"></custom-refresher>
<!-- list数据建议像下方这样在item外层套一个view而非直接for循环item因为slot插入有数量限制 -->
<view>
<view class="item" v-for="(item,index) in dataList" @click="itemClick(item)">
<view class="item-title">{{item.title}}</view>
<view class="item-detail">{{item.detail}}</view>
<view class="item-line"></view>
</view>
</view>
</z-paging>
```
## 自定义加载更多各个状态的描述view示例
* 以修改【没有更多了】状态描述view为例
```html
<z-paging ref="paging" v-model="dataList" @query="queryList">
<view>
<view class="item" v-for="(item,index) in dataList">
<view class="item-title">{{item.title}}</view>
</view>
</view>
<view style="background-color: red" slot="loadingMoreNoMore">这是完全自定义的没有更多数据view</view>
</z-paging>
```
## 使用页面滚动示例
```html
<!-- 使用页面滚动示例(无需设置z-paging的高度) -->
<template>
<view class="content">
<!-- 此时使用了页面的滚动z-paging不需要有确定的高度use-page-scroll需要设置为true -->
<!-- 注意注意这里的ref必须设置且必须等于"paging"否则mixin方法无效 -->
<z-paging ref="paging" v-model="dataList" use-page-scroll @query="queryList">
<!-- 如果希望其他view跟着页面滚动可以放在z-paging标签内 -->
<!-- list数据建议像下方这样在item外层套一个view而非直接for循环item因为slot插入有数量限制 -->
<view>
<view class="item" v-for="(item,index) in dataList" :key="index" @click="itemClick(item)">
<view class="item-title">{{item.title}}</view>
<view class="item-detail">{{item.detail}}</view>
<view class="item-line"></view>
</view>
</view>
</z-paging>
</view>
</template>
<script>
//使用页面滚动时引入此mixin用于监听和处理onPullDownRefresh等页面生命周期方法(如果全局引入了就不要这一步全局引入示例见main.js)
import ZPagingMixin from '@/uni_modules/z-paging/components/z-paging/js/z-paging-mixin'
export default {
//注意这一步不要漏掉必须注册mixins(如果全局引入了就不要这一步全局引入示例见main.js)
mixins: [ZPagingMixin],
data() {
//参见demo
},
methods: {
//参见demo
}
}
</script>
```
## i18n示例
* 请参照demo`i18n-demo.vue`
## 性能与建议
| | 使用内置scroll-view滚动 | 使用页面滚动 | 使用nvue |
| :--------: | :----------------------------------------------------------: | :----------------------------------------------------------: | :----------------------------------------------------------: |
| **说明** | 默认模式,`z-paging`需要有确定的高度,下拉刷新与上拉加载更多由`z-paging`内部处理,配置简单。 | `use-page-scroll`设置为true时生效使用页面滚动而非内置scroll-view滚动无需固定`z-paging`的高度,但需要在页面滚动到底部时调用`z-paging``doLoadMore()`方法。<br>当使用页面的下拉刷新时需要引入mixin(可全局引入)具体可参见demo。 | 创建nvue页面并引入`z-paging`且运行在APP上生效`z-paging`将使用nvue独有的`<list>``<refresh>`代替原有的scroll-view和自定义的下拉刷新可大幅提升性能。 |
| **性能** | 不佳 | 一般 | 优 |
| **优缺点** | 【优点】配置简单、耦合度低。普通的简单列表不会有明显卡顿。<br/>【缺点】需要固定`z-paging`高度超出页面部分渲染的资源无法自动回收当列表item比较复杂或数据量过多时可能会造成明显卡顿。 | 【优点】性能优于使用内置的scroll-view滚动超出页面部分渲染的资源会自动回收能适应绝大多数列表滚动的情况即使列表item比较复杂一般也不会感知到卡顿。<br>【缺点】配置略麻烦,耦合度较高。 | 【优点】原生渲染,极致性能,`<list>`组件在不可见部分的渲染资源回收有特殊的优化处理,`<refresh>`组件是app端独有的下拉刷新组件性能远超普通vue页面中的自定义下拉刷新。<br>【缺点】仅App端支持nvue页面写法不如vue页面方便`z-paging`中一些配置和方法在nvue中不支持且nvue页面中支持的第三方组件也比vue页面少。 |
#### 【总结】
* 如果项目列表item比较简单分页数据量不是特别多建议使用默认的「内置scroll-view滚动」。
* 如果项目列表item比较复杂数据量多且使用「内置scroll-view滚动」时卡顿明显建议使用页面滚动。
* 如果是App项目且对性能和细节有较高要求建议在nvue中使用`z-paging`
## 注意事项及常见问题
* 【若无法下拉刷新】请确认要在@query所绑定的方法中调用`this.$refs.paging.complete()`无论是否需要网络请求都要调用只有告知z-paging刷新状态结束了才可以开始下次的下拉刷新。
* 【使用内置scroll-view滚动时】z-paging必须有确定的高度否则上拉加载更多将无法触发建议设置`:fixed=true`即可不设置高度!!(不希望跟着滚动的view可以设置`slot="top"`)。
* 【使用页面滚动时】使用z-paging内置的scroll-view滚动性能不及使用页面的滚动。若您要使用页面的滚动请勿固定z-paging的高度并且必须设置`use-page-scroll`为true否则将导致页面无法滚动(不希望跟着滚动的view可以设置`slot="top"`)。
* 【使用页面滚动时】必须引入mixin(可全局引入)(具体可参照demo中的`page-default-demo.vue`文件)或在页面的`onReachBottom`事件中调用`this.$refs.paging.doLoadMore()`且在`onPageScroll(e)`事件中调用`this.$refs.paging.updatePageScrollTop(e.scrollTop)`。(具体可参照demo中的`page-default-demo.vue`文件)
* 【出现实际上有更多数据而显示没有更多数据时】默认的pageSize(每页显示数量)为10如果您服务端不需要传pageSize(例如有默认的pageSize8)则您需要将默认的pageSize改成您与后端约定好的8若没有修改则z-paging会认为传给服务端的pageSize是10而服务端只返回了8条因此会直接判定为没有更多数据。
* 【若页面无法滚动】请检查z-paging是否有固定的高度若您想使用页面滚动而非z-paging内置的scroll-view的滚动请设置`use-page-scroll`为true。
* 【关于自定义导航栏】若设置了`:fixed=true`则必须将自定义导航栏放在z-paging标签中且添加slot="top",如:`<custom-nav slot="top"></custom-nav>`,如果有多个需要固定顶部的元素,则书写`<view slot="top">需要固定顶部的元素</view>`
### API文档地址[http://z-paging.com](http://z-paging.com)
### 备用API文档地址[https://www.kancloud.cn/zxlee/z-paging/content](https://www.kancloud.cn/zxlee/z-paging/content)