연권
달콘박스
연권
전체 방문자
오늘
어제
  • 전체 (308)
    • Web (22)
      • JavaScript (8)
      • TypeScript (2)
      • Node.js (8)
      • HTML (0)
      • CSS (0)
      • Network (1)
      • Browser (0)
      • Patterns (3)
    • Framwork (4)
      • Vue.js (3)
      • Electron (1)
    • Infra&DevOps (1)
    • Algorithm (246)
    • Database (16)
    • Review (15)
    • Test (4)

블로그 메뉴

  • 홈
  • 태그
  • 방명록

공지사항

인기 글

태그

  • 정렬
  • 백준
  • typescript
  • 동적계획법
  • 프로그래머스
  • BFS
  • sql
  • 백트레킹
  • MySQL
  • 스택
  • javascript
  • 재귀
  • DP
  • 알고리즘
  • java
  • 진수
  • 문자열
  • 진법
  • 백준ㅇ
  • 코딩테스트 연습

최근 댓글

최근 글

티스토리

hELLO · Designed By 정상우.
연권

달콘박스

Vue.js에서 infinite scroll 구현하기
Framwork/Vue.js

Vue.js에서 infinite scroll 구현하기

2021. 5. 27. 03:11
반응형

Vue.js에서 infinite scroll 구현하기

Vue.js에서 무한스크롤(infinite scroll)을 구현하는 방법에 대한 포스팅입니다.

chrome extension을 만들던 도중에 여러 글 목록을 나열해야될 일이 있어

pagination과 infinite scroll중에 어떤 걸 사용할까 고민하던 중

작은 화면에는 infinite scroll이 더 어울린다고 생각하여서 이걸로 진행하게 되었습니다.

 

vue-infinite-loading

intersection observer 객체를 사용해 구현하는 방법도 있지만 이미 만들어져있는 플러그인인 vue-infinite-loading을 사용하면 더 빠르게 구현할 수 있습니다.

https://www.npmjs.com/package/vue-infinite-loading

 

vue-infinite-loading

An infinite scroll plugin for Vue.js

www.npmjs.com

 

설치

npm으로 설치해주었습니다.

npm install vue-infinite-loading -S

 

예제

가이드에 나와있는 Hacker News 예제 입니다.

infinite-loading 컴포넌트를 삽입해주고 @infinite에 대한 핸들러를 작성해줍니다. 

 

Vue-infinite-loading

 

peachscript.github.io

<header>
  <!-- Hacker News header -->
</header>

<div v-for="(item, $index) in list" :key="$index">
  <!-- Hacker News item loop -->
</div>

<infinite-loading @infinite="infiniteHandler"></infinite-loading>
import axios from 'axios';

const api = '//hn.algolia.com/api/v1/search_by_date?tags=story';

export default {
  data() {
    return {
      page: 1,
      list: [],
    };
  },
  methods: {
    infiniteHandler($state) {
      axios.get(api, {
        params: {
          page: this.page,
        },
      }).then(({ data }) => {
        if (data.hits.length) {
          this.page += 1;
          this.list.push(...data.hits);
          $state.loaded();
        } else {
          $state.complete();
        }
      });
    },
  },
};

 

적용

위 예제를 프로젝트에 적용해보았습니다.

똑같이 컴포넌트를 삽입해주었고 핸들러를 async-await 문법으로 작성해주었습니다.

<template>
  <div>
    <v-list two-line height="470" style="overflow: scroll">
      <v-list-item-group active-class="pink--text">
        <template v-for="(item, index) in items">
          <v-list-item :key="item.subject">
            <v-list-item-content @click.stop="showContent(index)">
              <v-list-item-title v-text="item.subject"></v-list-item-title>

              <v-list-item-subtitle
                class="text--primary"
                v-text="item.auther"
              ></v-list-item-subtitle>

              <v-list-item-subtitle
                v-text="`조회 ${item.hits}`"
              ></v-list-item-subtitle>
            </v-list-item-content>

            <v-list-item-action>
              <v-list-item-action-text
                v-text="item.date"
              ></v-list-item-action-text>
            </v-list-item-action>
          </v-list-item>

          <v-divider v-if="index < items.length - 1" :key="index"></v-divider>
        </template>
        <infinite-loading @infinite="infiniteHandler"></infinite-loading>
      </v-list-item-group>
    </v-list>
    <!-- 다이얼로그 -->
    <v-dialog v-model="dialog" max-width="500">
      <v-card>
        <v-card-title class="headline">
          {{ contents.subject }}
        </v-card-title>

        <v-card-text v-html="contents.content"></v-card-text>

        <v-card-actions>
          <v-spacer></v-spacer>
          <v-btn color="error" text @click="dialog = false"> 닫기 </v-btn>
        </v-card-actions>
      </v-card>
    </v-dialog>
  </div>
</template>

<script>
import InfiniteLoading from "vue-infinite-loading";
import { daelimNotice } from "@/api/daelim.js";

export default {
  components: {
    InfiniteLoading,
  },

  data() {
    return {
      dialog: false,
      page: 0,
      items: [],
      contents: {
        subject: "",
        content: "",
      },
    };
  },

  methods: {
    showContent(idx) {
      this.dialog = true;
      this.contents.subject = this.items[idx].subject;
      this.contents.content = this.items[idx].contents;
    },
    async infiniteHandler($state) {
      try {
        const { data } = await daelimNotice(this.page);
        if (data.data.list) {
          await setTimeout(() => {
            this.page += 1;
            for (const bulletin of data.data.list) {
              const data = {
                subject: bulletin.SUBJECT,
                auther: bulletin.WRITER_NM,
                hits: bulletin.HITS,
                date: bulletin.WRITE_DATE,
                contents: bulletin.CONTENTS,
              };
              this.items.push(data);
            }
            $state.loaded();
          }, 1000);
        } else {
          $state.complete();
        }
      } catch (error) {
        console.log(error);
      }
    },
  },
};
</script>

반응형
저작자표시 동일조건 (새창열림)

'Framwork > Vue.js' 카테고리의 다른 글

Nuxt.js 에 폰트 적용 방법  (0) 2021.08.14
확장 프로그램 vue로 만들기 - 프로젝트 세팅하기  (0) 2021.03.25
    'Framwork/Vue.js' 카테고리의 다른 글
    • Nuxt.js 에 폰트 적용 방법
    • 확장 프로그램 vue로 만들기 - 프로젝트 세팅하기
    연권
    연권

    티스토리툴바