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 |
댓글