Vue

[vue] 무한스크롤 적용하기

ITtraveler 2024. 8. 6. 12:29

 

 

 

무한스크롤 적용하기

 

 

 

처음에는 라이브러리 불러서 써보려고 했는데...

잘안되서 라이브러리는 포기하고 순수 바닐라자바스크립트 코드로 구현하였습니다.

 

 

기본 로직은 간단합니다.

 

1. 스크롤이 바닦에 갔는지 계산

2. 스크롤이 바닦까지 갔을때 데이터를 추가호출

3. 기존 화면에 뿌리는 데이터에 추가

 

 

 

data 변수 선언

 

 

처음 mount 할때 scroll 이벤트 리스너 추가

 

 

 

Backend 데이터 연결 부분

newData는 최종데이터까지만 추가 하도록 하지 않으면 무한반복됩니다.

 

 

scroll할때 페이지 높이 계산하여 데이터 추가

 

 

 

 

vue script 부분 코드

<script>
import axios from 'axios';

export default {
  name: "OrderComponent",
  data() {
    return {
      ordersList: [],
      currentPage: 0, // 페이지 변수를 currentPage로 설정
      pageSize: 5,    // 페이지 크기를 pageSize로 설정
      isLoading: false,
      isLastPage: false // 마지막 페이지 여부를 확인하는 변수
    };
  },
  mounted() {
    window.addEventListener('scroll', this.scrollPagination);
    this.getData();
  },
  methods: {
    async getData() {
        // 마지막 페이지이거나 로딩 중이면 중단
        if (this.isLastPage || this.isLoading) return;

        this.isLoading = true;

        try {
            const params = {
                page: this.currentPage,
                size: this.pageSize
            };

            const response = await axios.get(`http://localhost:8080/orders/list/user`, {
                params,
                withCredentials: true
            });

            const newData = response.data.result.content.map(item => ({ ...item, quantity: 1 }));
            if (newData.length < this.pageSize) {
                this.isLastPage = true;
            }

            this.ordersList = [...this.ordersList, ...newData];
        } catch (error) {
            console.error('Error fetching orders:', error);
        } finally {
            this.isLoading = false;
        }
    },
    scrollPagination() {
        const nearBottom = window.innerHeight + window.scrollY >= document.body.offsetHeight - 700;
        if (nearBottom && !this.isLastPage && !this.isLoading) {
            this.currentPage++;
            this.getData();
        }
    },
    formatOrderState(state) {
      switch (state) {
        case 'ready':
          return '상품준비';
        case 'shipped':
          return '배송중';
        case 'completed':
          return '배송완료';
        default:
          return '상태 미정';
      }
    }
  }
};
</script>

 

 

 

 

화면쪽 코드

<div v-for="order in ordersList" :key="order.order_id" class="css-9hrkbf e88f0q51">
<a class="css-h9u7nh e13d9bui8">
    <div class="css-1prr1nv e13d9bui7">
    <span class="css-mvcumu e13d9bui6">
        {{ new Date(order.order_date).toLocaleString() }}
    </span>
    <span class="css-yi6epy e13d9bui5">주문 상세</span>
    </div>
    <div class="css-1e8mkxi e13d9bui4">
    <dl class="css-oxiuin e13d9bui3">
        <dt class="css-1qdgh9t e13d9bui2">상품명</dt>
        <dd class="css-1iph3gc e13d9bui0">
        {{ order.item_name }} 외 {{ order.cnt - 1 }}건
        </dd>
    </dl>
    <dl class="css-oxiuin e13d9bui3">
        <dt class="css-1qdgh9t e13d9bui2">주문 번호</dt>
        <dd class="css-wstq91 e13d9bui1">{{ order.order_id }}</dd>
    </dl>
    <dl class="css-oxiuin e13d9bui3">
        <dt class="css-1qdgh9t e13d9bui2">결제 방법</dt>
        <dd class="css-wstq91 e13d9bui1">카카오페이</dd>
    </dl>
    <dl class="css-oxiuin e13d9bui3">
        <dt class="css-1qdgh9t e13d9bui2">결제 금액</dt>
        <dd class="css-wstq91 e13d9bui1">{{ order.price }}원</dd>
    </dl>
    <dl class="css-oxiuin e13d9bui3">
        <dt class="css-1qdgh9t e13d9bui2">주문 상태</dt>
        <dd class="css-wstq91 e13d9bui1">
        {{ formatOrderState(order.order_state) }}
        </dd>
    </dl>
    </div>
</a>
</div>

코드 부르는건 똑같이 부르면 됩니다.