Skip to content
This repository has been archived by the owner on Aug 16, 2023. It is now read-only.

Latest commit

ย 

History

History
649 lines (471 loc) ยท 28 KB

README-KR.md

File metadata and controls

649 lines (471 loc) ยท 28 KB

Vue.js ์ปดํฌ๋„ŒํŠธ ์Šคํƒ€์ผ ๊ฐ€์ด๋“œ

๋ฒˆ์—ญ

๋ชฉ์ 

์ด ๊ฐ€์ด๋“œ๋Š” Vue.js ์ฝ”๋“œ๋ฅผ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ฒด๊ณ„์ ์œผ๋กœ ๊ตฌ์„ฑํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

  • ๊ฐœ๋ฐœ์ž ํ˜น์€ ํŒ€์›์ด ์‰ฝ๊ฒŒ ์ดํ•ดํ•˜๊ณ  ์ฐพ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • IDE๊ฐ€ ์‰ฝ๊ฒŒ ์ฝ”๋“œ๋ฅผ ํ•ด์„ํ•˜๊ณ  ๋„์›€์„ ์ค„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ์ด๋ฏธ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ๋Š” ๋นŒ๋“œ ํˆด์„ ์žฌ์‚ฌ์šฉํ•˜๊ธฐ ์‰ฝ๊ฒŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ์‰ฝ๊ฒŒ ์บ์‹ฑ์ด ๊ฐ€๋Šฅํ•˜๊ณ  ์ฝ”๋“œ๋ฅผ ๋ถ„๋ฆฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด ๊ฐ€์ด๋“œ๋Š” De voorhoede๊ฐ€ ์ž‘์„ฑํ•œ RiotJS ์Šคํƒ€์ผ ๊ฐ€์ด๋“œ์—์„œ ์˜๊ฐ์„ ์–ป์—ˆ์Šต๋‹ˆ๋‹ค.

๋ชฉ์ฐจ

๋ชจ๋“ˆ ๊ธฐ๋ฐ˜ ๊ฐœ๋ฐœ

ํ•ญ์ƒ ํ•œ ๊ฐ€์ง€ ์ผ์„ ์ž˜ ์ˆ˜ํ–‰ํ•˜๋Š” ์ž‘์€ ๋ชจ๋“ˆ๋“ค๋กœ ๋‹น์‹ ์˜ ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๊ตฌ์„ฑํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค.

๋ชจ๋“ˆ์€ ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ๋…๋ฆฝ์ ์ธ ํ•œ ๋ถ€๋ถ„ ์ž…๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์„œ Vue.js๋Š” ๋ทฐ-๋กœ์ง ๋ชจ๋“ˆ์„ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ๋„๋ก ํŠน๋ณ„ํžˆ ๋””์ž์ธ๋œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ž…๋‹ˆ๋‹ค.

์™œ ๊ทธ๋ ‡๊ฒŒ ํ•˜๋‚˜์š”?

์ž‘์€ ๋ชจ๋“ˆ์€ ๋ฐฐ์šฐ๊ณ , ์ดํ•ดํ•˜๊ณ , ์œ ์ง€ํ•˜๊ณ , ์žฌ์‚ฌ์šฉ๊ณผ ๋””๋ฒ„๊ทธํ•˜๋Š” ๊ฒƒ์ด ๋” ์‰ฝ์Šต๋‹ˆ๋‹ค. ๋‹น์‹ ์ด ๋‹ค๋ฅธ ๊ฐœ๋ฐœ์ž์™€ ํ˜‘์—…ํ•˜๋Š” ๊ฒฝ์šฐ์—๋„์š”.

์–ด๋–ป๊ฒŒ ํ•˜๋‚˜์š”?

๊ฐ Vue ์ปดํฌ๋„ŒํŠธ(๋ชจ๋“ˆ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค)๋Š” FIRST์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค: Focused (๋‹จ์ผ ์ฑ…์ž„ ์›์น™), Independent(๋…๋ฆฝ์ ์ธ), Reusable(์žฌ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ), Small(์ž‘์€), Testable(ํ…Œ์ŠคํŠธ ๊ฐ€๋Šฅํ•œ).

์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋„ˆ๋ฌด ๋งŽ๊ฑฐ๋‚˜ ๋„ˆ๋ฌด ์ปค์ง€๋ฉด ํ•œ ๊ฐ€์ง€ ์ผ์„ ํ•˜๋Š” ์ž‘์€ ์ปดํฌ๋„ŒํŠธ๋กœ ๋‚˜๋ˆ ์„œ ๊ตฌ์„ฑํ•ฉ๋‹ˆ๋‹ค. ์ผ๋ฐ˜์ ์œผ๋กœ ๊ฐ ์ปดํฌ๋„ŒํŠธ ํŒŒ์ผ์„ 100๋ผ์ธ ๋ฏธ๋งŒ์œผ๋กœ ์œ ์ง€ํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค. ๋˜ํ•œ, Vue ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋…๋ฆฝ์ ์œผ๋กœ ์ž‘๋™ํ•˜๋Š”์ง€ ํ™•์ธํ•˜์„ธ์š”. ์˜ˆ๋ฅผ ๋“ค๋ฉด ๋…๋ฆฝ ์‹คํ–‰์ด ๊ฐ€๋Šฅํ•œ ๋ฐ๋ชจ๋ฅผ ๋งŒ๋“œ๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

โ†‘ ๋ชฉ์ฐจ๋กœ ๋Œ์•„๊ฐ€๊ธฐ

Vue ์ปดํฌ๋„ŒํŠธ ์ด๋ฆ„

๊ฐ ์ปดํฌ๋„ŒํŠธ์˜ ์ด๋ฆ„์€ ๋‹ค์Œ๊ณผ ๊ฐ™์•„์•ผํ•ฉ๋‹ˆ๋‹ค.

  • ์˜๋ฏธ์žˆ๋Š”: ์ง€๋‚˜์น˜๊ฒŒ ์ถ”์ƒ์ ์ด๊ฑฐ๋‚˜ ๊ตฌ์ฒด์ ์ด๋ฉด ์•ˆ๋ฉ๋‹ˆ๋‹ค.
  • ์งง์€: 2~3๋‹จ์–ด์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค.
  • ๋ฐœ์Œ ๊ฐ€๋Šฅํ•œ: ์šฐ๋ฆฌ๋Š” ์ปดํฌ๋„ŒํŠธ์— ๋Œ€ํ•ด ์ด์•ผ๊ธฐํ•  ์ˆ˜ ์žˆ์–ด์•ผํ•ฉ๋‹ˆ๋‹ค.

๋˜ํ•œ, Vue ์ปดํฌ๋„ŒํŠธ ์ด๋ฆ„์€ ๋‹ค์Œ๊ณผ ๊ฐ™์•„์•ผํ•ฉ๋‹ˆ๋‹ค.

  • ์‚ฌ์šฉ์ž ์ •์˜ ์—˜๋ฆฌ๋จผํŠธ ์ŠคํŽ™์„ ์ค€์ˆ˜ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค: ํ•˜์ดํ”ˆ(-)์„ ํฌํ•จํ•˜๊ณ , ์˜ˆ์•ฝ์–ด๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์•ˆ๋ฉ๋‹ˆ๋‹ค.
  • app- ๋„ค์ž„์ŠคํŽ˜์ด์Šค: ๋งค์šฐ ์ผ๋ฐ˜์ ์ด๊ณ  ํ•œ ๋‹จ์–ด๋ผ๋ฉด ๋‹ค๋ฅธ ํ”„๋กœ์ ํŠธ์—์„œ ์‰ฝ๊ฒŒ ์žฌ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์™œ ๊ทธ๋ ‡๊ฒŒ ํ•˜๋‚˜์š”?

  • ์ด๋ฆ„์€ ์ปดํฌ๋„ŒํŠธ๋ผ๋ฆฌ ํ†ต์‹ ํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ ์ปดํฌ๋„ŒํŠธ ์ด๋ฆ„์€ ์งง๊ณ , ์˜๋ฏธ์žˆ์œผ๋ฉด์„œ ๋ฐœ์Œ ํ•  ์ˆ˜ ์žˆ์–ด์•ผํ•ฉ๋‹ˆ๋‹ค.

์–ด๋–ป๊ฒŒ ํ•˜๋‚˜์š”?

<!-- ๊ถŒ์žฅํ•ฉ๋‹ˆ๋‹ค -->
<app-header></app-header>
<user-list></user-list>
<range-slider></range-slider>

<!-- ํ”ผํ•˜์„ธ์š”! -->
<btn-group></btn-group> <!-- ์งง์ง€๋งŒ ๋ฐœ์Œํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. `button-group`์œผ๋กœ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค. -->
<ui-slider></ui-slider> <!-- ๋ชจ๋“  ์ปดํฌ๋„ŒํŠธ๋Š” UI ์—˜๋ฆฌ๋จผํŠธ์ด๊ธฐ ๋•Œ๋ฌธ์— ์˜๋ฏธ๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. -->
<slider></slider> <!-- ์‚ฌ์šฉ์ž ์ •์˜ ์—˜๋ฆฌ๋จผํŠธ ์ŠคํŽ™์„ ์ค€์ˆ˜ํ•˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค. -->

โ†‘ ๋ชฉ์ฐจ๋กœ ๋Œ์•„๊ฐ€๊ธฐ

์ปดํฌ๋„ŒํŠธ ํ‘œํ˜„์‹์„ ๋‹จ์ˆœํ•˜๊ฒŒ ์‚ฌ์šฉํ•˜๊ธฐ

Vue.js์˜ ์ธ๋ผ์ธ ํ‘œํ˜„์‹์€ 100% ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์ž…๋‹ˆ๋‹ค. ์ด ๊ธฐ๋Šฅ์€ ๋งค์šฐ ๊ฐ•๋ ฅํ•˜์ง€๋งŒ ์ž˜๋ชป ์‚ฌ์šฉํ•˜๋ฉด ๋งค์šฐ ๋ณต์žกํ•ด์งˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ํ‘œํ˜„์‹์„ ๋‹จ์ˆœํ•˜๊ฒŒ ์‚ฌ์šฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

์™œ ๊ทธ๋ ‡๊ฒŒ ํ•˜๋‚˜์š”?

  • ๋ณต์žกํ•œ ์ธ๋ผ์ธ ํ‘œํ˜„์‹์€ ์ฝ๊ธฐ ์–ด๋ ต์Šต๋‹ˆ๋‹ค.
  • ์ธ๋ผ์ธ ํ‘œํ˜„์‹์€ ๋‹ค๋ฅธ ๊ณณ์—์„œ ์žฌ์‚ฌ์šฉํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ๊ทธ๋ ‡๊ธฐ ๋•Œ๋ฌธ์— ์ค‘๋ณต ์ฝ”๋“œ๊ฐ€ ์ƒ๊ธธ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • IDE๋Š” ๋Œ€๋ถ€๋ถ„ ํ‘œํ˜„์‹ ๋ฌธ๋ฒ•์„ ์ง€์›ํ•˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— IDE์—์„œ ์ž๋™์™„์„ฑ ํ˜น์€ ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ๋ฅผ ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

์–ด๋–ป๊ฒŒ ํ•˜๋‚˜์š”?

๋งŒ์•ฝ ํ‘œํ˜„์‹์ด ๋„ˆ๋ฌด ๋ณต์žกํ•˜๋‹ค๋ฉด methods ํ˜น์€ computed ์†์„ฑ์œผ๋กœ ์˜ฎ๊ธฐ์„ธ์š”!

<!-- ๊ถŒ์žฅํ•ฉ๋‹ˆ๋‹ค -->
<template>
  <h1>
    {{ `${year}-${month}` }}
  </h1>
</template>
<script type="text/javascript">
  export default {
    computed: {
      month() {
        return this.twoDigits((new Date()).getUTCMonth() + 1);
      },
      year() {
        return (new Date()).getUTCFullYear();
      }
    },
    methods: {
      twoDigits(num) {
        return ('0' + num).slice(-2);
      }
    },
  };
</script>

<!-- ํ”ผํ•˜์„ธ์š”! -->
<template>
  <h1>
    {{ `${(new Date()).getUTCFullYear()}-${('0' + ((new Date()).getUTCMonth()+1)).slice(-2)}` }}
  </h1>
</template>

โ†‘ ๋ชฉ์ฐจ๋กœ ๋Œ์•„๊ฐ€๊ธฐ

์ปดํฌ๋„ŒํŠธ props๋ฅผ ์›์‹œ ์ž๋ฃŒํ˜•์œผ๋กœ ์‚ฌ์šฉํ•˜๊ธฐ

Vue.js๋Š” ๋‹ค์–‘ํ•œ ์†์„ฑ์„ ํ†ตํ•ด ๋ณต์žกํ•œ JavaScript ๊ฐ์ฒด๋ฅผ ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ์ง€๋งŒ ์ปดํฌ๋„ŒํŠธ ์˜ต์…˜์„ ๊ฐ€๋Šฅํ•œ ์›์‹œ ์ž๋ฃŒํ˜•์œผ๋กœ ์œ ์ง€ํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค. ์ฆ‰, JavaScript ์›์‹œ ๊ฐ’ (string, number, boolean) ๋ฐ ํ•จ์ˆ˜๋งŒ์„ ์‚ฌ์šฉํ•˜๊ณ  ๋ณต์žกํ•œ Object๋Š” ํ”ผํ•˜๋Š”๊ฒŒ ์ข‹์Šต๋‹ˆ๋‹ค.

์™œ ๊ทธ๋ ‡๊ฒŒ ํ•˜๋‚˜์š”?

  • ๊ฐœ๋ณ„์ ์œผ๋กœ prop ์†์„ฑ์„ ์‚ฌ์šฉํ•จ์œผ๋กœ์จ ์ปดํฌ๋„ŒํŠธ๋Š” ๋ช…ํ™•ํ•œ API๋ฅผ ๊ฐ€์ง‘๋‹ˆ๋‹ค.
  • ์›์‹œ ์ž๋ฃŒํ˜•๊ณผ ํ•จ์ˆ˜๋งŒ์„ props ๊ฐ’์œผ๋กœ ์‚ฌ์šฉํ•˜๋ฉด ์ปดํฌ๋„ŒํŠธ API๊ฐ€ ๋„ค์ดํ‹ฐ๋ธŒ HTML(5) ์—˜๋ฆฌ๋จผํŠธ์˜ API์™€ ์œ ์‚ฌํ•ด์ง‘๋‹ˆ๋‹ค.
  • ๊ฐœ๋ณ„์ ์œผ๋กœ prop ์†์„ฑ์„ ์‚ฌ์šฉํ•˜๋ฉด ๋‹ค๋ฅธ ๊ฐœ๋ฐœ์ž๊ฐ€ ์ปดํฌ๋„ŒํŠธ ์ธ์Šคํ„ด์Šค๋กœ ์ „๋‹ฌ๋˜๋Š” ๋‚ด์šฉ์„ ์‰ฝ๊ฒŒ ์ดํ•ดํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ๋ณต์žกํ•œ Object๋ฅผ ์ „๋‹ฌํ•  ๋•Œ ์ „๋‹ฌํ•œ Object์˜ ์†์„ฑ๊ณผ ๋ฉ”์„œ๋“œ๊ฐ€ ์‹ค์ œ๋กœ ์‚ฌ์šฉ์ž ์ •์˜ ์ปดํฌ๋„ŒํŠธ์—์„œ ์‚ฌ์šฉ๋˜๋Š”์ง€ ๋ถ„๋ช…ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์ด๋ ‡๊ฒŒ ์‚ฌ์šฉํ•˜๋ฉด ์ฝ”๋“œ๋ฅผ ๋ฆฌํŒฉํ† ๋งํ•˜๊ธฐ๊ฐ€ ์–ด๋ ค์›Œ์ง€๊ณ  ์ฝ”๋“œ๊ฐ€ ๋”๋Ÿฌ์›Œ ์งˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์–ด๋–ป๊ฒŒ ํ•˜๋‚˜์š”?

์›์‹œ ์ž๋ฃŒํ˜• ํ˜น์€ ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ props ์ปดํฌ๋„ŒํŠธ ์†์„ฑ์„ ์‚ฌ์šฉํ•˜์„ธ์š”.

<!-- ๊ถŒ์žฅํ•ฉ๋‹ˆ๋‹ค -->
<range-slider
  :values="[10, 20]"
  min="0"
  max="100"
  step="5"
  :on-slide="updateInputs"
  :on-end="updateResults">
</range-slider>

<!-- ํ”ผํ•˜์„ธ์š”! -->
<range-slider :config="complexConfigObject"></range-slider>

โ†‘ ๋ชฉ์ฐจ๋กœ ๋Œ์•„๊ฐ€๊ธฐ

์ปดํฌ๋„ŒํŠธ props๋ฅผ ์ž˜ ์‚ฌ์šฉํ•˜๊ธฐ

Vue.js์—์„œ๋Š” ์ปดํฌ๋„ŒํŠธ props๊ฐ€ ๋‹น์‹ ์˜ API ์ž…๋‹ˆ๋‹ค. ๊ฐ•๋ ฅํ•˜๊ณ  ์˜ˆ์ธก๊ฐ€๋Šฅํ•œ API๋ฅผ ๋งŒ๋“ค๋ฉด ๋‹ค๋ฅธ ๊ฐœ๋ฐœ์ž๊ฐ€ ์ปดํฌ๋„ŒํŠธ๋ฅผ ์‰ฝ๊ฒŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ปดํฌ๋„ŒํŠธ props๋Š” ์‚ฌ์šฉ์ž ์ •์˜ HTML ์–ดํŠธ๋ฆฌ๋ทฐํŠธ์— ์˜ํ•ด ์ „๋‹ฌ๋ฉ๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ์–ดํŠธ๋ฆฌ๋ทฐํŠธ์˜ ๊ฐ’์€ Vue.js ์ผ๋ฐ˜ ๋ฌธ์ž์—ด(:attr="value" ๋˜๋Š” v-bind:attr="value")์ด๊ฑฐ๋‚˜ ๋ˆ„๋ฝ๋ฉ๋‹ˆ๋‹ค. ๋‹น์‹ ์€ ์ด๋Ÿฌํ•œ ๊ฒฝ์šฐ๋ฅผ ๊ณ ๋ คํ•˜์—ฌ ๋‹น์‹ ์˜ ์ปดํฌ๋„ŒํŠธ props๋ฅผ ์ž˜ ์‚ฌ์šฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

์™œ ๊ทธ๋ ‡๊ฒŒ ํ•˜๋‚˜์š”?

์ปดํฌ๋„ŒํŠธ props๋ฅผ ์ž˜ ์‚ฌ์šฉํ•˜๋ฉด ๋‹น์‹ ์˜ ์ปดํฌ๋„ŒํŠธ๋Š” ํ•ญ์ƒ ์ž‘๋™ํ•  ๊ฒƒ ์ž…๋‹ˆ๋‹ค(๋ฐฉ์–ด์  ํ”„๋กœ๊ทธ๋ž˜๋ฐ). ๋‚˜์ค‘์— ๋‹ค๋ฅธ ๊ฐœ๋ฐœ์ž๊ฐ€ ๋‹น์‹ ์ด ์ƒ๊ฐํ•˜์ง€ ๋ชปํ•œ ๋ฐฉ๋ฒ•์œผ๋กœ ์ปดํฌ๋„ŒํŠธ๋ฅผ ์‚ฌ์šฉํ•˜๋”๋ผ๋„ ๋งˆ์ฐฌ๊ฐ€์ง€ ์ž…๋‹ˆ๋‹ค.

์–ด๋–ป๊ฒŒ ํ•˜๋‚˜์š”?

  • props์— ๊ธฐ๋ณธ ๊ฐ’์„ ์‚ฌ์šฉํ•˜์„ธ์š”.
  • ๊ฐ’์„ validate ํ•˜๊ธฐ์œ„ํ•ด type ์˜ต์…˜์„ ์‚ฌ์šฉํ•˜์„ธ์š”. [1*]
  • ์ค‘๋ณต๋œ props๊ฐ€ ์žˆ๋Š”์ง€ ํ™•์ธํ•˜์„ธ์š”.
<template>
  <input type="range" v-model="value" :max="max" :min="min">
</template>
<script type="text/javascript">
  export default {
    props: {
      max: {
        type: Number, // [1*] 'max' prop์€ Number๋กœ๋งŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
        default() { return 10; },
      },
      min: {
        type: Number,
        default() { return 0; },
      },
      value: {
        type: Number,
        default() { return 4; },
      },
    },
  };
</script>

โ†‘ ๋ชฉ์ฐจ๋กœ ๋Œ์•„๊ฐ€๊ธฐ

this๋ฅผ component์— ์ง€์ •ํ•˜๊ธฐ

Vue.js ์ปดํฌ๋„ŒํŠธ ์—˜๋ฆฌ๋จผํŠธ์˜ ์ปจํ…์ŠคํŠธ ๋‚ด์—์„œ this๋Š” ์ปดํฌ๋„ŒํŠธ ์ธ์Šคํ„ด์Šค์— ๋ฐ”์ธ๋”ฉ๋ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋ฏ€๋กœ ๋‹ค๋ฅธ ์ปจํ…์ŠคํŠธ์—์„œ ๊ทธ๊ฒƒ์„ ์ฐธ์กฐํ•  ํ•„์š”๊ฐ€ ์žˆ์„ ๋•Œ this๋ฅผ component๋กœ์จ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

๋‹ค๋ฅธ ๋ง๋กœํ•˜๋ฉด ๋”์ด์ƒ const self = this;์™€ ๊ฐ™์€ ์ฝ”๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ๋งˆ์„ธ์š”. Vue ์ปดํฌ๋„ŒํŠธ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์•ˆ์ „ํ•ฉ๋‹ˆ๋‹ค.

์™œ ๊ทธ๋ ‡๊ฒŒ ํ•˜๋‚˜์š”?

  • this๋ฅผ component๋ผ๋Š” ๋ณ€์ˆ˜์— ์ง€์ •๋จ์œผ๋กœ์จ ๊ฐœ๋ฐœ์ž์—๊ฒŒ ๋ณ€์ˆ˜๊ฐ€ ์‚ฌ์šฉ๋˜๋Š” ๊ณณ๋งˆ๋‹ค ์ปดํฌ๋„ŒํŠธ ์ธ์Šคํ„ด์Šค์— ๋ฐ”์ธ๋”ฉ๋˜์—ˆ๋‹ค๋Š” ๊ฒƒ์„ ์•Œ๋ ค์ค๋‹ˆ๋‹ค.

์–ด๋–ป๊ฒŒ ํ•˜๋‚˜์š”?

<script type="text/javascript">
export default {
  methods: {
    hello() {
      return 'hello';
    },
    printHello() {
      console.log(this.hello());
    },
  },
};
</script>

<!-- ํ”ผํ•˜์„ธ์š”! -->
<script type="text/javascript">
export default {
  methods: {
    hello() {
      return 'hello';
    },
    printHello() {
      const self = this; // ๋ถˆํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.
      console.log(self.hello());
    },
  },
};
</script>

โ†‘ ๋ชฉ์ฐจ๋กœ ๋Œ์•„๊ฐ€๊ธฐ

์ปดํฌ๋„ŒํŠธ ๊ตฌ์กฐ

์ƒ๊ฐ์˜ ์ˆœ์„œ๋ฅผ ๋”ฐ๋ผ ์ปดํฌ๋„ŒํŠธ ๊ตฌ์กฐ๋ฅผ ๋งŒ๋“ค์–ด๋ณด์„ธ์š”. ์–ด๋–ป๊ฒŒ ํ•˜๋‚˜์š”?๋ฅผ ์ฐธ๊ณ ํ•˜์„ธ์š”.

์™œ ๊ทธ๋ ‡๊ฒŒ ํ•˜๋‚˜์š”?

  • ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋ช…ํ™•ํ•˜๊ณ  ๊ทธ๋ฃนํ™”ํ•˜์—ฌ exportํ•˜๋ฉด ๊ฐœ๋ฐœ์ž๊ฐ€ ์‰ฝ๊ฒŒ ํ‘œ์ค€์ ์ธ ์ฝ”๋“œ์— ๋Œ€ํ•ด์„œ ์ดํ•ดํ•˜๊ณ  ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ์†์„ฑ, ๋ฐ์ดํ„ฐ, ๊ณ„์‚ฐ๋œ ์†์„ฑ, ๊ฐ์‹œ์ž ๋ฐ ๋ฉ”์„œ๋“œ๋ฅผ ์•ŒํŒŒ๋ฒณ์ˆœ์œผ๋กœ ํ‘œ์‹œํ•˜๋ฉด ์‰ฝ๊ฒŒ ์ฐพ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ๋‹ค์‹œ๋งํ•ด, ๊ทธ๋ฃนํ™”ํ•˜๋ฉด ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋” ์‰ฝ๊ฒŒ ์ฝ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. (name; extends; props; data์™€ computed; components; watch์™€ method; ๋ผ์ดํ”„์‚ฌ์ดํด ๋ฉ”์„œ๋“œ ๋“ฑ)
  • name ์†์„ฑ์„ ์‚ฌ์šฉํ•˜์„ธ์š”. vue devtools๊ณผ ๊ทธ ์†์„ฑ์„ ์‚ฌ์šฉํ•˜๋ฉด ๊ฐœ๋ฐœ/ํ…Œ์ŠคํŠธ๊ฐ€ ๋” ์‰ฌ์›Œ์ง‘๋‹ˆ๋‹ค.
  • BEM ๋˜๋Š” rscss์™€ ๊ฐ™์€ CSS ๋„ค์ด๋ฐ ๊ทœ์น™์„ ์‚ฌ์šฉํ•˜์„ธ์š”. - ์ž์„ธํžˆ ๋ณด๊ธฐ
  • Vue.js ์ž‘์„ฑ์ž(Evan You)๊ฐ€ ๊ถŒ์žฅํ•˜๋Š” ํ…œํ”Œ๋ฆฟ ์Šคํฌ๋ฆฝํŠธ ์Šคํƒ€์ผ์ธ .vue ํŒŒ์ผ์„ ์‚ฌ์šฉํ•˜์‹ญ์‹œ์˜ค.

์–ด๋–ป๊ฒŒ ํ•˜๋‚˜์š”?

์•„๋ž˜ ์ปดํฌ๋„ŒํŠธ ๊ตฌ์กฐ๋ฅผ ์ฐธ๊ณ ํ•˜์„ธ์š”.

<template lang="html">
  <div class="Ranger__Wrapper">
    <!-- ... -->
  </div>
</template>

<script type="text/javascript">
  export default {
    // ์ด๋ฆ„ ์ ๋Š” ๊ฒƒ์„ ์žŠ์ง€๋งˆ์„ธ์š”
    name: 'RangeSlider',
    // compose new components
    extends: {},
    // ์ปดํฌ๋„ŒํŠธ ์–ดํŠธ๋ฆฌ๋ทฐํŠธ ๊ทธ๋ฃน
    props: {
      bar: {}, // ์•ŒํŒŒ๋ฒณ์ˆœ์œผ๋กœ ์ •๋ ฌํ•ฉ๋‹ˆ๋‹ค
      foo: {},
      fooBar: {},
    },
    // ์ปดํฌ๋„ŒํŠธ ๋ณ€์ˆ˜ ๊ทธ๋ฃน
    data() {},
    computed: {},
    // ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋‹ค๋ฅธ ์ปดํฌ๋„ŒํŠธ๋ฅผ ์‚ฌ์šฉํ•  ๊ฒฝ์šฐ
    components: {},
    // ์ปดํฌ๋„ŒํŠธ ๋ฉ”์„œ๋“œ ๊ทธ๋ฃน
    watch: {},
    methods: {},
    // ์ปดํฌ๋„ŒํŠธ ๋ผ์ดํ”„์‚ฌ์ดํด ๋ฉ”์„œ๋“œ ๊ทธ๋ฃน
    beforeCreate() {},
    mounted() {},
};
</script>

<style scoped>
  .Ranger__Wrapper { /* ... */ }
</style>

โ†‘ ๋ชฉ์ฐจ๋กœ ๋Œ์•„๊ฐ€๊ธฐ

์ปดํฌ๋„ŒํŠธ ์ด๋ฒคํŠธ ์ด๋ฆ„

Vue.js๋Š” ๋ชจ๋“  Vue ํ•ธ๋“ค๋Ÿฌ ํ•จ์ˆ˜๋ฅผ ์ œ๊ณตํ•˜๋ฉฐ ํ‘œํ˜„์‹์€ ViewModel์— ์—„๊ฒฉํ•˜๊ฒŒ ๋ฐ”์ธ๋”ฉ๋ฉ๋‹ˆ๋‹ค. ๊ฐ ์ปดํฌ๋„ŒํŠธ ์ด๋ฒคํŠธ๋Š” ๊ฐœ๋ฐœ ๋„์ค‘ ๋ฌธ์ œ๋ฅผ ํ”ผํ•  ์ˆ˜์žˆ๋Š” ์ข‹์€ ๋„ค์ด๋ฐ ์Šคํƒ€์ผ์„ ๋”ฐ๋ผ์•ผํ•ฉ๋‹ˆ๋‹ค. ์•„๋ž˜ **์™œ ๊ทธ๋ ‡๊ฒŒ ํ•˜๋‚˜์š”?**๋ฅผ ์ฐธ์กฐํ•˜์‹ญ์‹œ์˜ค.

์™œ ๊ทธ๋ ‡๊ฒŒ ํ•˜๋‚˜์š”?

  • ๊ฐœ๋ฐœ์ž๊ฐ€ ์ด๋ฒคํŠธ ์ด๋ฆ„์„ ์ž์œ ๋กญ๊ฒŒ ์ž‘์„ฑํ•  ๊ฒฝ์šฐ ํ˜ผ๋ž€์„ ๋ฐœ์ƒ์‹œํ‚ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ์ด๋ฒคํŠธ ์ด๋ฆ„์„ ์ž์œ ๋กญ๊ฒŒ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— DOM ํ…œํ”Œ๋ฆฟ์˜ ๋น„ ํ˜ธํ™˜์„ฑ์ด ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์–ด๋–ป๊ฒŒ ํ•˜๋‚˜์š”?

  • ์ด๋ฒคํŠธ ์ด๋ฆ„์€ kebab-cased์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค(ํ•˜์ดํ”ˆ์œผ๋กœ ๊ตฌ๋ถ„).
  • ํŠน๋ณ„ํ•œ ์ด๋ฒคํŠธ ์ด๋ฆ„์€ upload-success, upload-error ๋˜๋Š” dropzone-upload-success, dropzone-upload-error(๋งŒ์•ฝ ๋ฒ”์œ„๊ฐ€ ์ง€์ •๋œ ์ ‘๋‘์–ด๊ฐ€ ํ•„์š”ํ•˜๋‹ค๋ฉด)์™€ ๊ฐ™์ด ์™ธ๋ถ€ ์„ธ๊ณ„์— ๊ด€์‹ฌ์„ ๊ฐ€์งˆ ์ˆ˜ ์žˆ๋Š” ์ปดํฌ๋„ŒํŠธ์˜ ํŠน๋ณ„ํ•œ ๋™์ž‘์— ๋Œ€ํ•ด ์‹คํ–‰๋˜์•ผ ํ•ฉ๋‹ˆ๋‹ค.
  • ์ด๋ฒคํŠธ๋Š” ๋ถ€์ •์‚ฌ์˜ ํ˜•ํƒœ(e.g. client-api-load)์ด๊ฑฐ๋‚˜ ๋ช…์‚ฌ(e.g. drive-upload-success)์—์„œ ๋™์‚ฌ๋กœ ๋๋‚˜์•ผ ํ•ฉ๋‹ˆ๋‹ค. (์ถœ์ฒ˜)

โ†‘ ๋ชฉ์ฐจ๋กœ ๋Œ์•„๊ฐ€๊ธฐ

this.$parent ํ”ผํ•˜๊ธฐ

Vue.js๋Š” ๋ถ€๋ชจ ์ปจํ…์ŠคํŠธ์— ์ ‘๊ทผ ํ•  ์ˆ˜ ์žˆ๋Š” ์ค‘์ฒฉ ์ปดํฌ๋„ŒํŠธ๋ฅผ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ Vue ์ปดํฌ๋„ŒํŠธ ์™ธ๋ถ€์˜ ์ปจํ…์ŠคํŠธ์— ์ ‘๊ทผํ•˜๋ฉด ์ปดํฌ๋„ŒํŠธ ๊ธฐ๋ฐ˜ ๊ฐœ๋ฐœ์˜ FIRST ๊ทœ์น™์„ ์œ„๋ฐ˜ํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ this.$parent๋ฅผ ์‚ฌ์šฉ์„ ํ”ผํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค.

์™œ ๊ทธ๋ ‡๊ฒŒ ํ•˜๋‚˜์š”?

  • Vue ์ปดํฌ๋„ŒํŠธ๋Š” ๋‹ค๋ฅธ ๋ชจ๋“  ์ปดํฌ๋„ŒํŠธ์™€ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ๋…๋ฆฝ์ ์œผ๋กœ ์ž‘๋™ํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค. ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋ถ€๋ชจ์— ์ ‘๊ทผํ•ด์•ผํ•  ๊ฒฝ์šฐ ์ด ๊ทœ์น™์€ ๋ฌด๋„ˆ์ง€๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.
  • ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋ถ€๋ชจ์— ์ ‘๊ทผํ•˜๋Š” ๊ฒฝ์šฐ ๋‹ค๋ฅธ ๊ณณ์—์„œ ์žฌ์‚ฌ์šฉํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

์–ด๋–ป๊ฒŒ ํ•˜๋‚˜์š”?

  • ์–ดํŠธ๋ฆฌ๋ทฐํŠธ/ํ”„๋กœํผํ‹ฐ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ถ€๋ชจ์—์„œ ์ž์‹ ์ปดํฌ๋„ŒํŠธ๋กœ ๊ฐ’์„ ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค.
  • ์–ดํŠธ๋ฆฌ๋ทฐํŠธ ํ‘œํ˜„์‹์—์„œ ์ฝœ๋ฐฑ์„ ์‚ฌ์šฉํ•˜์—ฌ ๋ถ€๋ชจ ์ปดํฌ๋„ŒํŠธ์— ์ •์˜๋œ ๋ฉ”์†Œ๋“œ๋ฅผ ์ž์‹ ์ปดํฌ๋„ŒํŠธ๋กœ ์ „๋‹ฌํ•˜์‹ญ์‹œ์˜ค.
  • ์ž์‹ ์ปดํฌ๋„ŒํŠธ์—์„œ ์ด๋ฒคํŠธ๋ฅผ emitํ•˜์—ฌ ๋ถ€๋ชจ ์ปดํฌ๋„ŒํŠธ์—์„œ ์ด๋ฒคํŠธ๋ฅผ ๋ฐœ์ƒ์‹œํ‚ต๋‹ˆ๋‹ค.

โ†‘ ๋ชฉ์ฐจ๋กœ ๋Œ์•„๊ฐ€๊ธฐ

this.$refs๋ฅผ ์ฃผ์˜ํ•˜์—ฌ ์‚ฌ์šฉํ•˜๊ธฐ

Vue.js๋Š” ์ปดํฌ๋„ŒํŠธ๊ฐ€ ref ์–ดํŠธ๋ฆฌ๋ทฐํŠธ๋ฅผ ํ†ตํ•ด ๋‹ค๋ฅธ ์ปดํฌ๋„ŒํŠธ์™€ ๊ธฐ๋ณธ HTML ์—˜๋ฆฌ๋จผํŠธ์— ์ ‘๊ทผ ํ•  ์ˆ˜ ์žˆ๋„๋ก ์ง€์›ํ•ฉ๋‹ˆ๋‹ค. ์ด ์–ดํŠธ๋ฆฌ๋ทฐํŠธ๋Š” this.$refs๋ฅผ ํ†ตํ•ด ์ปดํฌ๋„ŒํŠธ ๋˜๋Š” DOM ์—˜๋ฆฌ๋จผํŠธ์— ์ ‘๊ทผ ํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ค๋‹ˆ๋‹ค. ๋Œ€๋ถ€๋ถ„์˜ ๊ฒฝ์šฐ this.$refs๋ฅผ ํ†ตํ•ด ๋‹ค๋ฅธ ์ปดํฌ๋„ŒํŠธ์— ์ ‘๊ทผํ•˜๋Š” ๊ฒƒ์„ ํ”ผํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ ์ž˜๋ชป๋œ ์ปดํฌ๋„ŒํŠธ API๋ฅผ ํ”ผํ•˜๊ธฐ ์œ„ํ•ด์„œ ์‚ฌ์šฉํ•  ๋•Œ ์ฃผ์˜ํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค.

์™œ ๊ทธ๋ ‡๊ฒŒ ํ•˜๋‚˜์š”?

  • Vue ์ปดํฌ๋„ŒํŠธ๋Š” ๋…๋ฆฝ์ ์œผ๋กœ ์ž‘๋™ํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค. ์ปดํฌ๋„ŒํŠธ๊ฐ€ ํ•„์š”ํ•œ ๋ชจ๋“  ์ ‘๊ทผ์„ ์ง€์›ํ•˜์ง€ ์•Š์œผ๋ฉด ์ž˜๋ชป ์„ค๊ณ„/๊ตฌํ˜„๋œ ๊ฒƒ ์ž…๋‹ˆ๋‹ค.
  • ๋Œ€๋ถ€๋ถ„์˜ ์ปดํฌ๋„ŒํŠธ๋Š” ํ”„๋กœํผํ‹ฐ์™€ ์ด๋ฒคํŠธ๊ฐ€ ์ถฉ๋ถ„ํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค.

์–ด๋–ป๊ฒŒ ํ•˜๋‚˜์š”?

  • ์ข‹์€ ์ปดํฌ๋„ŒํŠธ API๋ฅผ ์ž‘์„ฑํ•ฉ๋‹ˆ๋‹ค.
  • ํ•ญ์ƒ ์ปดํฌ๋„ŒํŠธ์˜ ๋ชฉ์ ์— ๋ฒ—์–ด๋‚˜์ง€ ์•Š๋„๋ก ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•ฉ๋‹ˆ๋‹ค.
  • ํŠน์ •ํ•œ ์ฝ”๋“œ(์˜ˆ: ํŠน์ • ๋””๋ฐ”์ด์Šค์— ๊ด€ํ•œ ์ฝ”๋“œ)๋ฅผ ์“ฐ์ง€ ๋งˆ์‹ญ์‹œ์˜ค. ์ผ๋ฐ˜์ ์ธ ์ปดํฌ๋„ŒํŠธ ๋‚ด์— ํŠน์ •ํ•œ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•ด์•ผํ•˜๋Š” ๊ฒฝ์šฐ ํ•ด๋‹น API๊ฐ€ ์ถฉ๋ถ„ํžˆ ์ผ๋ฐ˜์ ์ธ ๊ฒƒ์ด ์•„๋‹ˆ๊ฑฐ๋‚˜ ์ƒˆ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ํ•„์š”ํ•  ์ˆ˜๋„ ์žˆ์Œ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.
  • props๋ฅผ ๋ชจ๋‘ ๊ฒ€์‚ฌํ•˜์—ฌ ๋†“์นœ ๋ถ€๋ถ„์ด ์žˆ๋Š”์ง€ ํ™•์ธํ•˜์„ธ์š”. ๋งŒ์•ฝ ๋†“์นœ ๋ถ€๋ถ„์ด ์žˆ๋‹ค๋ฉด ์ด์Šˆ๋ฅผ ๋งŒ๋“ค๊ฑฐ๋‚˜ ์ง์ ‘ ์ปดํฌ๋„ŒํŠธ๋ฅผ ์ˆ˜์ •ํ•˜์„ธ์š”.
  • ๋ชจ๋“  ์ด๋ฒคํŠธ๋ฅผ ํ™•์ธํ•˜์„ธ์š”. ๋Œ€๋ถ€๋ถ„์˜ ๊ฒฝ์šฐ ๊ฐœ๋ฐœ์ž๋Š” ์ž์‹์—์„œ ๋ถ€๋ชจ๋กœ์˜ ํ†ต์‹ (์ด๋ฒคํŠธ)ํ•˜๋Š” ๊ฒƒ์ด ํ•„์š”ํ•˜๋‹ค๋Š” ๊ฒƒ์„ ์žŠ์—ˆ์Šต๋‹ˆ๋‹ค. ๊ทธ ์ด์œ ๋Š” ๋ถ€๋ชจ์—์„œ ์ž์‹์œผ๋กœ์˜ ํ†ต์‹ (props ์‚ฌ์šฉ)๋งŒ ๊ธฐ์–ตํ•˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.
  • props๋Š” ์•„๋ž˜๋กœ, ์ด๋ฒคํŠธ๋Š” ์œ„๋กœ! ์ข‹์€ API์™€ ๋ถ„๋ฆฌ๊ฐ€ ํ•„์š”ํ•  ๋•Œ ๋‹น์‹ ์˜ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๊ฐœ์„ ํ•˜์„ธ์š”.
  • props์™€ ์ด๋ฒคํŠธ๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ํž˜๋“ค๊ณ  ref๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์— ์˜๋ฏธ๊ฐ€ ์žˆ๋Š” ๊ฒฝ์šฐ ์ปดํฌ๋„ŒํŠธ์— this.$refs๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. (์•„๋ž˜ ์˜ˆ์ œ๋ฅผ ์ฐธ๊ณ ํ•˜์„ธ์š”)
  • ์—˜๋ฆฌ๋จผํŠธ๋ฅผ ๋ฐ์ดํ„ฐ ๋ฐ”์ธ๋”ฉ์ด๋‚˜ ๋””๋ ‰ํ‹ฐ๋ธŒ๋กœ ์กฐ์ž‘ํ•  ์ˆ˜ ์—†๋Š” ๊ฒฝ์šฐ DOM ์—˜๋ฆฌ๋จผํŠธ์— ์ ‘๊ทผํ•˜๊ธฐ ์œ„ํ•ด jQuery, document.getElement*, document.queryElement๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋Œ€์‹  this.$refs๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์€ ์ข‹์€ ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค.
<!-- ์ข‹์•„์š”, ref๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š์•„๋„ ๋ฉ๋‹ˆ๋‹ค -->
<range :max="max"
  :min="min"
  @current-value="currentValue"
  :step="1"></range>
<!-- this.$refs๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์ข‹์€ ์˜ˆ์ œ ์ž…๋‹ˆ๋‹ค -->
<modal ref="basicModal">
  <h4>Basic Modal</h4>
  <button class="primary" @click="$refs.basicModal.close()">Close</button>
</modal>
<button @click="$refs.basicModal.open()">Open modal</button>

<!-- Modal ์ปดํฌ๋„ŒํŠธ -->
<template>
  <div v-show="active">
    <!-- ... -->
  </div>
</template>

<script>
  export default {
    // ...
    data() {
        return {
            active: false,
        };
    },
    methods: {
      open() {
        this.active = true;
      },
      hide() {
        this.active = false;
      },
    },
    // ...
  };
</script>
<!-- `emit`์œผ๋กœ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋‹ค๋ฉด ํ”ผํ•˜์„ธ์š”! -->
<template>
  <range :max="max"
    :min="min"
    ref="range"
    :step="1"></range>
</template>

<script>
  export default {
    // ...
    methods: {
      getRangeCurrentValue() {
        return this.$refs.range.currentValue;
      },
    },
    // ...
  };
</script>

โ†‘ ๋ชฉ์ฐจ๋กœ ๋Œ์•„๊ฐ€๊ธฐ

๋ฒ”์œ„ ์Šคํƒ€์ผ์— ์ปดํฌ๋„ŒํŠธ ์ด๋ฆ„ ์‚ฌ์šฉํ•˜๊ธฐ

Vue.js ์ปดํฌ๋„ŒํŠธ ์—˜๋ฆฌ๋จผํŠธ๋Š” ๋ฒ”์œ„ ์Šคํƒ€์ผ์˜ ๋ฃจํŠธ๋กœ ์ž˜ ์‚ฌ์šฉ ๋  ์ˆ˜ ์žˆ๋Š” ์‚ฌ์šฉ์ž ์ง€์ • ์—˜๋ฆฌ๋จผํŠธ์ž…๋‹ˆ๋‹ค. ๋˜ํ•œ ์ปดํฌ๋„ŒํŠธ ์ด๋ฆ„์„ CSS ํด๋ž˜์Šค ๋„ค์ž„์ŠคํŽ˜์ด์Šค๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์™œ ๊ทธ๋ ‡๊ฒŒ ํ•˜๋‚˜์š”?

  • ์ปดํฌ๋„ŒํŠธ์— ๋ฒ”์œ„ ์Šคํƒ€์ผ์„ ์ ์šฉํ•˜๋ฉด ์ปดํฌ๋„ŒํŠธ ์™ธ๋ถ€์— ์Šคํƒ€์ผ์ด ์ ์šฉ๋˜์ง€ ์•Š์œผ๋ฏ€๋กœ ์˜ˆ์ธก ๊ฐ€๋Šฅ์„ฑ์ด ํ–ฅ์ƒ๋ฉ๋‹ˆ๋‹ค.
  • Vue.js ์ปดํฌ๋„ŒํŠธ์™€ ์Šคํƒ€์ผ์˜ ๋ฃจํŠธ ์ด๋ฆ„๋ฅผ ๋ชจ๋“ˆ ๋””๋ ‰ํ† ๋ฆฌ์™€ ๋™์ผํ•œ ์ด๋ฆ„์œผ๋กœ ์‚ฌ์šฉํ•˜๋ฉด ๊ฐœ๋ฐœ์ž๊ฐ€ ์ดํ•ดํ•˜๊ธฐ ์ข€ ๋” ์‰ฝ์Šต๋‹ˆ๋‹ค.

์–ด๋–ป๊ฒŒ ํ•˜๋‚˜์š”?

BEM ๋ฐ OOCSS์— ๊ธฐ๋ฐ˜ํ•œ ๋„ค์ž„์ŠคํŽ˜์ด์Šค ์ ‘๋‘์–ด๋กœ ์ปดํฌ๋„ŒํŠธ ์ด๋ฆ„์„ ์‚ฌ์šฉํ•˜๊ณ  style์— scoped ์–ดํŠธ๋ฆฌ๋ทฐํŠธ๋ฅผ ์‚ฌ์šฉํ•˜์„ธ์š”. scoped๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด Vue ์ปดํŒŒ์ผ๋Ÿฌ๋Š” <style>์ด ๊ฐ€์ง„ ๋ชจ๋“  ํด๋ž˜์Šค์— ํŠน์ • ์„œ๋ช…์„ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค. ์ด ์„œ๋ช…์€ ๋ธŒ๋ผ์šฐ์ €๊ฐ€(์ง€์›ํ•œ๋‹ค๋ฉด) ์ปดํฌ๋„ŒํŠธ๋ฅผ ๊ตฌ์„ฑํ•˜๋Š” ๋ชจ๋“  ํƒœ๊ทธ์— ์ปดํฌ๋„ŒํŠธ CSS๋ฅผ ์ ์šฉํ•˜๊ณ  CSS๊ฐ€ ๋ˆ„์ถœ๋˜์ง€ ์•Š๋„๋ก ๋„์™€์ค๋‹ˆ๋‹ค.

<style scoped>
  /* ๊ถŒ์žฅํ•ฉ๋‹ˆ๋‹ค */
  .MyExample { }
  .MyExample li { }
  .MyExample__item { }

  /* ํ”ผํ•˜์„ธ์š”! */
  .My-Example { } /* ์ปดํฌ๋„ŒํŠธ๋‚˜ ๋ชจ๋“ˆ ์ด๋ฆ„์œผ๋กœ scoped๊ฐ€ ์ง€์ •๋˜์ง€ ์•Š๊ณ  BEM ๋ฌธ๋ฒ•๊ณผ ์ผ์น˜ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. */
</style>

โ†‘ ๋ชฉ์ฐจ๋กœ ๋Œ์•„๊ฐ€๊ธฐ

์ปดํฌ๋„ŒํŠธ API๋ฅผ ๋ฌธ์„œํ™” ํ•˜๊ธฐ

Vue.js ์ปดํฌ๋„ŒํŠธ ์ธ์Šคํ„ด์Šค๋Š” ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜ ๋‚ด๋ถ€์˜ ์ปดํฌ๋„ŒํŠธ ์—˜๋ฆฌ๋จผํŠธ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋งŒ๋“ญ๋‹ˆ๋‹ค. ์ธ์Šคํ„ด์Šค๋Š” ์‚ฌ์šฉ์ž ์ •์˜ ์–ดํŠธ๋ฆฌ๋ทฐํŠธ๋ฅผ ํ†ตํ•ด ๊ตฌ์„ฑ๋ฉ๋‹ˆ๋‹ค. ๋‹ค๋ฅธ ๊ฐœ๋ฐœ์ž๊ฐ€ ์ปดํฌ๋„ŒํŠธ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ ์ด๋Ÿฌํ•œ ์‚ฌ์šฉ์ž ์ง€์ • ์–ดํŠธ๋ฆฌ๋ทฐํŠธ(์ปดํฌ๋„ŒํŠธ์˜ API)๋ฅผ README.md ํŒŒ์ผ์— ๋ฌธ์„œํ™”ํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค.

์™œ ๊ทธ๋ ‡๊ฒŒ ํ•˜๋‚˜์š”?

  • ๋ฌธ์„œ๋Š” ๊ฐœ๋ฐœ์ž๊ฐ€ ์ฝ”๋“œ ์ „์ฒด๋ฅผ ๊ฒ€ํ† ํ•  ํ•„์š” ์—†์ด ์ปดํฌ๋„ŒํŠธ์— ๋Œ€ํ•œ ๊ฐ„๋žตํ•œ ๊ฐœ์š”๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. ๋ฌธ์„œ๋ฅผ ๋งŒ๋“ค๋ฉด ์ปดํฌ๋„ŒํŠธ๋ฅผ ์‰ฝ๊ฒŒ ์ ‘๊ทผํ•˜๊ณ  ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ์ปดํฌ๋„ŒํŠธ์˜ API๋Š” ์‚ฌ์šฉ์ž ์ง€์ • ์–ดํŠธ๋ฆฌ๋ทฐํŠธ์˜ ์ง‘ํ•ฉ์„ ํ†ตํ•ด ๊ตฌ์„ฑ๋ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋ฏ€๋กœ ์ด๊ฒƒ๋“ค์€ ์ปดํฌ๋„ŒํŠธ๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ์›ํ•˜๋Š” (๋‹ค์‹œ ๊ฐœ๋ฐœํ•˜์ง€ ์›์น˜ ์•Š๋Š”) ๋‹ค๋ฅธ ๊ฐœ๋ฐœ์ž๋“ค์—๊ฒŒ ์ค‘์š”ํ•ฉ๋‹ˆ๋‹ค.
  • ๋ฌธ์„œ๋Š” API๋ฅผ ํ˜•์‹์„ ๊ฐ–์ถ”๊ฒŒํ•˜๊ณ  ๊ฐœ๋ฐœ์ž์—๊ฒŒ ์ปดํฌ๋„ŒํŠธ์˜ ์ฝ”๋“œ๋ฅผ ์ˆ˜์ •ํ•  ๋•Œ ํ•˜์œ„ ํ˜ธํ™˜์„ฑ์„ ์œ ์ง€ํ•  ์ˆ˜ ์žˆ๋„๋ก ๋•์Šต๋‹ˆ๋‹ค.
  • README.md๋Š” ๋จผ์ € ์ฝ์–ด์•ผํ•  ๋ฌธ์„œ๋ฅผ ์œ„ํ•œ ์‚ฌ์‹ค์ƒ ํ‘œ์ค€์ ์ธ ํŒŒ์ผ๋ช…์ž…๋‹ˆ๋‹ค. ์ฝ”๋“œ ์ €์žฅ์†Œ๋ฅผ ํ˜ธ์ŠคํŒ…ํ•˜๋Š” ์„œ๋น„์Šค(Github, Bitbucket, Gitlab ๋“ฑ)๋Š” ์†Œ์Šค ๋””๋ ‰ํ† ๋ฆฌ๋ฅผ ํƒ์ƒ‰ํ•  ๋•Œ README.md ํŒŒ์ผ์˜ ๋‚ด์šฉ์„ ํ‘œ์‹œํ•ฉ๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ ๋ชจ๋“ˆ ๋””๋ ‰ํ† ๋ฆฌ์—๋„ ๋˜‘๊ฐ™์ด ์ ์šฉ๋ฉ๋‹ˆ๋‹ค.

์–ด๋–ป๊ฒŒ ํ•˜๋‚˜์š”?

README.md ๋ฌธ์„œ๋ฅผ ์ปดํฌ๋„ŒํŠธ์˜ ๋ชจ๋“ˆ ๋””๋ ‰ํ† ๋ฆฌ์— ์ถ”๊ฐ€ํ•˜์„ธ์š”.

range-slider/
โ”œโ”€โ”€ range-slider.vue
โ”œโ”€โ”€ range-slider.less
โ””โ”€โ”€ README.md

README.md ํŒŒ์ผ์—์„œ ๋ชจ๋“ˆ์˜ ๊ธฐ๋Šฅ ๋ฐ ์‚ฌ์šฉ๋ฒ•์„ ์ ์œผ์„ธ์š”. Vue ์ปดํฌ๋„ŒํŠธ์˜ ๊ฒฝ์šฐ API์™€ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ์ง€์›ํ•˜๋Š” ์‚ฌ์šฉ์ž ์ •์˜ ์–ดํŠธ๋ฆฌ๋ทฐํŠธ์— ๋Œ€ํ•ด์„œ ์„ค๋ช…ํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค.

๋ฒ”์œ„ ์Šฌ๋ผ์ด๋”

๊ธฐ๋Šฅ

๋ฒ”์œ„ ์Šฌ๋ผ์ด๋”๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์Šฌ๋ผ์ด๋” ํ•ธ๋“ค์„ ๋“œ๋ž˜๊ทธํ•˜์—ฌ ์‹œ์ž‘๊ณผ ๋ ๊ฐ’๋‚ด์— ๊ฐ’์„ ์„ค์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด ๋ชจ๋“ˆ์€ ํฌ๋กœ์Šค ๋ธŒ๋ผ์šฐ์ง• ๋ฐ ํ„ฐ์น˜ ์ง€์›์„ ์œ„ํ•ด์„œ noUiSlider๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

์‚ฌ์šฉ ๋ฐฉ๋ฒ•

<range-slider>๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์‚ฌ์šฉ์ž ์ •์˜ ์ปดํฌ๋„ŒํŠธ ์–ดํŠธ๋ฆฌ๋ทฐํŠธ๋ฅผ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค :

์–ดํŠธ๋ฆฌ๋ทฐํŠธ ํƒ€์ž… ์„ค๋ช…
min Number ๋ฒ”์œ„๊ฐ€ ์‹œ์ž‘๋˜๋Š” ๊ฐ’ (์ตœ์†Œ๊ฐ’).
max Number ๋ฒ”์œ„๊ฐ€ ๋๋‚˜๋Š” ๊ฐ’ (์ตœ๋Œ€๊ฐ’).
values Number[] optional ์‹œ์ž‘๊ณผ ๋๊ฐ’์„ ํฌํ•จํ•˜๋Š” ๋ฐฐ์—ด. ์˜ˆ) values="[10, 20]". ๊ธฐ๋ณธ๊ฐ’์€ [opts.min, opts.max] ์ž…๋‹ˆ๋‹ค.
step Number optional ์ˆซ์ž๋ฅผ ์ฆ๊ฐ€/๊ฐ์†Œ ์‹œํ‚ฌ ๊ฐ’. ๊ธฐ๋ณธ๊ฐ’์€ 1์ž…๋‹ˆ๋‹ค.
on-slide Function optional ์‚ฌ์šฉ์ž๊ฐ€ ์‹œ์ž‘(HANDLE == 0) ๋˜๋Š” ๋(HANDLE == 1)์— ํ•ธ๋“ค์„ ์œ„์น˜ํ•˜๋ฉด ํ˜ธ์ถœ๋˜๋Š” ํ•จ์ˆ˜ํž™๋‹ˆ๋‹ค. ์˜ˆ) on-slide={ updateInputs }, component.updateInputs = (values, HANDLE) => { const value = values[HANDLE]; }.
on-end Function optional ์‚ฌ์šฉ์ž๊ฐ€ ํ•ธ๋“ค ๋“œ๋ž˜๊ทธ๋ฅผ ๋ฉˆ์ถ”๋ฉด (values, HANDLE) ํ•จ์ˆ˜๊ฐ€ ํ˜ธ์ถœ๋ฉ๋‹ˆ๋‹ค.

์Šฌ๋ผ์ด๋” ๋ชจ์–‘์„ ์‚ฌ์šฉ์ž ์ •์˜ํ•˜๋ ค๋ฉด noUiSlider ๋ฌธ์„œ์˜ Styling ์„น์…˜์„ ์ฐธ๊ณ ํ•˜์„ธ์š”.

โ†‘ ๋ชฉ์ฐจ๋กœ ๋Œ์•„๊ฐ€๊ธฐ

์ปดํฌ๋„ŒํŠธ ์˜ˆ์ œ ์ถ”๊ฐ€ํ•˜๊ธฐ

index.html ํŒŒ์ผ์„ ์ถ”๊ฐ€ํ•˜์—ฌ ์ปดํฌ๋„ŒํŠธ์˜ ์‚ฌ์šฉ ๋ฐฉ๋ฒ•์„ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค.

์™œ ๊ทธ๋ ‡๊ฒŒ ํ•˜๋‚˜์š”?

  • ์ปดํฌ๋„ŒํŠธ ์˜ˆ์ œ๋Š” ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋…๋ฆฝ์ ์œผ๋กœ ์ž‘๋™ํ•จ์„ ์ฆ๋ช…ํ•ฉ๋‹ˆ๋‹ค.
  • ์ปดํฌ๋„ŒํŠธ ์˜ˆ์ œ๋ฅผ ์ž‘์„ฑํ•˜๋ฉด ๊ฐœ๋ฐœ์ž๊ฐ€ ๋ฌธ์„œ ๋˜๋Š” ์ฝ”๋“œ๋ฅผ ์‚ดํŽด๋ณด๊ธฐ ์ „์— ์ž‘๋™ ๋ชจ์Šต์„ ํ™•์ธ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ์ปดํฌ๋„ŒํŠธ ์˜ˆ์ œ๋Š” ์ปดํฌ๋„ŒํŠธ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๋ชจ๋“  ์„ค์ •์„ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค.

โ†‘ ๋ชฉ์ฐจ๋กœ ๋Œ์•„๊ฐ€๊ธฐ

์ปดํฌ๋„ŒํŠธ ํŒŒ์ผ์„ Lintํ•˜๊ธฐ

Lint๋Š” ์ฝ”๋“œ ์ผ๊ด€์„ฑ์„ ๊ฐœ์„ ํ•˜๊ณ  ๊ตฌ๋ฌธ ์˜ค๋ฅ˜๋ฅผ ์ถ”์ ํ•˜๋Š” ๊ฒƒ์„ ๋„์™€์ค๋‹ˆ๋‹ค. .vue ํŒŒ์ผ์€ ํ”„๋กœ์ ํŠธ์— eslint-plugin-html์„ ๋‹น์‹ ์˜ ํ”„๋กœ์ ํŠธ์— ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋งŒ์•ฝ ์‚ฌ์šฉํ•˜๊ธธ ์›ํ•˜๋ฉด ๋‹น์‹ ์€ vue-cli๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ESLint๊ฐ€ ํ™œ์„ฑํ™”๋œ ํ”„๋กœ์ ํŠธ๋ฅผ ์‹œ์ž‘ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์™œ ๊ทธ๋ ‡๊ฒŒ ํ•˜๋‚˜์š”?

  • ์ปดํฌ๋„ŒํŠธ ํŒŒ์ผ์„ Lintํ•˜๋ฉด ๋ชจ๋“  ๊ฐœ๋ฐœ์ž๊ฐ€ ๋™์ผํ•œ ์ฝ”๋“œ ์Šคํƒ€์ผ์„ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ๋„๋ก ๋ณด์žฅํ•ฉ๋‹ˆ๋‹ค.
  • ์ปดํฌ๋„ŒํŠธ ํŒŒ์ผ์„ Lintํ•˜๋ฉด ๊ตฌ๋ฌธ ์˜ค๋ฅ˜๋ฅผ ๋น ๋ฅด๊ฒŒ ์ˆ˜์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์–ด๋–ป๊ฒŒ ํ•˜๋‚˜์š”?

Lint๊ฐ€ *.vue ํŒŒ์ผ์—์„œ ์Šคํฌ๋ฆฝํŠธ๋ฅผ ์ถ”์ถœํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•˜๋ ค๋ฉด ์Šคํฌ๋ฆฝํŠธ๋ฅผ ์ปดํฌ๋„ŒํŠธ์˜ <script> ์•ˆ์— ๋„ฃ๊ณ  ์ปดํฌ๋„ŒํŠธ์˜ ํ‘œํ˜„์‹์„ ๋‹จ์ˆœํ•˜๊ฒŒ ์‚ฌ์šฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค(Lint๊ฐ€ ํ‘œํ˜„์‹์„ ์ดํ•ดํ•˜์ง€ ๋ชปํ•ฉ๋‹ˆ๋‹ค). ๊ทธ๋ฆฌ๊ณ  Lint์— ๊ธ€๋กœ๋ฒŒ ๋ณ€์ˆ˜ vue์™€ ์ปดํฌ๋„ŒํŠธ props๋ฅผ ํ—ˆ์šฉํ•˜๋„๋ก ์„ค์ •ํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค.

ESLint

ESLint๋Š” ์ปดํฌ๋„ŒํŠธ์—์„œ ์Šคํฌ๋ฆฝํŠธ๋ฅผ ์ถ”์ถœํ•˜๊ธฐ ์œ„ํ•ด์„œ ESLint HTML ํ”Œ๋Ÿฌ๊ทธ์ธ์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

.eslintrc ํŒŒ์ผ์„ ์ž‘์„ฑํ•˜์—ฌ ESLint๋ฅผ ์„ค์ •ํ•˜์„ธ์š”. (IDE๋Š” ๊ทธ๊ฒƒ์„ ํ•ด์„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค)

{
  "extends": "eslint:recommended",
  "plugins": ["html"],
  "env": {
    "browser": true
  },
  "globals": {
    "opts": true,
    "vue": true
  }
}

ESLint๋ฅผ ์‹คํ–‰ํ•ด๋ณด์„ธ์š”.

eslint src/**/*.vue

JSHint

JSHint์€ --extra-ext๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ HTML์„ ํŒŒ์‹ฑํ•˜๊ณ  --extract=auto๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์Šคํฌ๋ฆฝํŠธ๋ฅผ ์ถ”์ถœํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. 0 .jshintrc ํŒŒ์ผ์„ ์ž‘์„ฑํ•˜์—ฌ JSHint๋ฅผ ์„ค์ •ํ•˜์„ธ์š”. (IDE๋Š” ๊ทธ๊ฒƒ์„ ํ•ด์„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค)

{
  "browser": true,
  "predef": ["opts", "vue"]
}

JSHint๋ฅผ ์‹คํ–‰ํ•ด๋ณด์„ธ์š”.

jshint --config modules/.jshintrc --extra-ext=html --extract=auto modules/

์ฐธ๊ณ : JSHint๋Š” vue๋ฅผ ํ™•์žฅ์ž๋กœ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ณ  html๋งŒ์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

โ†‘ ๋ชฉ์ฐจ๋กœ ๋Œ์•„๊ฐ€๊ธฐ


๋„์›€์„ ์ฃผ์‹œ๊ฒ ์Šต๋‹ˆ๊นŒ?

์ €์žฅ์†Œ๋ฅผ Forkํ•˜๊ณ  Pull Request๋ฅผ ๋ณด๋‚ด์ฃผ์‹œ๊ฑฐ๋‚˜ ์ด์Šˆ๋ฅผ ์ž‘์„ฑํ•ด์ฃผ์‹œ๋ฉด ๊ฐ์‚ฌํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

๋ฒˆ์—ญ์ž๋“ค