티스토리 뷰
vue3 환경에서 차트를 그리려고 한다. 기본적으로 chart.js를 사용하면서, vue3 기반으로 래핑해놓은 vue-chart-3를 활용하려고 한다. 그래서 공식문서 데모 페이지에 나와있는 대로 따라하려고 하니 문제가 하나 생겼다. 내가 화면에 보여줄 데이터는 백엔드와 비동기 통신을 통해서 받아야 한다. 그런데 데모 소스코드 상에서는 데이터가 아래와 같이 그냥 하드코딩 되어 있었다.
// template
<DoughnutChart :chartData="testData" />
// script
const dataValues = ref([30, 40, 60, 70, 5]);
const dataLabels = ref(["Paris", "Nîmes", "Toulon", "Perpignan", "Autre"]);
const testData = {
labels: dataLabels.value,
datasets: [
{
data: dataValues.value,
},
],
};
실제 chart.js를 활용하는 사례에서는 데이터를 하드코딩해서 넣는 경우보단, 백엔드에서 데이터를 비동기로 받아온 후에 넣는 경우가 더 일반적이다. 하지만 chart.js는 차트를 그리는 데 필요한 데이터를 받으면 곧바로 canvas
로 그려버리기 때문에, 그 이후에는 비동기로 데이터가 도착한다고 한들 차트가 변하지 않는다는 문제가 있다.
예를 들어 아래 코드와 같이 비동기 통신을 가장한 fetchData
함수가 onMounted
에서 실행된다 하더라도 차트는 그려지지 않는다.
const dataValues = ref([]);
const dataLabels = ref([]);
onMounted(() => {
fetchData().then((res) => {
dataValues.value = res.map((item) => item.data);
dataLabels.value = res.map((item) => item.label);
});
});
const testData = {
labels: dataLabels.value,
datasets: [
{
data: dataValues.value,
},
],
};
const fetchData = () => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve([
{ data: 10, label: "a" },
{ data: 30, label: "b" },
{ data: 15, label: "c" },
{ data: 5, label: "d" },
{ data: 20, label: "e" },
]);
}, 1000);
});
};
이를 해결하기 위해서는 dataValues
와 dataLabels
의 반응성을 testData
에 주입시켜주면 된다. 그래서 fetchData
에서 1초 뒤에 값을 받아오고 나면 testData
에서도 받아온 값으로 세팅되도록 해주면 된다. testData
에 반응성을 부여하는 방법으로는 computed
또는 watch
를 사용하면 되는데, computed
를 사용하는 방법이 훨씬 간단하다.
const testData = computed(() => {
return {
labels: dataLabels.value,
datasets: [
{
data: dataValues.value,
},
],
};
});
이런 식으로 computed
로 감싸주면 1초 뒤에 차트가 그려지게 된다.
'Dev' 카테고리의 다른 글
vue3 modal transition(모달 트랜지션) (0) | 2023.03.09 |
---|---|
vue3 route transition(라우트 트랜지션) (0) | 2023.03.09 |
vue 에서 스크롤 위치 저장 (0) | 2023.03.09 |
프로젝트 회고 (0) | 2023.02.18 |
vue 커스텀 디렉티브(custom directive) (0) | 2022.12.05 |