123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282 |
- <template>
- <view>
- <movable-area style="width: 100%;" :style="{'height':scrollHeight+50+'px'}">
- <view class="display_flex_center" style="height: 40px;font-size: 15px;color:#6b6a6a;">
- <view v-if="refreshSuccess">
- {{refreshSuccessText}}
- </view>
- <block v-else>
- <view v-if="!refreshing" class="refresh-icon display_flex_center" :class="{'refresh-icon-active': refreshFlag}">↓</view>
- <view v-if="!refreshing">{{refreshFlag?refreshReady:refreshText}}</view>
- <view v-else class="display_flex_center">
- <image src="./loading.gif" class="loading_img"></image>
- <text>{{refreshingText}}</text>
- </view>
- </block>
- </view>
- <movable-view :x="x" :y="y" :direction="isRefresh?'vertical':'none'" :out-of-bounds='false' style="width:100%;" :style="{'height':scrollHeight+'px'}"
- @change="onChange" @touchend="touchend">
- <view :style="{'height':scrollHeight+'px'}">
- <scroll-view :scroll-y="scrollStatus" :style="{'height':scrollHeight+'px','background':backgroundColor}" :scroll-into-view="top_viewId" :upper-threshold="10" @scroll="onScroll" @scrolltoupper="scrollToTop" @scrolltolower="loadMore">
- <view id="top_view" @touchstart="touchstart" @touchmove="touchMove">
- <slot></slot>
- </view>
- <view class="display_flex_center" style="height: 40px;font-size: 15px;color:#999">
- <block v-if="noMore">
- {{noMoreText}}
- </block>
- <block v-else-if="isLoading!=2">
- {{loadingMoreText}}
- </block>
- <block v-else>
- {{loadingText}}
- </block>
- </view>
- <view v-if="showGoTop && scrollTop>scrollHeight" class="go_top_icon_back" @click.stop="goTop">
- <image src="./go_top.png" class="top_icon"></image>
- </view>
- </scroll-view>
- </view>
- </movable-view>
- </movable-area>
- </view>
- </template>
-
- <script>
- export default {
- name:"zyq-movableRefresh",
- props: {
- isRefresh: {
- type: Boolean,
- default: true
- },
- scrollHeight: {
- type: Number,
- default: 300
- },
- refreshText: {
- type: String,
- default:'下拉可以刷新'
- },
- refreshReady: {
- type: String,
- default:'释放立即刷新'
- },
- refreshingText: {
- type: String,
- default:'正在刷新...'
- },
- refreshSuccessText: {
- type: String,
- default:'刷新完成'
- },
- loadingMoreText: {
- type: String,
- default:'上拉加载更多'
- },
- loadingText: {
- type: String,
- default:'正在加载...'
- },
- noMoreText: {
- type: String,
- default:'无更多数据'
- },
- pullHeight: {
- type: Number,
- default: 40
- },
- noMore: {
- type:Boolean,
- default:false
- },
- backgroundColor:{
- type: String,
- default:'#fff'
- },
- showGoTop: {
- type:Boolean,
- default:false
- }
- },
- data() {
- return {
- x: 50,
- y: 0,
- old: {
- x: 0,
- y: 0
- },
- refreshFlag: false,
- refreshing: false,
- scrollStatus: true,
- isLoading: 0, //加载状态,1:正在下拉刷新,2:正在触底加载
- refreshSuccess: false,
- scrollTop: 0,
- startX: 0,
- startY: 0,
- inTop: true,
- moveHeight: 0 ,//下拉刷新移动距离
- showLoadingMore: false,
- top_viewId: ''
- };
- },
- methods:{
- onChange(e){
- let y = e.detail.y
- this.old.x = e.detail.x
- this.old.y = y
- this.moveHeight = y
- if(y<this.pullHeight){
- this.refreshFlag = false
- }else{
- this.refreshFlag = true
- }
- },
- touchstart(e){
- let obj = e.changedTouches[0]
- this.startX = obj.pageX
- this.startY = obj.pageY
- },
- touchMove(e){
- if(!this.isRefresh){
- return
- }
- this.refreshSuccess = false
- let obj = e.changedTouches[0]
- let endX = obj.pageX
- let endY = obj.pageY
- let distanceX = endX - this.startX
- let distanceY = endY - this.startY
- if((this.inTop || this.scrollTop==0) && Math.abs(distanceX)<Math.abs(distanceY) && distanceY>0){
- this.scrollStatus = false
- }
- },
- touchend(e){
- let that = this
- let moveHeight = this.moveHeight
- if(moveHeight<this.pullHeight){
- this.x = this.old.x
- this.y = this.old.y
- this.$nextTick(function() {
- this.x = 0
- this.y = 0
- })
- this.refreshFlag = false
- this.refreshing = false
- }else{
- this.refreshing = true
- this.refreshFlag = true
- this.refresh()
- }
- this.scrollStatus = true
- },
- scrollToTop(e){
- if(this.scrollTop<5){
- this.inTop = true
- }
- },
- onScroll(e){
- let scrollTop = e.detail.scrollTop
- this.scrollTop = scrollTop
- this.$emit('onScroll',scrollTop);
- if(scrollTop>3){
- this.inTop = false
- }else{
- this.inTop = true
- }
- },
- goTop(){
- this.top_viewId = ""
- this.$nextTick(function() {
- this.top_viewId = "top_view"
- })
- },
- runRefresh(callback=false){
- let that = this
- this.x = this.old.x
- this.y = this.old.y
- this.$nextTick(function() {
- this.scrollTop = 0
- this.x = that.pullHeight
- this.y = that.pullHeight
- that.refreshing = true
- that.refreshFlag = true
- that.refresh()
- })
- },
- refresh(){
- if(this.isLoading){
- return
- }
- this.isLoading = 1
- this.$emit('refresh');
- },
- loadMore(){
- if(this.noMore || this.isLoading){
- return
- }
- this.isLoading = 2
- this.$emit('loadMore');
- },
- endLoad(){
- let that = this
- this.refreshSuccess = true
- setTimeout(function(){
- that.refreshSuccess = false
- },800)
- this.x = this.old.x
- this.y = this.old.y
- this.$nextTick(function() {
- this.x = 0
- this.y = 0
- })
- this.scrollStatus = true
- this.refreshing = false
- this.refreshFlag = false
- this.isLoading = 0
- }
- }
- }
- </script>
-
- <style>
- .display_flex_center{
- display: flex;
- justify-content: center;
- align-items: center;
- }
- .refresh-icon {
- width: 20px;
- height: 20px;
- font-weight: 700;
- transition-duration: .5s;
- transition-property: transform;
- transform: rotate(0deg);
- }
- .refresh-icon-active {
- transform: rotate(180deg);
- }
- .loading_img{
- width: 20px;
- height: 20px;
- margin-right: 5px;
- }
- .go_top_icon_back{
- position: fixed;
- right: 40px;
- bottom: 40px;
- height: 40px;
- width: 40px;
- border-radius: 50%;
- background: #fff;
- display: flex;
- justify-content: center;
- align-items: center;
- }
- .top_icon{
- height: 30px;
- width: 30px;
- }
- </style>
|