본문 바로가기

framework(Vue_Nuxt)

infinite scroll(무한 스크롤)만들기

 

 

infinite scroll이란?

 

 

위와 같이 무한하게 데이터의 끝까지 스크롤이 가능하게 하여, 사용자편의(UX)를 높이는 기능이다.

현재 만들고 있는 토이프로젝트에 인피니트 스크롤기능을 구현해보려고 한다.

 

 

현재 PostCard를 구현중인 홈화면이다.

백엔드구현이 아직 안되어서 랜덤함수를 이용하여 store에 mutation으로 FakeUserData를 넣어줬다.

const fakePosts = Array(diff > limit ? limit : diff)
      .fill()
      .map(v => ({
        id: Math.random().toString(),
        User: {
          id: 1,
          nickname: "test"
        },
        content: `Hello scroll ${Math.random()}`,
        Comments: [],
        Images: []
      }));

 

 

그 다음, 테스트를 위해 state를 추가해주고, 편의를 위해 총 post개수는 51개, 한번 스크롤시 불러올 개수(limit)는 10개로 정의해주었다.

 

export const state = () => ({
  mainPosts: [],
  hasMorePost: true
});

const totalPosts = 51;
const limit = 10;

 

 

그 뒤, index page에서 인덱스 구성을 해주었다.

 

<script>
export default {
  computed: {
    me() {
      return this.$store.state.users.me;
    },
    mainPosts() {
      return this.$store.state.posts.mainPosts;
    },
    hasMorePost() {
      return this.$store.state.posts.hasMorePost;
    }
  },
  
  //1번@@@@@
  fetch({ store }) {
    store.dispatch("posts/loadPosts");
  },
  
  //2번@@@@
  mounted() {
    window.addEventListener("scroll", this.onScroll);
  },
  beforeDestroy() {
    window.removeEventListener("scroll", this.onScroll);
  },
};
</script>

 

 

1번: fetch는 보통 컴포넌트가 마운트 되기 전에(화면에 보이기 전에) vuex store에 비동기적으로 데이터를 넣을때 사용한다.

 

2번 : created로 생성시, destroy를 꼭 같이 써줘야 메모리 누수가 일어나지 않는다. 그러나 window는 created에서 사용할 수 없다. 하는수없이 mounted사용

 

 

 

methods: {
    onScroll() {
      if (
        window.scrollY + document.documentElement.clientHeight >
        document.documentElement.scrollHeight - 300
      ) {
        if (this.hasMorePost) {
          this.$store.dispatch("posts/loadPosts");
        }
      }
    }
  }

 

추가적으로 스크롤이 어느위치에 오면 추가 포스트를 불러올 것인가에 대해서

지정해 주었다(페이지 총길이에서 -300언저리)

 

 

 

export const mutations = {
  loadPosts(state) {
    const diff = totalPosts - state.mainPosts.length; //아직 안불러오고 남은 게시글의 갯수가 나옴
    const fakePosts = Array(diff > limit ? limit : diff)
      .fill()
      .map(v => ({
        id: Math.random().toString(),
        User: {
          id: 1,
          nickname: "test"
        },
        content: `Hello scroll ${Math.random()}`,
        Comments: [],
        Images: []
      }));
    state.mainPosts = state.mainPosts.concat(fakePosts);
    state.hasMorePost = fakePosts.length === limit;
  }
};

export const actions = {
  loadPosts({ commit, state }, payload) {
    if (state.hasMorePost) {
      commit("loadPosts");
    }
  }
};

해당 인덱스를 store에서 action으로 불러들여 mutation에서 동작하도록 랜덤함수값을 넣어준 부분에 데이터 추가.

 

 

 

 


 

 

결과

 

 

자동 스크롤이 되도록 지정해준 높이에 다다르면 위와 같이 loadPosts가 작동하며 새로운 post10개를 불러와준다.

(window.scrollY + document.documentElement.clientHeight > document.documentElement.scrollHeight - 300)

 

 

또한 totalPosts의 갯수를 51개로 지정해주었었는데

위와 같이 mainPosts Array배열에 51개가 담겨있는 것을 볼 수 있다.

'framework(Vue_Nuxt)' 카테고리의 다른 글

routing middleware(Vue)  (0) 2019.12.16
vuetify Grind System  (0) 2019.12.13
vuex component, mutation&action 실습 followlist예제  (0) 2019.12.12
Vuex란?  (0) 2019.12.10
Vue.js 화면 구성하기, 기본 문법  (0) 2019.12.09