Vue

당겨서 새로고침

99duuk 2024. 10. 22. 17:24
<template>
  <div 
    ref="wrapper" 
    class="pull-refresh-wrapper"
    @touchstart="touchStart"
    @touchmove="touchMove"
    @touchend="touchEnd"
  >
    <div class="spinner" :style="spinnerStyle"></div>
    <slot></slot>
  </div>
</template>

<script>
export default {
  name: 'PullToRefresh',
  props: {
    onRefresh: { type: Function, required: true },
    disabled: { type: Boolean, default: false }
  },
  data() {
    return {
      startY: 0,
      moveY: 0,
      isRefreshing: false,
      threshold: 160,
      minPullDuration: 400
    };
  },
  computed: {
    spinnerStyle() {
      const translateY = Math.min(this.moveY * 0.4, this.threshold);
      const scale = Math.min(this.moveY / this.threshold, 1);
      return {
        transform: `translateY(${translateY}px) scale(${scale})`,
        opacity: scale
      };
    }
  },
  methods: {
    touchStart(e) {
      if (this.disabled || this.isRefreshing) return;
      if (this.$refs.wrapper.scrollTop <= 0) {
        this.startY = e.touches[0].pageY;
        this.startTime = new Date().getTime();
      }
    },
    touchMove(e) {
      if (this.startY > 0) {
        this.moveY = e.touches[0].pageY - this.startY;
        if (this.moveY > 0) {
          e.preventDefault();
          this.$refs.wrapper.style.transform = 
            `translateY(${Math.min(this.moveY / 2, this.threshold)}px)`;
        }
      }
    },
    async touchEnd() {
      const duration = new Date().getTime() - this.startTime;
      if (this.moveY >= this.threshold && 
          duration >= this.minPullDuration && 
          !this.isRefreshing) {
        this.isRefreshing = true;
        try {
          await this.onRefresh();
        } finally {
          this.isRefreshing = false;
        }
      }
      this.reset();
    },
    reset() {
      this.startY = 0;
      this.moveY = 0;
      setTimeout(() => {
        this.$refs.wrapper.style.transition = 'transform 0.3s ease';
        this.$refs.wrapper.style.transform = 'translateY(0)';
      }, 0);
    }
  }
};
</script>

<style scoped>
.pull-refresh-wrapper {
  overflow-y: auto;
  position: relative;
  height: 100%;
}

.spinner {
  height: 2rem;
  width: 2rem;
  border: 3px solid rgba(0, 0, 0, 0.1);
  border-top: 3px solid #999;
  border-radius: 50%;
  position: absolute;
  top: 0;
  left: 50%;
  transform: translateX(-50%);
  animation: rotation 1s linear infinite;
}

@keyframes rotation {
  from { transform: rotate(0deg); }
  to { transform: rotate(360deg); }
}
</style>

 

<template>
  <div class="app">
    <PullToRefresh :onRefresh="handleRefresh">
      <div class="content">
        <div>
        <!-- 컨텐츠 --> 
        </div>
      </div>
    </PullToRefresh>
  </div>
</template>


<script>
import PullToRefresh from './components/PullToRefresh.vue'

export default {
  components: { PullToRefresh },
  data() {
    return { .. }
    },
    
     methods: {
    async handleRefresh() {
      // 새로고침 시 수행할 작업 (예: API 호출)
      await new Promise(resolve => setTimeout(resolve, 1000));
      this.items = [
        ...this.items,
        { id: this.items.length + 1, text: `항목 ${this.items.length + 1}` }
      ];
    }
  }
}
</script>

<style>
..
</style>

 

 

야매로 만들어 보았읍ㄴ다람쥐

'Vue' 카테고리의 다른 글

선택항목 개수 계산  (0) 2024.10.28
템플릿에서 조건식 vs Computed  (0) 2024.10.28
vue-query 맛보기  (1) 2024.10.18
스크립트 요소 순서  (2) 2024.10.18
promise 사용  (0) 2024.10.18