| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242 |
- <template>
- <div class="nut-vert-scroll" ref="wrapper">
- <div class="nut-vert-list" ref="list" :style="{'min-height': listMinHeightStyle}">
- <div class="nut-vert-pulldown" v-if="isFirstPull">
- <div class="nut-vert-pulldown-txt" v-if="!isLoading">{{pulldownTxt}}</div>
- <div class="nut-vert-pulldown-status" v-else>
- <span class="nut-vert-loading"></span>
- <span class="nut-vert-loading-txt">加载中...</span>
- </div>
- </div>
- <slot name="list"></slot>
- <div class="nut-vert-loadmore" >
- <template v-if="!isUnMore && isShowLoadMore">
- <!-- <div class="nut-vert-load-txt" >{{loadMoreTxt}}</div> -->
- <div class="nut-vert-load-status" v-if="isLoading">
- <span class="nut-vert-loading"></span>
- <span class="nut-vert-loading-txt">加载中...</span>
- </div>
- </template>
- <template v-else-if="isUnMore">
- <div class="nut-vert-unloadmore-txt">{{unloadMoreTxt}}</div>
- </template>
- </div>
- </div>
- </div>
- </template>
- <script>
- export default {
- name:'nut-vert-scroll',
- props: {
- stretch: {
- type: Number,
- default: 100
- },
- isUnMore: {
- type: Boolean,
- default: false
- },
- isLoading: {
- type: Boolean,
- default: false
- },
- pulldownTxt: {
- type: String,
- default: '下拉刷新'
- },
- loadMoreTxt: {
- type: String,
- default: '上拉加载'
- },
- unloadMoreTxt: {
- type: String,
- default: '没有更多了'
- },
- threshold: {
- type: Number,
- default: 100
- },
- propsTime: {
- type:Number,
- default: 0
- },
- scrollTo: {
- type: Number,
- default: 1
- }
- },
- watch: {
- 'isLoading': function(status) {
- if (!status && this.realMove === 0) {
- clearTimeout(this.timer);
- this.timer = setTimeout(() => {
- this.setTransform(this.realMove, 'end', null);
- }, this.propsTime);
- }
- },
- 'isUnMore': function() {
- this.isShow();
- },
- 'scrollTo': function(val) {
- if (typeof val === 'number' && !isNaN(val) && val <= 0 ) {
- this.setTransform(val, null, 500);
- this.$emit('scrollToCbk');
- }
- }
- },
- data() {
- return {
- touchParams: {
- startY: 0,
- endY: 0,
- startTime: 0,
- endTime: 0
- },
- translateY: 0,
- scrollDistance: 0,
- timer: null,
- timerEmit: null,
- realMove: 0,
- isShowLoadMore: false,
- listMinHeightStyle: 'auto',
- isFirstPull: true
- }
- },
- methods: {
- isShow() {
- let wrapH = this.$refs.wrapper.offsetHeight;
- let listH = this.$refs.list.offsetHeight;
- if (wrapH < listH) {
- this.isShowLoadMore = true;
- this.listMinHeightStyle = 'auto'
- } else {
- this.isShowLoadMore = false;
- this.isFirstPull = true;
- this.listMinHeightStyle = `${wrapH}px`;
- }
- },
- setTransform(translateY = 0, type, time = 500) {
- if (type === 'end') {
- this.$refs.list.style.webkitTransition = `transform ${time}ms cubic-bezier(0.19, 1, 0.22, 1)`;
- } else {
- this.$refs.list.style.webkitTransition = '';
- }
- this.$refs.list.style.webkitTransform = `translate3d(0, ${translateY}px, 0)`;
- this.scrollDistance = translateY;
- },
- setMove(move, type, time) {
- let updateMove = move + this.translateY;
- let h = this.$refs.wrapper.offsetHeight;
- let maxMove = -this.$refs.list.offsetHeight + h;
- if (type === 'end') {
- if (updateMove > 0) {
- this.realMove = 0;
- if ((!this.isShowLoadMore || this.isFirstPull ) && !this.isLoading && updateMove > 20) {
- updateMove = 50;
- clearTimeout(this.timerEmit);
- this.timerEmit = setTimeout(() => {
- this.$emit('pulldown');
- }, time / 2);
- } else {
- this.isFirstPull = true;
- updateMove = 0;
- }
- } else if (updateMove < 0 && updateMove < maxMove + this.threshold) {
- if (updateMove < maxMove) {
- updateMove = maxMove;
- }
- this.realMove = maxMove;
- if (!this.isLoading && !this.isUnMore) {
- //clearTimeout(this.timerEmit);
- //this.timerEmit = setTimeout(() => {
- this.$emit('loadMore');
- // }, time / 2);
- }
- }
- // if (updateMove == 50 && !this.isLoading) {
- // clearTimeout(this.timer);
- // this.timer = setTimeout(() => {
- // this.setTransform(this.realMove, 'end', null);
- // }, 3000);
- // }
- this.setTransform(updateMove, type, time)
- } else {
- if (updateMove > 0 && updateMove > this.stretch) {
- updateMove = this.stretch;
- } else if (updateMove < maxMove - this.stretch) {
- updateMove = maxMove - this.stretch;
- }
- this.setTransform(updateMove, null, null);
- }
- },
-
- touchStart(event) {
- // event.preventDefault();
- let changedTouches = event.changedTouches[0];
- this.touchParams.startY = changedTouches.pageY;
- this.touchParams.startTime = event.timestamp || Date.now();
- this.translateY = this.scrollDistance;
- },
- touchMove(event) {
- event.preventDefault();
- let changedTouches = event.changedTouches[0];
- this.touchParams.lastY = changedTouches.pageY;
- this.touchParams.lastTime = event.timestamp || Date.now();
- let move = this.touchParams.lastY - this.touchParams.startY;
- if (move < 0 && this.isShowLoadMore && this.isFirstPull) {
- this.isFirstPull = false;
- }
- this.setMove(move);
- },
- touchEnd(event) {
- // event.preventDefault();
- let changedTouches = event.changedTouches[0];
- this.touchParams.lastY = changedTouches.pageY;
- this.touchParams.lastTime = event.timestamp || Date.now();
- let move = this.touchParams.lastY - this.touchParams.startY;
- let moveTime = this.touchParams.lastTime - this.touchParams.startTime;
- let h = this.$refs.wrapper.offsetHeight;
- let maxMove = -this.$refs.list.offsetHeight + h;
- if (moveTime <= 300) {
- move = move * 2;
- if (move < 0 && move < maxMove) {
- move = maxMove;
- }
- moveTime = moveTime + 500;
- this.setMove(move, 'end', moveTime);
- } else {
- this.setMove(move, 'end');
- }
- }
- },
- mounted() {
- this.$nextTick(() => {
- this.isShow();
- // 监听
- this.$el.addEventListener('touchstart', this.touchStart);
- this.$el.addEventListener('touchmove', this.touchMove);
- this.$el.addEventListener('touchend', this.touchEnd);
- });
- },
- beforeDestroy() {
- // 移除监听
- this.$el.removeEventListener('touchstart', this.touchStart);
- this.$el.removeEventListener('touchmove', this.touchMove);
- this.$el.removeEventListener('touchend', this.touchEnd);
- clearTimeout(this.timer);
- clearTimeout(this.timerEmit);
- }
- }
- </script>
|