본문 바로가기
Framework/vue_Architecture

fetching data (vue.js)

by cariño 2022. 12. 26.
728x90
반응형

(현재 셋팅 상태: json-server를 사용하여 가상 데이터를 생성했음)

이제 vue에서 데이터를 패칭을 할 때 어떻게 해야하는지 알아보자.

 

vue의 생명주기에서 페이지가 로딩시에 진행되는 순서를 다시 생각해보면, 
부모 created ->  자식 created ->  자식 mounted -> 부모 mounted 이 상태를 잘 기억하고 있어야 한다. 

created는 인스턴스가 작성이 된 후에 동기적으로 호출된다.
데이터 초기화 선언시에 주로 created를 사용하는데 가상돔을 사용할 수 없는 상태이다. mounted는 인스턴스가 마운트 된 직후이기에 가상돔을 핸들링 할 수 있는 상태이다. 

 

* [ 먼저, 데이터를 가져오려면 언제 어디서 얻을 수 있는지?]

dom을 생성할 때 실행되는 생명주기 훅인 mounted() 해당 시점에서 데이터를 가져온다. 

 

//Jobs.vue

<template>
    <div v-for="job in jobs" :key="job.id">
        <router-link :to="{ name: 'JobDetails', params: { id: job.id } }">
        	<h2>{{ job.title }}</h2>
        </router-link>
    </div>
</template>

<script>
export default {
    data() {
        return {
            jobs: [],
        };
    },
    mounted() {
        fetch("http://localhost:3000/jobs")
            .then((res) => res.json())
            .then((data) => {this.jobs = data})
            .catch((err) => console.log(err));
    },
};
</script>

<style></style>

this.jobs = data으로 통신에서 받아온 data를 배열에 넣었다. 

 

 

//JobDetails.vue 

<template>
    <h1>{{ job.title }}</h1>
    <p>the job id is {{ id }}</p>
</template>

<script>
export default {
    props: ["id"],
    data() {
        return {
            job: null,
        };
    },
    mounted() {
        fetch("http://localhost:3000/jobs/" + this.id)
            .then((res) => res.json())
            .then((data) => {
                this.job = data;
            })
            .catch((err) => console.log(err));
    },
};
</script>

 

여기서 오류가 발생하기 시작했다. 

h1으로 감싼 job.title이 읽을 수 없는 속성이고, null속성도 읽을 수 없다고 한다. 

초기 mounted됐을 때 job이 null이라 error가 뜨는 상황이 발생했다. api를 이용해서 데이터를 가져올 때 mounted안에서 페이지를 로드하는데 1초정도 걸린다. job은 null로 선언했기 때문에 null의 값을 해석이 되지 않아 오류가 발생하는 것이다. 
(null은 패칭된 데이터를 액세스 할 수 없다)
 
영상이 영어고 자막이라 ㅠㅠ 글 정리가 잘 안된다.
정리하자면.. mounted를 통해 통신 요청으로 얻은 값을 사용할 수 있는 로딩 시간이 소요된다. 해당 로드 시간이 지나고 나서 데이터가 뿌려질 수 있도록 리팩토링 해야한다. 
 
 
이럴 때는 vue beginner 영상에서는 조건부로 항목을 출력할 수 있다고 한다. 
 

다른 블로그를 참고해서 보니까
1. DOM이 모두 load 되고 나서 import 하거나 (동기면 비동기로. async await, promise, load 등)
2. DOM state가 interactive 일때 약간의 시간을 delay한 후 function을 실행하는 것입니다.
3. 혹은 이벤트 실행 후 계속 관찰하다 원하는 element가 준비되면 function을 실행하면 됩니다.

 
이런 의견들이 많았다. 일단 vue3 비기너 영상만 끝나고 나면 promise로 다시 시도해봐야겠다. 
 

 
해결 된 코드
 
[ v-if를 이용하여 조건이 참인 경우에만 템플릿을 표현하게 하는 방법 ]
 
//Jobs.vue

<template>
    <div v-if="jobs.length">
        <div v-for="job in jobs" :key="job.id">
            <router-link :to="{ name: 'JobDetails', params: { id: job.id } }"
                ><h2>{{ job.title }}</h2></router-link
            >
        </div>
    </div>
    <div v-else>Loading...</div>
</template>

<script>
export default {
    data() {
        return {
            jobs: [],
        };
    },
    mounted() {
        fetch("http://localhost:3000/jobs")
            .then((res) => res.json())
            .then((data) => {
                this.jobs = data;
            })
            .catch((err) => console.log(err));
    },
};
</script>

jobs 데이터의 length가 있을 경우 패칭된 데이터가 출력이 되는 화면을 확인할 수 있게 됐다. 

 

//JobDetails.vue

<template>
    <div v-if="job">
        <h1>{{ job.title }}</h1>
        <p>아이디: {{ id }}</p>
        <p>{{ job.details }}</p>
    </div>
    <div v-else>
        <p>Loading...</p>
    </div>
</template>

<script>
export default {
    props: ["id"],
    data() {
        return {
            job: null,
        };
    },
    mounted() {
        fetch("http://localhost:3000/jobs/" + this.id)
            .then((res) => res.json())
            .then((data) => {
                this.job = data;
            })
            .catch((err) => console.log(err));
    },
};
</script>

마찬가지로 null값이 아닌 패칭된 데이터로 job에 데이터들이 생긴다면 아이템의 요소를 화면에 뿌릴 수 있게 됐다.

 

 

 

728x90

'Framework > vue_Architecture' 카테고리의 다른 글

Composition API: ref() vs reactive()  (0) 2023.01.02
Vue Router(1)  (0) 2023.01.02
composition API(1)_반응성(vue3.js)  (1) 2022.12.30
부모, 자식간 데이터 전송 (vue.js)  (0) 2022.12.25
데이터 양방향 바인딩 (vue.js)  (0) 2022.12.25

댓글