14 –애플리케이션 실전 파트– 외부 라이브러리 모듈화 방법(차트)

source: categories/study/vue-beginner-lv3/vue-beginner-lv3_9-05.md

14.1 라이브러리 모듈화의 이유와 배경

  1. 외부 라이브러리 모듈화
    • 외부 라이브러리를 모듈화해야하는 이유: Vue.js 관련 라이브러리가 없을 때 일반 라이브러리를 결합할 수 있어야 함
    • 종류
      1. 차트
      2. 데이트 피커
      3. 테이블 라이브러리
      4. 스피너
      5. etc…

14.2 차트 라이브러리 설치 및 차트 그리기

프로젝트 폴더 세팅


vue create vue-chart
# vue 2 default 선택
cd vue-chart
yarn serve

vue-cli 2점대 버전과 달라진점은 vue create <filepath> 명령어로 vue init ~~npm i 명령어를 모두 실행한다는 것이다.

chart.js 라이브러리 설치


npm i chart.js
# OR
yarn add chart.js

chart.js 강의는 2.7.3 버전.. 현재 2021년 10월 12일 기준 3.5.1 버전.. 에러



import Chart from 'chart.js';


2점대 버전에선 위와 같이 import해오는 방식이었나봄.
그런데 위와 같이 작성하면..


Uncaught Error: "bar" is not a registered controller.

위와 같은 에러가 뜸.

에러 해결책



import { Chart, registerables } from 'chart.js';
Chart.register(...registerables);


3점대 버전에선 위와 같이 import하는게 속편한듯.

Note

import { Chart, registerables } from 'chart.js';

위와 같이 import해올때 해당 라이브러리, chart.jspackage.json의 데브디팬던시든 디펜던시든 기록되어있다면, node_modules 폴더에서 찾아온다.
그렇지않으면 현재 경로에서 상대경로로 찾아온다.

그런데 그동안 봐온 결과생각하면 맨 앞에 @가 붙을 경우는 절대경로로 찾아오는 듯?
맞나?
아직 제대로 확인은 안해봄.

chart.js 코드 적용

document.getElementById()DOM에 요소가 등록된 다음에 작동해야될 코드이므로
mounted에 코드를 작성하자.



<template>
  <div>
    <h1>Chart.js</h1>
    <canvas id="myChart" width="400" height="400"></canvas>
  </div>
</template>

<script>
import { Chart, registerables } from 'chart.js';
Chart.register(...registerables);

export default {
  // 컴포넌트 속성 && 인스턴스 옵션
  name: 'App',
  mounted() {
    const ctx = document.getElementById('myChart');
    new Chart(ctx, {
      type: 'bar',
      data: {
        labels: ['Red', 'Blue', 'Yellow', 'Green', 'Purple', 'Orange'],
        datasets: [{
          label: '# of Votes',
          data: [12, 19, 3, 5, 2, 3],
          backgroundColor: [
            'rgba(255, 99, 132, 0.2)',
            'rgba(54, 162, 235, 0.2)',
            'rgba(255, 206, 86, 0.2)',
            'rgba(75, 192, 192, 0.2)',
            'rgba(153, 102, 255, 0.2)',
            'rgba(255, 159, 64, 0.2)'
          ],
          borderColor: [
            'rgba(255, 99, 132, 1)',
            'rgba(54, 162, 235, 1)',
            'rgba(255, 206, 86, 1)',
            'rgba(75, 192, 192, 1)',
            'rgba(153, 102, 255, 1)',
            'rgba(255, 159, 64, 1)'
          ],
          borderWidth: 1
        }]
      },
      options: {
        scales: {
          y: {
            beginAtZero: true
          }
        }
      }
    });
  },
}
</script>

<style>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>


Note
  1. 차트 라이브러리 NPM으로 설치
  2. 설치된 라이브러리를 importApp.vue로 불러옴
  3. mounted 라이프 사이클 훅에 차트 적용

14.3 BarChart 컴포넌트화 작업

  1. 차트 라이브러리 NPM으로 설치
  2. 설치된 라이브러리를 importApp.vue로 불러옴
  3. mounted 라이프 사이클 훅에 차트 적용
  4. 차트를 컴포넌트화 <- 현재 여기
  5. 컴포넌트의 플러그인화
  6. 컴포넌트 통신을 이용한 차트 컴포넌트 기능 결합

14.4 [실습] LineChart 실습 안내

14.5 [실습] LineChart 제작 및 차트 충돌 문제 해결

id값 일치하는지 아닌지 확인!!!
겹치는 요소가 있다면 오작동 또는 에러 발생함.

14.6 Vue에서 DOM을 접근하는 방법인 ref 속성 소개



<div id="app"></div>




// 자바스크립트 DOM 선택
document.getElementById('app');
document.querySelector('#app');

// 제이쿼리 DOM 선택
$('#app');

// vue DOM 선택
this.$refs.app;


ref 속성의 장점

reference 속성은 각각의 컴포넌트에서만 접근할 수 있는 접근자이기 때문에, id로 했을 땐 서로 겹치면 충돌 에러가 발생했었잖아요?
ref 속성을 통해 접근하면 그런일이 발생하지 않습니다.
에러 없는 코딩을 할 수 있습니다.

14.7 Vue.js 플러그인 소개 및 차트 플러그인 제작

  1. 차트 라이브러리 NPM으로 설치
  2. 설치된 라이브러리를 importApp.vue로 불러옴
  3. mounted 라이프 사이클 훅에 차트 적용
  4. 차트를 컴포넌트화
  5. 컴포넌트의 플러그인화 <- 현재 여기
  6. 컴포넌트 통신을 이용한 차트 컴포넌트 기능 결합

BarChart, LineChart보시면



import Chart from 'chart.js';


위와 같이 chart.js 라이브러리를 컴포넌트마다 불러옵니다.
이는 불필요한 로직과 코드가 발생하는 것입니다.
그랬을 때 이 라이브러리를 전부 다 플러그인으로 모듈화 할 수 있습니다.

14.8 결합력 높은 차트 컴포넌트 모듈 제작 방법

  1. 차트 라이브러리 NPM으로 설치
  2. 설치된 라이브러리를 importApp.vue로 불러옴
  3. mounted 라이프 사이클 훅에 차트 적용 (ref 속성)
  4. 차트를 컴포넌트화
  5. 컴포넌트의 플러그인화
  6. 컴포넌트 통신을 이용한 차트 컴포넌트 기능 결합 <- 현재 여기

보통 코드를 작성하다보면 chart 컴포넌트를 사용한 컴포넌트에서 아래와 같이 데이터를 불러오게끔 짤 확률이 크다



<template>
  <div>
    <h1>Chart.js</h1>
    <bar-chart></bar-chart>
    <line-chart></line-chart>
  </div>
</template>

<script>
import BarChart from "./components/BarChart";
import LineChart from "./components/LineChart";

export default {
  // 컴포넌트 속성 && 인스턴스 옵션
  name: 'App',
  components: {
    BarChart,
    LineChart
  },
  data() {
    return {
      chartDataSet: [],
    }
  },
  created() {
    axios.get('charts/line/1')
      .then(response => this.chartDataSet = response.data)
      .catch(error => console.log(error))
  },
}
</script>

<style>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>


위와 같이 하위 컴포넌트에선 데이터를 내려받도록(props) 하는 구조가 좋다.
그리고 하위 컴포넌트에서 eventemit해서 상위 컴포넌트에서 받게하는 구조가 좋다.

  • 14.8 결합력 높은 차트 컴포넌트 모듈 제작 방법
  • vue-chartjs - npm

    vue에서 사용하기 쉽게 만든 chart.js(wrapping 해놓은 것)
    플러그인화 시키는 것과 비슷한 원리로 만드는 것.
    따라서 vue-chartjs 처럼 vue를 위한 특정 라이브러리가 없더라도 일반 라이브러리로도 충분히 저희가 접근했던 방식으로

    1. 컴포넌트화를 하고
    2. 플러그인을 만들고
    3. 컴포넌트 통신을 이용해서 결합도 매끈하게 할 수 있습니다.

위와 같이 3가지를 잘하시면 vue-chartjs를 만드실 수 있는겁니다.
위와 같은 방식으로 API도 작성하시고 그러셔서 오픈소스에 충분히 기여하실 수 있습니다.