douyin/src/components/Scroll.vue
2024-04-02 15:40:18 +08:00

133 lines
2.9 KiB
Vue

<template>
<div
v-if="useRefresh"
class="scroll-wrapper scroll Scroll"
ref="wrapper"
@touchmove="move"
@touchend="end"
@scroll="scroll"
>
<Loading :is-full-screen="false" :style="pullUpStyle" />
<div class="scroll-content" :style="pullUpStyle">
<slot></slot>
<Loading v-if="loading" :is-full-screen="false" />
</div>
</div>
<div v-else class="scroll-wrapper scroll Scroll" ref="wrapper" @scroll="scroll">
<div class="scroll-content">
<slot></slot>
<Loading v-if="loading" :is-full-screen="fullLoading" />
</div>
</div>
</template>
<script>
import Loading from './Loading'
import { nextTick } from 'vue'
export default {
name: 'Scroll',
components: {
Loading
},
props: {
fixedHeight: {
type: Number,
default: -1
},
useRefresh: {
type: Boolean,
default: false
},
loading: {
type: Boolean,
default: false
},
fullLoading: {
type: Boolean,
default: false
}
},
data() {
return {
wrapper: null,
startMoveY: null,
distance: null,
refresh: false
}
},
computed: {
pullUpStyle() {
return {
'transition-duration': this.refresh ? '300ms' : '0ms',
transform: `translate3d(0px, ${this.distance !== null ? this.distance : -40}px,0`
}
}
},
created() {},
mounted() {
nextTick(() => {
this.wrapper = this.$refs.wrapper
})
},
methods: {
move(e) {
// console.log(this.wrapper)
// console.log(this.wrapper.scrollTop)
if (this.refresh) return
if (this.wrapper.scrollTop > 0) return
if (this.wrapper.scrollTop === 0 && this.startMoveY === null) {
this.startMoveY = e.touches[0].pageY
}
let distance = e.touches[0].pageY - this.startMoveY
this.distance = distance - 40 < 10 ? distance - 40 : 10
},
end() {
this.startMoveY = null
if (this.distance !== null && this.wrapper.scrollTop === 0) {
this.refresh = true
this.distance = 10
this.$emit('refresh')
} else {
this.distance = null
}
// console.log('end')
},
refreshEnd() {
this.distance = null
setTimeout(() => {
this.refresh = false
}, 300)
},
async scroll() {
if (this.fixedHeight !== -1) {
this.$emit('fixed', this.fixedHeight < this.wrapper.scrollTop)
}
if (this.$attrs.onPulldown) {
if (this.wrapper.scrollHeight - this.wrapper.clientHeight < this.wrapper.scrollTop + 60) {
this.$emit('pulldown')
}
}
},
scrollBottom() {
nextTick(() => {
this.wrapper.scrollTo({
top: this.wrapper.scrollHeight - this.wrapper.clientHeight
})
})
}
}
}
</script>
<style scoped lang="less">
@import '../assets/less/index';
.scroll-wrapper {
overflow: auto;
.scroll-content {
padding-bottom: 30rem;
}
}
</style>