8000 GitHub - sudheerj/vuejs-interview-questions-korean: VueJS interview questions in Korean language
[go: up one dir, main page]

Skip to content

sudheerj/vuejs-interview-questions-korean

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

28 Commits
 
 
 
 

Repository files navigation

vuejs-interview-questions-korean

List of 300 VueJS Interview Questions

Contributor

  • đź“‹ 본 문서는 sudheerjěť vuejs-interview-questionsěť ë˛ě—­ëł¸ěž…ë‹ë‹¤.
  • â­ ěť´ 프로젝트가 ë§ěťŚě— 드셨다면 STAR를 ëŚëź¬ěŁĽě„¸ěš”.
  • ✔️ í’€ 리í€ěŠ¤íŠ¸ëŠ” 언제든 í™ěěž…ë‹ë‹¤.

Table of Contents


No. Questions
1 VueJS란 무엇인가
2 VueJSěť ěŁĽěš” 특징은
3 VueJSěť ëťĽěť´í”„ě‚¬ěť´í´(lifecycle) 함ě는
4 조건부 지시ěž(conditional directives)란
5 v-show와 v-ifěť ě°¨ěť´ě ěť€
6 v-for를 쓰는 목ě ěť€
7 Vue 인스턴스란
8 여러 ě—리먼트들을 한 ë˛ě— 조건부로 ë‚í€ë‚´ëŠ” 방법은
9 key 속성을 이용해 ě—리먼트를 재사용í•는 방법은
10 같은 ě—리먼트ě—서 v-for와 v-if를 í•¨ę» ě“°ë©´ ě• ë는 이유는
11 v-forě—서 key 속성이 필요한 ěť´ěś 
12 ë°°ě—´ěť„ 변화시키는 함ě(Mutation method)란
13 ë°°ě—´ěť„ 대체í•는 함ě(Non-mutation method)란
14 ë°°ě—´ 변경을 í지할 때 주ěťí•  ě 
15 객체 변경을 í지할 때 주ěťí•  ě 
16 v-for를 특정 íšźěë§ŚíĽ ë°ëłµí•는 방법은
17 v-for로 템플릿을 ë°ëłµí•는 방법은
18 이벤트 핸들러를 사용í•는 방법은
19 Vueě—서 이벤트 ě식어(Event modifier)란
20 키 ě식어(Key modifiers)란
21 키 ě식어를 커스터ë§ěť´ě§•í•는 방법은
22 시스템 ě식어 키(System modifier key)란
23 ë§ěš°ěФ 버튼 ě식어(Mouse button modifier)란?
24 v-modelěť ě—­í• ěť€
25 v-modelě—서 ě§€ě›ë는 ě식어는?
26 컴포넌트(Component)란
27 props란?
28 컴포넌트ě—서 여러 ě—리먼트를 쓰려면?
29 í•ěś„ 컴포넌트ě—서 ěěś„ 컴포넌트로 이벤트를 전달í•는 방법은?
30 ě‚¬ěš©ěž ě •ěťěť input 컴포넌트ě—서 v-modelěť„ 사용í•는 법은?
31 slots이란?
32 컴포넌트를 ě „ě—­ 등록í•는 방법은?
33 ě»´íŹ¬ë„ŚíŠ¸ěť ě§€ě—­ 등록이 필요한 이유는?
34 ëŞ¨ë“ ě‹śěŠ¤í…śě—서 ě „ě—­ 등록과 지역 등록ěťě°¨ěť´ě ěť€?
35 prop í€ěž…ěť ě˘…ëĄëŠ”?
36 propsě— ěťí•ś 데이터 íťë¦„은?
37 Props가 아닌 속성은?
38 Props를 검증í•는 방법은?
39 컴포넌트ě—서 v-modelěť„ ě‚¬ěš©ěž ě •ěťí•는 방법은?
40 íŠ¸ëžśě§€ě… íš¨ęłĽëĄĽ 넣을 ě ěžëŠ” 방법은?
41 Vue Router란?
42 Vue Router를 사용í•는 방법은?
43 ëŹ™ě  ëťĽěš°íŠ¸ 매칭이란?
44 라우터 params를 ë°ěť‘ě ěśĽëˇś 만드는 방법은?
45 ëťĽěš°íŠ¸ěť ěš°ě„  ěśěś„는?
46 ě¤‘ě˛©ëś ëťĽěš°íŠ¸ëž€?
47 싱글 파일 컴포넌트란?
48 관심사 분리(separation of concerns)이란?
49 싱글 파일 컴포넌트는 왜 필요할까?
50 filter란?
51 filter를 ě „ě—­ě  ë는 지역ě ěśĽëˇś 만드는 법은?
52 filter를 연속해 쓰는 방법은?
53 filterě— íŚŚëťĽëŻ¸í„°ëĄĽ 전달할 ě ěžěť„까?
54 플러그인이란?
55 플러그인을 만드는 방법은?
56 플러그인을 사용í•는 방법은?
57 믹스인이란?
58 전역 믹스인이란?
59 CLI í™ę˛˝ě—서 믹스인을 사용í•는 법은
60 ëŻąěŠ¤ěť¸ěť ěµě…ěť´ ě»´íŹ¬ë„ŚíŠ¸ěť ěµě…과 충돌한다면?
61 ëŻąěŠ¤ěť¸ěť ëł‘í•© 방법을 ě‚¬ěš©ěž ě •ěťí•는 방법은?
62 ě‚¬ěš©ěž ě •ěť ě§€ě‹śěž(Custom directive)란?
63 지시ěžëĄĽ 지역 등록í•는 방법은?
64 지시ěžě— ěťí•´ ě śęłµë는 라이프 ě‚¬ěť´í´ í›…ěť€?
65 디렉티브 í›…ěť ě „ë‹¬ěť¸ěžëŠ”?
66 지시ěžě— 여러 값들을 전달í•는 방법은?
67 ě§€ě‹śěž í›…ě—서 함ě 약어는?
68 render 함ě를 사용í•는 이유는?
69 render 함ě란?
70 createElement 함ě란
71 ę°€ě 노드를 여러 ë˛ ě‚¬ěš©í•  ě ěžëŠ” 방법은?
72 render 함ě와 템플릿을 ëą„ęµí•śë‹¤ë©´?
73 함ěí• ě»´íŹ¬ë„ŚíŠ¸(Functional component)란?
74 Vue와 Reactěť ęłµí†µě ěť€?
75 Vue와 Reactěť ě°¨ěť´ě ěť€?
76 Vueę°€ Reactě— ëą„í•´ ë‚은 ě ěť€
77 Reactę°€ Vueě— ëą„í•´ ë‚은 ě ěť€
78 Vue와 AngularJSěť ě°¨ěť´ě ěť€
79 ëŹ™ě  ě»´íŹ¬ë„ŚíŠ¸ëž€?
80 keep-alive íśę·¸ëž€?
81 비동기 컴포넌트(Async component)란?
82 비동기 컴포넌트 팩토리 패턴이란?
83 인라인 템플릿(inline templates)이란?
84 X-Templates이란?
85 재귀 컴포넌트(recursive components)란?
86 컴포넌트 ě‚¬ěť´ěť ěśí™ 참조 해결 방법은?
87 CSP í™ę˛˝ě—서 Vue 어플리케이ě…ěť„ 빌드í•는 법은
88 전체 빌드와 ëź°í€ěž„ ëąŚë“śěť ě°¨ěť´ě ěť€?
89 Vueěť ëąŚë“ś 종ëĄëŠ”?
90 웹팩ě—서 Vue 설정을 í•는 방법은?
91 Vue ě»´íŚŚěťĽëź¬ěť ëŞ©ě ěť€?
92 DevTool이란
93 VueJSěť ë¸ŚëťĽěš°ě € ě§€ě›ěť€?
94 CDN으로 Vue를 사용í•는 방법은?
95 강제로 업데이트를 ë°śěťě‹śí‚¤ëŠ” 방법은?
96 템플릿ě—서 once 지시ěžëĄĽ 쓰는 이유는?
97 루트 Vue ěť¸ěŠ¤í„´ěŠ¤ě— ě ‘ę·Ľí•는 방법은?
98 Vue를 사용í•ęł  ěžëŠ” 기업들은?
99 renderError ë©”ě†Śë“śěť ëŞ©ě ěť€?
100 í•ěś„ 컴포넌트ě—서 ěěś„ 컴포넌트로 ě§ě ‘ ě ‘ę·Ľí•는 방법은?
101 vuex란?
102 ěíś ę´€ë¦¬ íŚ¨í„´ěť ěŁĽěš” 구성 요소는 무엇입ë‹ęąŚ?
103 Vuexě—서 단방향 데이터 íťë¦„ 모델을 어떻게 표í„í•©ë‹ęąŚ?
104 vuejs loader는 무엇입ë‹ęąŚ?
105 웹팩ě—서 vue loader를 설정í•는 방법은?
106 vue-loaderěť Asset URL í•¸ë“¤ë§ ę·śěą™ěť€?
107 vue-loaderě—서 ě „ě˛ë¦¬ę¸°ëĄĽ 사용í•는 경우라면?
108 범위 CSS(Scoped CSS)란?
109 범위 CSS와 ě „ě—­ CSS를 í•¨ę» ě“¸ ě ěžěť„까?
110 범위 CSSę°€ ěžě‹ť ě»´íŹ¬ë„ŚíŠ¸ě— ěí–Ąěť„ 미ěąę˛Ś í•는 방법은?
111 ěěś„ ě»´íŹ¬ë„ŚíŠ¸ěť ë˛”ěś„ CSSę°€ í•ěś„ ě»´íŹ¬ë„ŚíŠ¸ě— ěí–Ąěť„ 주는가?
112 동ě ěśĽëˇś ěťě„±ëś 컨í…ě¸ ě— ë˛”ěś„ CSS를 ě ěš©ě‹śí‚¤ëŠ” 방법은?
113 Vueě—서 CSS 모ë“ěť„ 사용할 ě ěžěť„까?
114 모든 í…śí”Śë¦żě— ëŚ€í•´ ëź°í€ěž„ 빌드를 í•  ě ěžëД氀?
115 Vueě—서 CSS 모ë“ěť„ 사용í•는 방법은?
116 CSS 모ë“ěť„ ě „ě˛ë¦¬ę¸°ě—서 사용할 ě ěžëД氀?
117 CSS 모ë“ě— ě‚¬ěš©ěž ě •ěťěť 이름을 사용할 ě ěžëД氀?
118 핫 리로드(Hot Reload)란?
119 í•« 리로드가 비활성화 ë  ë•ŚëŠ”?
120 í•« 리로드를 명시ě ěśĽëˇś 비활성화í•는 방법은?
121 í•« 리로드를 활성화í•는 방법은?
122 í•« 리로드ě—서 ěíśę°€ 보존ë는 규칙은?
123 Vue loader를 이용해 함ěí• ě»´íŹ¬ë„ŚíŠ¸ëĄĽ ěťě„±í•는 방법은?
124 함ěí• ě»´íŹ¬ë„ŚíŠ¸ě—서 ě „ě—­ ě†Ťě„±ě— ě ‘ę·Ľí•는 방법은?
125 Vueě—서 테스트 í•는 방법은?
126 CSSě— Lint를 설정í•는 방법은?
127 eslint 플러그인을 사용í•는 방법은?
128 eslint-loader를 사용í•는 이유는?
129 CSS 단일 파일 추출이란?
130 ě‚¬ěš©ěž ě •ěť ë¸”ëˇťěť´ëž€?
  1. VueJS란 무엇인가

    Vue.js는 ě‚¬ěš©ěž ěť¸í„°íŽěť´ěŠ¤ëĄĽ 만들기 위한 ě§„ëł´ě ěť¸ 프ë ěž„워í¬ěž…ë‹ë‹¤. 핵심 라이브러리는 ë·° ë ěť´ě–´ë§Ś ě´ě ěť„ 맞추어, 다른 ëťĽěť´ë¸Śëź¬ë¦¬ë‚ ę¸°ěˇ´ í”„ëˇśě ťíŠ¸ě™€ěť í†µí•©ěť´ 쉽습ë‹ë‹¤.

  2. VueJSěť ěŁĽěš” 특징은

    ě•„ëžěť 항목들은 VueJSěť ěŁĽěš” 특징들입ë‹ë‹¤.

    1. ę°€ě DOM(Virtual DOM): VueJSě—서는 ReactJS, Ember 프ë ěž„워í¬ě™€ 유사í•게 ę°€ě DOMěť„ 사용합ë‹ë‹¤. ę°€ě DOM은 ě›ëł¸ HTML DOMěť„ 표í„í•는 메모리 ěěť ę°€ë˛Ľěš´ DOM 트리로, ě›ëł¸ DOMě— ěí–Ąěť„ 미ěąě§€ 않고 업데이트를 í•  ě ěžěеë‹ë‹¤.
    2. 컴포넌트(Components): VueJS 어플리케이ě…ě—서 재사용할 ě ěžëŠ” ě—리먼트들을 만들 ě ěžěеë‹ë‹¤.
    3. 템플릿(Templates): VueJS는 Vue 인스턴스 데이터와 DOMě— ě ‘ę·Ľí•  ě ěžëŠ” HTML 기ë°ěť 템플릿을 제공합ë‹ë‹¤.
    4. 라우팅(Routing): íŽěť´ě§€ěť ě „í™ěť€ vue-router를 이용합ë‹ë‹¤.
    5. 저용량(Light weight): VueJS는 다른 프ë ěž„워í¬ě™€ ëą„ęµí•´ 저용량입ë‹ë‹¤.
  3. VueJSěť ëťĽěť´í”„ě‚¬ěť´í´(lifecycle) 함ě는

    ëťĽěť´í”„ě‚¬ěť´í´ í›…(Lifecycle hook)은 사용중인 라이브러리가 ě–´ë–¤ ěśě„śëˇś 동작í•는지를 알려주는 ě—­í• ěť„ í•©ë‹ë‹¤. í›…ěť„ 이용해 컴포넌트가 언제 ěťě„±ëęł , 언제 DOMě— ě¶”ę°€ëë©°, 언제 업데이트ëęł  언제 사라지는지 알 ě ěžěеë‹ë‹¤. ě•„ëžěť 다이어그램을 통해 VueJSěť ě „ë°ě ěť¸ 라이프사이í´ěť„ 확인할 ě ěžěеë‹ë‹¤.

    1. Creation(ě´ę¸°í™”): Create 훅은 컴포넌트가 DOMě— ě¶”ę°€ë기 ě „ě— ě‹¤í–‰ë는 단계입ë‹ë‹¤. í´ëťĽěť´ě–¸íŠ¸ě™€ 서버가 ë ŚëŤ”ë§ ë‹¨ęł„ ě „ě— ě»´íŹ¬ë„ŚíŠ¸ě— ě„¤ě •í•´ě•Ľ í•  ę˛ë“¤ěť´ ěžěť„ 때 사용í•는 단계입ë‹ë‹¤. 다른 훅과는 다르게, Create 훅은 서버 사이드 렌더ë§ě—서도 ě§€ě›ë는 í›…ěž…ë‹ë‹¤.

      1. beforeCreate: beforeCreate 훅은 컴포넌트 ě´ę¸°í™” 단계 중 가장 ě˛ěťŚěśĽëˇś 실행ë©ë‹ë‹¤. ěť´ í›…ě—서는 ě»´íŹ¬ë„ŚíŠ¸ěť data를 관찰í•ęł , 이벤트를 ě´ę¸°í™”í•©ë‹ë‹¤. ěť´ 단계ě—서 data는 ě•„ě§ęąŚě§€ ë°ěť‘ě ěť´ě§€ 않으며, ě»´íŹ¬ë„ŚíŠ¸ěť ëťĽěť´í”„ě‚¬ěť´í´ě—서 ë°śěťí•는 이벤트 역시 설정ëě§€ 않은 ěíśěž…ë‹ë‹¤.
          new Vue({
            data: {
             count: 10
            },
            beforeCreate: function () {
              console.log('Nothing gets called at this moment')
              // `this` points to the view model instance
              console.log('count is ' + this.count);
            }
          })
             // count is undefined
      1. created: created 훅은 Vue 인스턴스가 이벤트를 설정í•ęł  data를 관찰할 때 ë°śěťí•©ë‹ë‹¤. ěť´ 단계ě—서 템플릿은 ě•„ě§ ë§ěš´íЏëę±°ë‚ ë ŚëŤ”ë§ëě§€ 않ě•지만, 이벤트들이 활성화ëë©° dataě— ë°ěť‘ě ěśĽëˇś ě ‘ę·Ľí•는 ę˛ěť´ 가능합ë‹ë‹¤.
        new Vue({
          data: {
           count: 10
          },
          created: function () {
            // `this` points to the view model instance
            console.log('count is: ' + this.count)
          }
        })
           // count is: 10

      주ěť: Create í›…ě—서는 DOMě— ě§ě ‘ ě ‘ę·Ľí•ę±°ë‚ ë§ěš´íŠ¸í•  ě—리먼트(this.$el)ě— ě§ě ‘ ě ‘ę·Ľí•  ě 없다는 ě ěť„ 기억í•세요.

    2. Mounting(DOM 추가): Mount 훅은 가장 ë§Žěť´ 사용ë는 단계로, 컴포넌트가 렌더ë§ë기 ě§ě „ěť´ë‚ ě§í›„ě— ě»´íŹ¬ë„ŚíŠ¸ě— ě ‘ę·Ľí•  ě ěžëŠ” 단계입ë‹ë‹¤.

      1. beforeMount: beforeMount 훅은 컴포넌트가 DOMě— ě¶”ę°€ë기 ě§ě „ě— ě‹¤í–‰ë는 í›…ěž…ë‹ë‹¤.
        new Vue({
          beforeMount: function () {
            // `this` points to the view model instance
            console.log(`this.$el is yet to be created`);
          }
        })
      1. mounted: mounted 훅은 ë°ěť‘ě ěť¸ data, 템플릿, 렌더ë§ëś DOM(this.$el) 모ë‘ě— ě ‘ę·Ľí•  ě ěžě–´ě„ś 가장 ë§Žěť´ 사용ë는 í›…ěž…ë‹ë‹¤. íť”íž ě»´íŹ¬ë„ŚíŠ¸ě—서 필요한 데이터를 외부ě—서 가져ě¤ëŠ”(fetch) 용도로 ë§Žěť´ 사용ë©ë‹ë‹¤.
      <div id="app">
          <p>I’m text inside the component.</p>
      </div>
        new Vue({
          el: '#app',
          mounted: function() {
            console.log(this.$el.textContent); // I'm text inside the component.
          }
        })
    3. Updating (재 렌더ë§): Update 훅은 컴포넌트 ë‚´ë¶€ěť ë°ěť‘ě ěť¸ 속성이 변í–ę±°ë‚, ę·¸ ě™¸ěť ę˛ë“¤ěť´ 재 렌더ë§ěť„ 일으킬 때 실행ë는 단계입ë‹ë‹¤.

      1. beforeUpdate: beforeUpdate 훅은 ě»´íŹ¬ë„ŚíŠ¸ěť dataę°€ 변경ëě–´ 업데이트 사이í´ěť´ ě‹śěž‘ë  ë•Ś 실행ë©ë‹ë‹¤.
      <div id="app">
        <p>{{counter}}</p>
      </div>
      ...// rest of the code
        new Vue({
          el: '#app',
          data() {
            return {
              counter: 0
            }
          },
           created: function() {
            setInterval(() => {
              this.counter++
            }, 1000)
          },
      
          beforeUpdate: function() {
            console.log(this.counter) // Logs the counter value every second, before the DOM updates.
          }
        })
      1. updated: updated 훅은 ě»´íŹ¬ë„ŚíŠ¸ěť dataę°€ 변í•ě—¬ 재 렌더ë§ěť´ 일어난 í›„ě— ě‹¤í–‰ë©ë‹ë‹¤.
      <div id="app">
        <p ref="dom">{{counter}}</p>
      </div>
      ...//
        new Vue({
          el: '#app',
          data() {
            return {
              counter: 0
            }
          },
           created: function() {
            setInterval(() => {
              this.counter++
            }, 1000)
          },
          updated: function() {
            console.log(+this.$refs['dom'].textContent === this.counter) // Logs true every second
          }
        })
    4. Destruction(해체): Destruction 훅은 컴포넌트를 더 ěť´ě 사용í•ě§€ 않을 때 사용í•는 단계입ë‹ë‹¤.

      1. beforeDestroy: beforeDestroy 훅은 컴포넌트가 해체ë기 ě§ě „ě— ě‹¤í–‰ë©ë‹ë‹¤. ěť´ 훅은 ë°ěť‘ě ěť¸ ěť´ë˛¤íŠ¸ë“¤ěť´ë‚ data들을 해체í•는 훅으로 ě í•©í•©ë‹ë‹¤. ěť´ 단계ě—서 컴포넌트는 ě—¬ě „íž ë¬¸ě śě—†ěť´ ěž ëŹ™ěž‘í•©ë‹ë‹¤.
      new Vue ({
        data() {
          return {
            message: 'Welcome VueJS developers'
          }
        },
      
        beforeDestroy: function() {
          this.message = null
          delete this.message
        }
      })
      1. destroyed: destroyed 훅은 컴포넌트가 해체ëęł  난 ě§í›„ě— í¸ě¶śë©ë‹ë‹¤. 모든 지시ěžë“¤ěť 바인딩이 í•´ě śëě—으며, 이벤트 리스ë„ę°€ ě śę±°ëś ěíśěž…ë‹ë‹¤.
      new Vue ({
          destroyed: function() {
            console.log(this) // Nothing to show here
          }
        })
  4. 조건부 지시ěž(conditional directives)란

    VueJS는 ěˇ°ę±´ě— ë”°ëťĽ ě—리먼트를 ëł´ě—¬ěŁĽę±°ë‚ ě¨ę¸¸ ě ěžëŠ” 지시ěžë“¤ěť„ 제공합ë‹ë‹¤. 사용할 ě ěžëŠ” 지시ěžë“¤ěť€ v-if, v-else, v-else-if and v-showę°€ ěžěеë‹ë‹¤.

    1. v-if: v-if 지시ěžëŠ” ěˇ°ę±´ě— ë”°ëťĽ DOM ě—리먼트를 추가í•ę±°ë‚ ě śę±°í•©ë‹ë‹¤. ě를 들어, ě•„ëžěť 버튼은 isLoggedIněť ę°’ěť´ false라면 ë‚í€ë‚ě§€ 않습ë‹ë‹¤.

    <button v-if="isLoggedIn">Logout</button>

    ě—리먼트들을 <template> íśę·¸ëˇś ę°ě‹Ľë‹¤ë©´, í•ë‚ěť v-if만으로 여러 ě—ë¦¬ë¨ĽíŠ¸ë“¤ěť ěˇ°ę±´ěť„ 설정할 ě ěžěеë‹ë‹¤. ě를 들어, ě•„ëžě™€ 같이 label과 button íśę·¸ëĄĽ í•ë‚ěť ěˇ°ę±´ 지시ěžëˇś ě śě–´í•  ě ěžěеë‹ë‹¤.

    <template v-if="isLoggedIn">
      <label> Logout </button>
      <button> Logout </button>
    </template>

    2. v-else: 프로그ëžë°Ť 언어ě—서 ifěť ěˇ°ę±´ě— ë§žě§€ 않는 경우 else로 ë„어가는 ę˛ě˛ëźĽ, v-else 지시ěžëŠ” 인접한 v-if ě§€ě‹śěž ë는 v-else-if 지시ěžę°€ false일 때만 ę·¸ 내용이 ë‚í€ë‚©ë‹ë‹¤. ěť´ 지시ěžě—는 조건을 지정할 필요가 없습ë‹ë‹¤. ě를 들어, ě•„ëžěť ě시는 isLoggedIněť´ false일 때(즉 로그인 ëś ěíśę°€ ě•„ë‹ ë•Ś), v-else를 이용해 로그인 버튼을 보여줍ë‹ë‹¤.

    <button v-if="isLoggedIn"> Logout </button>
    <button v-else> Log In </button>

    3. v-else-if: v-else-if 지시ěžëŠ” v-if ěť´ě™¸ěť ë‹¤ëĄ¸ 조건을 추가로 확인해야 í•  때 사용합ë‹ë‹¤. ě를 들어, v-else-if 지시ěžëĄĽ 이용해 ifLoginDisableděť ę°’ěť´ true일 때는 로그인 버튼 대신 텍스트를 보여줄 ě ěžěеë‹ë‹¤.

    <button v-if="isLoggedIn"> Logout </button>
    <label v-else-if="isLoginDisabled"> User login disabled </label>
    <button v-else> Log In </button>

    4. v-show: v-show 지시ěžëŠ” v-if 지시ěžě™€ 비슷한 기능을 í•지만, DOMě— ě—리먼트가 ě¶”ę°€ëś ěíśě—서 CSSěť display ę°’ěť„ 이용해 보여주고 ě¨ęą€ěť„ 결정합ë‹ë‹¤. v-show 지시ěžëŠ” 조건문이 ěžěŁĽ í† ę¸€ë  ë•Ś 권장ë©ë‹ë‹¤.

    <span v-show="user.name">Welcome user,{{user.name}}</span>
  5. v-show와 v-ifěť ě°¨ěť´ě ěť€

    v-show와 v-ifěť ěŁĽěš” 차이ě ěť€ 다음과 같습ë‹ë‹¤.

    1. v-if는 조건이 일ěąí•는 ě—리먼트만 DOMě— ë ŚëŤ”ë§í•는 ë°ë©´, v-show는 모든 ě—리먼트를 DOMě— ë ŚëŤ”ë§í•ś 후 CSS를 이용해 내용을 ëł´ě—¬ěŁĽę±°ë‚ ě¨ęąë‹ë‹¤.
    2. v-if와 v-else-ifě—서는 v-else를 사용할 ě ěžě§€ë§Ś, v-showě—서는 사용할 ě 없습ë‹ë‹¤.
    3. v-if는 토글할 때 높은 ë ŚëŤ”ë§ ëą„ěš©ěť´ 들지만, v-show는 ě´ę¸°ěť ë ŚëŤ”ë§ ěž‘ě—…ě—서 높은 비용이 ë“­ë‹ë‹¤. 즉, v-show는 요소를 ěžěŁĽ 켜고 ë„는 경우 성능 ěěť ěť´ě ěť´ ěžě§€ë§Ś, ě´ę¸° ë ŚëŤ”ë§ ěž‘ě—…ě—서는 v-ifę°€ 더 효율ě ěž…ë‹ë‹¤.
    4. v-if는 <template>íśę·¸ě—서 사용할 ě ěžě§€ë§Ś v-show는 사용할 ě 없습ë‹ë‹¤.
  6. v-for를 쓰는 목ě ěť€

    v-for 지시ěžëŠ” ë°°ě—´ěť´ë‚ ę°ťě˛´ëĄĽ ěśí™í•면서 ë°ëłµě ěť¸ 렌더ë§ěť„ 가능í•게 í•©ë‹ë‹¤.

    1. ë°°ě—´ěť ę˛˝ěš°:
    <ul id="list">
      <li v-for="(item, index) in items">
        {{ index }} - {{ item.message }}
      </li>
    </ul>
    
    var vm = new Vue({
      el: '#list',
      data: {
        items: [
          { message: 'John' },
          { message: 'Locke' }
        ]
      }
    })

    ěžë°”스í¬ë¦˝íЏ ěśí™ë¬¸ęłĽ 유사í•게, in 외ě—도 of를 사용할 ě ěžěеë‹ë‹¤.

    1. ę°ťě˛´ěť ę˛˝ěš°:
    <div id="object">
      <div v-for="(value, key, index) in user">
        {{ index }}. {{ key }}: {{ value }}
      </div>
    </div>
    
    var vm = new Vue({
      el: '#object',
      data: {
        user: {
          firstName: 'John',
          lastName: 'Locke',
          age: 30
        }
      }
    })
  7. Vue 인스턴스란

    모든 Vue 어플리케이ě…은 Vue 함ě를 이용해 Vue 인스턴스를 ěťě„±í•면서 동작합ë‹ë‹¤. 일ë°ě ěśĽëˇś vm(ViewModelěť ě¶•ě•˝í•)이라는 변ě를 이용해 Vue 인스턴스를 참조합ë‹ë‹¤. ě•„ëžě™€ 같은 방법으로 Vue 인스턴스를 ěťě„±í•  ě ěžěеë‹ë‹¤.

    var vm = new Vue({
      // options
    })

    ěś„ěť ě˝”ë“śě—서 볼 ě ěžë“Ż, ěµě…ěť„ 설정í•기 위한 객체를 전달해야 í•©ë‹ë‹¤. ěť´ ěµě…은 API 문서ě—서 ěžě„¸íž 확인할 ě ěžěеë‹ë‹¤.

  8. 여러 ě—리먼트들을 한 ë˛ě— 조건부로 ë‚í€ë‚´ëŠ” 방법은

    렌더ë§ě— ěí–Ąěť„ 미ěąě§€ 않는 <template> íśę·¸ě— v-if 지시ěžëĄĽ ě ěš©í•¨ěśĽëˇśěŤ¨ 여러 ě—리먼트들을 한 ë˛ě— 조건부로 ë‚í€ë‚Ľ ě ěžěеë‹ë‹¤. ě를 들어, ě•„ëžě™€ 같이 유효한 사용ěžěť¸ ę˛˝ěš°ě— í•śí•´ě„ś ě‚¬ěš©ěž ě •ëł´ëĄĽ 보여줄 ě ěžěеë‹ë‹¤.

    <template v-if="condition">
      <h1>Name</h1>
      <p>Address</p>
      <p>Contact Details</p>
    </template>
  9. key 속성을 이용해 ě—리먼트를 재사용í•는 방법은

    Vue는 가능한 한 ě—리먼트를 효율ě ěśĽëˇś 렌더ë§í•ë ¤ í•©ë‹ë‹¤. ę·¸ëžě„ś ě—리먼트를 ě˛ěťŚë¶€í„° 다시 만들기보다는 재사용í•ë ¤ í•©ë‹ë‹¤. ę·¸ëź¬ë‚ ěť´ëŠ” 몇 가지 ě황ě—서 문제를 일으킬 ě ěžěеë‹ë‹¤. ě를 들어, input ě—리먼트를 v-if와 v-else 블록 양쪽ě—서 사용í•ë©´, input ě—리먼트는 ěˇ°ę±´ë¬¸ě— ë”°ëťĽ 바뀌지 않고 최ě´ě— ë ŚëŤ”ë§ ëś ě—ë¦¬ë¨ĽíŠ¸ěť ěíśëĄĽ ěś ě§€í•ęł  ěžěеë‹ë‹¤.

    <template v-if="loginType === 'Admin'">
      <label>Admin</label>
      <input placeholder="Enter your ID">
    </template>
    <template v-else>
      <label>Guest</label>
      <input placeholder="Enter your name">
    </template>

    ěť´ 경우ě—서 input ě—리먼트는 재사용ë어서는 ě• ë기 때문ě—, key 속성을 이용해 ë‘ ę°śěť input ě—리먼트를 ëł„ę°śěť ę˛ěśĽëˇś 취급í•도록 선언할 ě ěžěеë‹ë‹¤.

        <template v-if="loginType === 'Admin'">
          <label>Admin</label>
          <input placeholder="Enter your ID" key="admin-id">
        </template>
        <template v-else>
          <label>Guest</label>
          <input placeholder="Enter your name" key="user-name">
        </template>

    ěś„ěť ę˛˝ěš°ëŠ” ë‘ ę°śěť input ě—리먼트가 ëł„ę°śěť ę˛ěśĽëˇś 취급ëë©° 서로ě—게 ě–´ë–¤ ě향도 ëĽěąě§€ 않습ë‹ë‹¤.

  10. 같은 ě—리먼트ě—서 v-for와 v-if를 í•¨ę» ě“°ë©´ ě• ë는 이유는

    v-for 지시ěžëŠ” v-if 보다 더 높은 ěš°ě„  ěśěś„를 ę°–ęł  ěžę¸° 때문ě—, 한 ě—리먼트 ë‚´ě—서 v-for와 v-if를 í•¨ę» ě“°ëŠ” ę˛ěť€ 권장ëě§€ 않습ë‹ë‹¤. 일ë°ě ěśĽëˇś 다음과 같은 ěť´ěś  ë•Śë¬¸ě— ë‘ ě§€ě‹śěžëĄĽ í•¨ę» ě“°ęł¤ í•©ë‹ë‹¤.

    1. ë¦¬ěŠ¤íŠ¸ěť ěš”ě†ŚëĄĽ í•„í„°ë§í•기 위해 ě를 들어, v-if 지시ěžëĄĽ 이용해 ë¦¬ěŠ¤íŠ¸ě— ěžëŠ” ě•„ěť´í…śěť„ í•„í„°ë§í•ęł  싶은 경우입ë‹ë‹¤.
    <ul>
      <li
        v-for="user in users"
        v-if="user.isActive"
        :key="user.id"
      >
        {{ user.name }}
      <li>
    </ul>

    ěť´ 경우는 ě•„ëžě™€ 같이 ě‚¬ě „ě— computed 속성을 이용해 í•„í„°ë§ëś 리스트를 만들어 사용할 ě ěžěеë‹ë‹¤.

    computed: {
      activeUsers: function () {
        return this.users.filter(function (user) {
          return user.isActive
        })
      }
    }
    ...... //
    ...... //
    <ul>
      <li
        v-for="user in activeUsers"
        :key="user.id">
        {{ user.name }}
      <li>
    </ul>
    1. 리스트 ěžě˛´ę°€ ě¨ę˛¨ě ¸ě•Ľ í•  때 ě를 들어, v-if를 이용해 ë°ëłµë는 리스트를 ě¨ę¸°ęł  싶은 경우입ë‹ë‹¤.
    <ul>
      <li
        v-for="user in users"
        v-if="shouldShowUsers"
        :key="user.id"
      >
        {{ user.name }}
      <li>
    </ul>

    ěť´ 경우는 ě•„ëžě™€ 같이 조건문을 ěěś„ ě—리먼트로 ě®ęą€ěśĽëˇśěŤ¨ 해결할 ě ěžěеë‹ë‹¤.

    <ul v-if="shouldShowUsers">
      <li
        v-for="user in users"
        :key="user.id"
      >
        {{ user.name }}
      <li>
    </ul>
  11. v-forě—서 key 속성이 필요한 ěť´ěś 

    Vueě—서 ę°śëł„ DOM 노드들을 ě¶”ě í•ęł  기존 ě—ë¦¬ë¨ĽíŠ¸ěť ěž¬ě‚¬ěš©/재정렬을 위해, v-forěť ěš”ě†Śě— ęł ěś í•ś key 속성을 제공해야 í•©ë‹ë‹¤. keyě— ëŚ€í•ś ěť´ěě ěť¸ 값은 ę° í•­ëŞ©ěť„ 식별할 ě ěžëŠ” 고유한 IDěž…ë‹ë‹¤.

    <div v-for="item in items" :key="item.id">
      {{item.name}}
    </div>

    ë°ëłµë는 DOM 내용이 단ěśí•ś ę˛˝ěš°ë‚ ěťëŹ„ě ěť¸ 성능 í–Ąěěť„ 위해 기본 ëŹ™ěž‘ě— ěťěˇ´í•ě§€ 않는 경우를 제외í•ë©´, 가능í•ë©´ ě–¸ě śë‚ v-forě— key를 추가í•는 ę˛ěť´ 좋습ë‹ë‹¤. Note: ę°ťě˛´ë‚ ë°°ě—´ě˛ëźĽ, 기본 í€ěž…(Primitive value)ěť´ 아닌 ę°’ěť„ 키로 사용해서는 ě•ë©ë‹ë‹¤. 문ěžě—´ěť´ë‚ ě«ěžëĄĽ 사용í•세요.

  12. ë°°ě—´ěť„ 변화시키는 함ě(Mutation method)란

    이름ě—서 볼 ě ěžë“Ż, ë°°ě—´ěť„ 변화시키는 함ě(mutation methods)는 ě›ëł¸ ë°°ě—´ěť„ 변경시킵ë‹ë‹¤. ě•„ëžěť 함ě는 ë·°(view) 업데이트를 일으킵ë‹ë‹¤.

    1. push()
    2. pop()
    3. shift()
    4. unshift()
    5. splice()
    6. sort()
    7. reverse()

    ě를 들어, ě•„ëžě™€ 같이 todos ë°°ě—´ě— push 함ě를 실행시키면 ë·° 업데이트가 일어납ë‹ë‹¤.

    vm.todos.push({ message: 'Baz' })
  13. ë°°ě—´ěť„ 대체í•는 함ě(Non-mutation method)란

    ë°°ě—´ěť„ 대체í•는 함ě는 ě›ëł¸ ë°°ě—´ěť„ ěě •í•ě§€ 않고, í•­ě ě로운 ë°°ě—´ěť„ ë°í™í•©ë‹ë‹¤. ě•„ëžěť 함ě는 ë°°ě—´ěť„ 대체í•는 함ěěž…ë‹ë‹¤.

    1. filter()
    2. concat()
    3. slice()

    ě를 들어, ě•„ëžě™€ 같이 status ě†Ťě„±ě— ë”°ëťĽ todos ë°°ě—´ěť„ í•„í„°ë§í•ś ě로운 ë°°ě—´ěť„ ë°í™ë°›ěť„ ě ěžěеë‹ë‹¤.

    vm.todos = vm.todos.filter(function (todo) {
      return todo.status.match(/Completed/)
    })

    Vueę°€ DOMěť„ 효율ě ěśĽëˇś 재사용í•기 때문ě—, 전체 리스트가 ě로 렌더ë§ë지는 않습ë‹ë‹¤.

  14. ë°°ě—´ 변경을 í지할 때 주ěťí•  ě 

    Vue는 ě•„ëžěť ë‘ ę°€ě§€ ę˛˝ěš°ěť ëł€ę˛˝ 사항을 ę°ě§€í•  ě 없습ë‹ë‹¤.

    1. 인덱스로 ë°°ě—´ě— ěžëŠ” 항목을 ě§ě ‘ 할당í•는 경우
    vm.todos[indexOfTodo] = newTodo
    1. ë°°ě—´ěť ę¸¸ěť´ëĄĽ ěě •í•는 경우
    vm.todos.length = todosLength

    이는 set과 splice 함ě를 이용해 해결할 ě ěžěеë‹ë‹¤.

    첫 ë˛ě§¸ 경우

    // Vue.set
    Vue.set(vm.todos, indexOfTodo, newTodoValue)
    // Array.prototype.splice
    vm.todos.splice(indexOfTodo, 1, newTodoValue)

    ë‘ ë˛ě§¸ 경우

    vm.todos.splice(todosLength)
  15. 객체 변경을 í지할 때 주ěťí•  ě 

    Vue는 추가ëę±°ë‚ ě‚­ě śëś ě†Ťě„±ě— ë°ěť‘í•으로 ě ‘ę·Ľí•  ě 없습ë‹ë‹¤.

    var vm = new Vue({
      data: {
        user: {
          name: 'John'
        }
      }
    })
    
    // `vm.name` is now reactive
    
    vm.email = john@email.com // `vm.email` is NOT reactive

    ěť´ 경우는 Vue.set(object, key, value)ë‚ Object.assign()를 이용함으로써 ë°ěť‘í• ě†Ťě„±ěť„ 추가할 ě ěžěеë‹ë‹¤.

    Vue.set(vm.user, 'email', john@email.com);
    vm.user = Object.assign({}, vm.user, {
      email: john@email.com
    })
  16. v-for를 특정 íšźěë§ŚíĽ ë°ëłµí•는 방법은?

    v-for 지시ěžě— ě •ě를 사용해 특정 íšźěë§ŚíĽ ë°ëłµí•´ ë ŚëŤ”ë§ í•  ě ěžěеë‹ë‹¤.

    <div>
      <span v-for="n in 20">{{ n }} </span>
    </div>

    ěť´ 경우 1부터 20까지 ě«ěžę°€ ě¶śë Ąë©ë‹ë‹¤.

  17. v-for로 템플릿을 ë°ëłµí•는 방법은

    <template>ě—서 v-if를 사용한 ę˛ęłĽ 유사í•게, <template>ě—서 v-for 문법을 사용할 ě ěžěеë‹ë‹¤.

    <ul>
      <template v-for="todo in todos">
        <li>{{ todo.title }}</li>
        <li class="divider"></li>
      </template>
    </ul>
  18. 이벤트 핸들러를 사용í•는 방법은?

    VueJSě—서는 ěśě ěžë°”스í¬ë¦˝íŠ¸ě™€ 유사í•게 이벤트 핸들러를 사용할 ě ěžěеë‹ë‹¤. 함ěě—서 $event 변ě를 í¸ě¶śí•´ 사용할 ě ěžěеë‹ë‹¤.

    <button v-on:click="show('Welcome to VueJS world', $event)">
      Submit
    </button>
    
    methods: {
      show: function (message, event) {
        // now we have access to the native event
        if (event) event.preventDefault()
        console.log(message);
      }
    }
  19. Vueě—서 이벤트 ě식어(Event modifier)란?

    일ë°ě ěśĽëˇś ěžë°”스í¬ë¦˝íЏě—서는 이벤트 핸들러 ë‚´ë¶€ě—서 event.preventDefault() ë는 event.stopPropagation()를 제공합ë‹ë‹¤. Vueěť ë©”ě†Śë“ś ë‚´ë¶€ě—서도 ěť´ 작업을 í•  ě ěžě§€ë§Ś, DOMě—서 ë°śěťí•ś 이벤트와 ë©”ě†Śë“śěť ëˇśě§ěť€ 별개로 구분í•는 ę˛ěť´ 좋습ë‹ë‹¤.

    ěť´ 문제를 해결í•기 위해, Vue는 v-on ěť´ë˛¤íŠ¸ě— ěť´ë˛¤íŠ¸ ě식어를 제공합ë‹ë‹¤. ě식어는 ě ěśĽëˇś í‘śě‹śëś ě ‘ëŻ¸ě‚¬ ěž…ë‹ë‹¤.

    1. .stop
    2. .prevent
    3. .capture
    4. .self
    5. .once
    6. .passive

    .stop ě식어를 ě로 들어보겠습ë‹ë‹¤.

    <!-- the click event's propagation will be stopped -->
    <a v-on:click.stop="methodCall"></a>

    ě식어는 연속해서 사용할 ě ěžěеë‹ë‹¤.

    <!-- modifiers can be chained -->
    <a v-on:click.stop.prevent="doThat"></a>
  20. 키 ě식어(Key modifiers)란?

    Vue는 키보드 이벤트를 ě śě–´í•기 위해 v-on 지시ěžě— 키 ě식어를 제공합ë‹ë‹¤.

    <!-- only call `vm.show()` when the `keyCode` is 13 -->
    <input v-on:keyup.13="show">

    모든 키 코드를 외우는 ę˛ěť€ 어렵기 때문ě—, Vueě—서는 ěžěŁĽ 사용ë는 키들은 별칭을 ě śęłµí•ęł  ěžěеë‹ë‹¤.

    1. .enter
    2. .tab
    3. .delete (“Delete”와 “Backspace” 포함)
    4. .esc
    5. .space
    6. .up
    7. .down
    8. .left
    9. .right

    ěś„ ěě‹śěť í‚¤ 코드는 ě•„ëžě™€ 같이 별칭으로 다시 쓸 ě ěžěеë‹ë‹¤.

    <input v-on:keyup.enter="submit">
    // (OR)
    <!-- with shorthand notation-->
    <input @keyup.enter="submit">

    키 코드 ěť´ë˛¤íŠ¸ěť ě‚¬ěš©ěť€ 최신 브라우저ě—서는 ě§€ě›ëě§€ 않을 ě ěžěеë‹ë‹¤.

  21. 키 ě식어를 커스터ë§ěť´ě§•í•는 방법은?

    ě „ě—­ config.keyCodes 객체를 통해 키 ě식어를 커스터ë§ěť´ě§•í•  ě ěžěеë‹ë‹¤. 여기ě—는 몇 가지 규칙들이 ěžěеë‹ë‹¤.

    1. 카멜 케이스(camelCase)를 대신 쌍따ě´í‘śëˇś ę°ě‹¸ě§„ 케밥 케이스(Kebab-case)를 사용해야 í•©ë‹ë‹¤.
    2. ë°°ě—´ěť„ 이용해 한 ë˛ě— 여러 값들을 ě •ěťí•  ě ěžěеë‹ë‹¤.
    Vue.config.keyCodes = {
      f1: 112,
      "media-play-pause": 179,
      down: [40, 87]
    }
  22. 시스템 ě식어 키(System modifier key)란?

    Vueě—서는 다음 ě식어를 사용해 해당 ě식어 키가 ëŚëź¬ě§„ 경우ě—ë§Ś ë§ěš°ěФ ë는 키보드 이벤트를 ë°śěťě‹śí‚¬ ě ěžěеë‹ë‹¤.

    1. .ctrl
    2. .alt
    3. .shift
    4. .meta

    ě•„ëžëŠ” 컨트롤 키가 ëŚë¦° ěíśě—서 í´ë¦­ 이벤트를 활성화 í•는 ě시입ë‹ë‹¤.

    <!-- Ctrl + Click -->
    <div @click.ctrl="doSomething">Do something</div>
  23. ë§ěš°ěФ 버튼 ě식어(Mouse button modifier)란?

    Vue는 특정한 ë§ěš°ěФ 버튼으로 ë°śěťí•ś 이벤트를 ě śě–´í•  ě ěžěеë‹ë‹¤.

    1. .left
    2. .right
    3. .middle

    ë§ěš°ěФ 이벤트로 .right를 이용한 ě시입ë‹ë‹¤.

     <button
       v-if="button === 'right'"
       v-on:mousedown.right="increment"
       v-on:mousedown.left="decrement"
     />
  24. v-modelěť ě—­í• ěť€?

    v-model 지시ěžëĄĽ 이용해 input, textarea, select ě—ë¦¬ë¨ĽíŠ¸ěť ëŤ°ěť´í„°ëĄĽ 양방향으로 ě śě–´í•  ě ěžěеë‹ë‹¤. ě•„ëžěť input ě—리먼트를 살펴보세요.

    <input v-model="message" placeholder="Enter input here">
    <p>The message is: {{ message }}</p>

    v-model은 모든 form ě—리먼트ě—서 HTML 속성(attribute)으로 ě„ ě–¸ëś value, checked 그리고 selected를 무시합ë‹ë‹¤. ę·¸ 대신 Vue 인스턴스ě—서 v-model로 바인딩한 ę°’ěť„ 이용합ë‹ë‹¤. 따라서 ě»´íŹ¬ë„ŚíŠ¸ěť dataě—서 ě´ę¸°ę°’ěť„ 선언해야 í•©ë‹ë‹¤.

  25. v-modelě—서 ě§€ě›ë는 ě식어는?

    v-model 지시ěžě—는 세 가지 ě식어가 ě§€ě›ë©ë‹ë‹¤.

    1. lazy: 기본ě ěśĽëˇś, v-model은 í•ë‚ěť í‚¤ ěž…ë Ą 이벤트가 ë°śěťí•  때ë§ë‹¤ dataę°€ 업데이트ë©ë‹ë‹¤. 이를 ë°©ě§€í•기 위해서는 .lazy ě식어를 이용합ë‹ë‹¤.

    <!-- synced after "change" instead of "input" -->
    <input v-model.lazy="msg" >

    2. number: v-modelě— .number ě식어를 붙이면 ěžëŹ™ě ěśĽëˇś 사용ěžěť ěž…ë Ąěť ěžëŁŚí•ěť´ Number로 변í™ë©ë‹ë‹¤. HTML input íśę·¸ěť 속성이 type="number"일지라도 ë°í™ë는 ę°’ěť ěžëŁŚí•은 문ěžě—´ěť´ę¸° 때문ě—, ě«ěž ěžëŁŚí•ěť´ í•„ěš”í•다면 .number ě식어를 사용해야 í•©ë‹ë‹¤.

    <input v-model.number="age" type="number">

    3. trim: .trim ě식어를 ě‚¬ěš©ěž ěž…ë Ąě—서 ě˛ěťŚęłĽ ëťě— 들어ěžëŠ” 공백을 ěžëŹ™ěśĽëˇś 제거해줍ë‹ë‹¤.

    <input v-model.trim="msg">
  26. 컴포넌트(Component)란?

    컴포넌트란 재사용 가능í•면서 이름이 ëŞ…ëŞ…ëś Vue 인스턴스입ë‹ë‹¤. 컴포넌트는 Vueě˛ëźĽ data, computed, watch, methods, ëťĽěť´í”„ě‚¬ěť´í´ ěµě…ěť„ ę°–ęł  ěžěеë‹ë‹¤. ě•„ëžëŠ” Vueě— ě „ě—­ěśĽëˇś 컴포넌트를 추가í•는 ě시입ë‹ë‹¤.

    // Define a new component called button-counter
    Vue.component('button-counter', {
      template: '<button v-on:click="count++">You clicked me {{ count }} times.</button>'
      data: function () {
        return {
          count: 0
        }
      },
    })

    ěť´ 컴포넌트는 전역으로 ě„ ě–¸ëě—기 ë•Śë¬¸ě— Vue 인스턴스ě—서 사용할 ě ěžěеë‹ë‹¤.

    <div id="app">
      <button-counter></button-counter>
    </div>
    
    var vm = new Vue({ el: '#app' });
  27. props란?

    props는 ěěś„ ě»´íŹ¬ë„ŚíŠ¸ěť ě •ëł´ëĄĽ í•ěś„ 컴포넌트로 전달할 ě ěžëŠ” ě‚¬ěš©ěž ě§€ě •ěť ě†Ťě„±ěž…ë‹ë‹¤. ěěś„ 컴포넌트ě—서 전달ë는 props는 í•ěś„ ě»´íŹ¬ë„ŚíŠ¸ěť ě†Ťě„±ěśĽëˇś 여겨지며, í•ěś„ 컴포넌트ě—서는 props ěµě…ěť„ 사용í•ě—¬ ěě‹ í•  ę˛ěśĽëˇś ěěë는 props를 명시ě ěśĽëˇś 선언해야 í•©ë‹ë‹¤.

    Vue.component('todo-item', {
      props: ['title'],
      template: '<h2>{{ title }}</h2>'
    })

    í•ěś„ 컴포넌트ě—서 propsę°€ 등록ëęł  ë‚ë©´, ěěś„ 컴포넌트ě—서는 ě‚¬ěš©ěž ě§€ě • 속성을 이용해 ę°’ěť„ 전달할 ě ěžěеë‹ë‹¤.

    <todo-item title="Learn Vue conceptsnfirst"></todo-item>
  28. 컴포넌트ě—서 여러 ě—리먼트를 쓰려면?

    템플릿이 여러 ę°śěť ě—리먼트들로 구성ëě–´ ěžěť„ 때, ě»´íŹ¬ë„ŚíŠ¸ěť ěµśě단 템플릿은 ë°ë“śě‹ś 단일 ě—리먼트로 ę°ě‹¸ě ¸ ěžě–´ě•Ľ í•©ë‹ë‹¤.

    <div class="todo-item">
      <h2>{{ title }}</h2>
      <div v-html="content"></div>
    </div>

    그렇지 않다면, "Component template should contain exactly one root element..."라는 ě—러를 ë°śěťě‹śí‚µë‹ë‹¤.

  29. í•ěś„ 컴포넌트ě—서 ěěś„ 컴포넌트로 이벤트를 전달í•는 방법은?

    í•ěś„ 컴포넌트ě—서 $emit 객체를 이용해 ěěś„ 컴포넌트로 이벤트를 ë°śěťí‚¬ ě ěžěеë‹ë‹¤.

    Vue.component('todo-tem', {
      props: ['todo'],
      template: `
        <div class="todo-item">
          <h3>{{ todo.title }}</h3>
          <button v-on:click="$emit('increment-count', 1)">
            Add
          </button>
          <div v-html="todo.description"></div>
        </div>
      `
    })

    ěť´ 때 ěěś„ 컴포넌트ě—서는 v-on 지시ěžëĄĽ 이용해 í•ěś„ 컴포넌트ě—서 명명한 이벤트와 ę°’ěť„ 사용할 ě ěžěеë‹ë‹¤.

    <ul v-for="todo in todos">
     <li>
       <todo-item
         v-bind:key="todo.id"
         v-bind:todo="todo"
         v-on:increment-count="total += 1">
       </todo-item>
     </li>
    </ul>
    <span> Total todos count is {{total}}</span>
  30. ě‚¬ěš©ěž ě •ěťěť input 컴포넌트ě—서 v-modelěť„ 사용í•는 법은?

    ě‚¬ěš©ěž ě •ěť input 컴포넌트ě—서도 v-modelěť„ 활용할 ě ěžěеë‹ë‹¤. 해당 ě»´íŹ¬ë„ŚíŠ¸ěť input은 ě•„ëž ę·śěą™ë“¤ěť„ 준ě해야 í•©ë‹ë‹¤.

    1. inputěť value를 props를 이용해 바인딩합ë‹ë‹¤.
    2. ě로운 ę°’ěť´ ěž…ë Ąë는 input 이벤트 ë°śěť ě‹ś, 해당 ę°’ěť„ emití•ě—¬ ěěś„ 컴포넌트로 이벤트를 전달합ë‹ë‹¤.
    Vue.component('custom-input', {
      props: ['value'],
      template: `
        <input
          v-bind:value="value"
          v-on:input="$emit('input', $event.target.value)"
        >
      `
    })

    ěť´ 경우 ěěś„ 컴포넌트ě—서 v-modelěť„ 이용해 ę°’ěť„ 바인딩할 ě ěžěеë‹ë‹¤.

    <custom-input v-model="searchInput"></custom-input>
  31. slots이란?

    Vueě—서는 <slot>ěť„ 이용해 ěěś„ 컴포넌트ě—서 í•ěś„ 컴포넌트 ë‚´ë¶€ě— ě‚¬ěš©ěž ě •ěťěť 컨í…츠를 ě§‘ě–´ 넣을 ě ěžěеë‹ë‹¤. í•ěś„ ě»´íŹ¬ë„ŚíŠ¸ě— <slot>ěť„ 이용해 문구를 동ě ěśĽëˇś 넣을 ě ěžëŠ” 컴포넌트를 만들어봅시다.

    Vue.component('alert', {
      template: `
        <div class="alert-box">
          <strong>Error!</strong>
          <slot></slot>
        </div>
      `
    })

    <alert> íśę·¸ ě•ě— ë„Łěť€ 값은 컴포넌트 ë‚´ë¶€ěť <slot>ěť ě»¨í…츠로 들어가게 ë©ë‹ë‹¤.

    <alert>
      There is an issue with in application.
    </alert>
  32. 컴포넌트를 ě „ě—­ 등록í•는 방법은?

    컴포넌트를 전역으로 등록í•게 ëë©´ 모든 Vue 인스턴스ě—서 해당 컴포넌트를 사용할 ě ěžěеë‹ë‹¤. 컴포넌트는 Vue.component() 함ě를 이용해 ě „ě—­ 등록할 ě ěžěеë‹ë‹¤.

    Vue.component('my-component-name', {
      // ... options ...
    })

    Vue ěť¸ěŠ¤í„´ěŠ¤ě— ě—¬ëź¬ ę°śěť ě»´íŹ¬ë„ŚíŠ¸ëĄĽ ě „ě—­ 등록해봅시다.

    Vue.component('component-a', { /* ... */ })
    Vue.component('component-b', { /* ... */ })
    Vue.component('component-c', { /* ... */ })
    
    new Vue({ el: '#app' })

    ěś„ěť ě»´íŹ¬ë„ŚíŠ¸ë“¤ěť€ Vue 인스턴스 ë‚´ě—서 ě‚¬ěš©ë  ě ěžěеë‹ë‹¤.

    <div id="app">
      <component-a></component-a>
      <component-b></component-b>
      <component-c></component-c>
    </div>

    전역으로 등록한 컴포넌트들은 í•ěś„ 컴포넌트ě—서도 사용이 가능합ë‹ë‹¤.

  33. ě»´íŹ¬ë„ŚíŠ¸ěť ě§€ě—­ 등록이 필요한 이유는?

    ě „ě—­ 등록으로 인해 사용ëě§€ 않는 컴포넌트가 빌드 ě‹śě— ě—¬ě „íž ë‚¨ě•„ěžěť„ ě ěžěеë‹ë‹¤. 이는 ë¶í•„요한 ěžë°”스í¬ë¦˝íŠ¸ëĄĽ 만들죠. 이를 ë°©ě§€í•기 위해, ě•„ëžě™€ 같이 컴포넌트를 지역 등록할 ě ěžěеë‹ë‹¤.

    1. ěš°ě„  ěžë°”스í¬ë¦˝íЏ 객체로 컴포넌트를 ě •ěťí•©ë‹ë‹¤.
    var ComponentA = { /* ... */ }
    var ComponentB = { /* ... */ }
    var ComponentC = { /* ... */ }

    지역 등록한 컴포넌트는 다른 ě»´íŹ¬ë„ŚíŠ¸ěť í•ěś„ě—서는 사용할 ě 없습ë‹ë‹¤. ěť´ 경우, components 속성으로 컴포넌트를 추가해 사용할 ě ěžěеë‹ë‹¤.

    var ComponentA = { /* ... */ }
    
    var ComponentB = {
      components: {
        'component-a': ComponentA
      },
      // ...
    }
    1. Vue 인스턴스ě—서 components ě†Ťě„±ě— ě‚¬ěš©í•  컴포넌트들을 ě •ěťí•  ě ěžěеë‹ë‹¤.
    new Vue({
      el: '#app',
      components: {
        'component-a': ComponentA,
        'component-b': ComponentB
      }
    })
  34. ëŞ¨ë“ ě‹śěŠ¤í…śě—서 ě „ě—­ 등록과 지역 ë“±ëˇťěť ě°¨ěť´ě ěť€?

    지역 ë“±ëˇťěť ę˛˝ěš°, ę° ě»´íŹ¬ë„ŚíŠ¸ëĄĽ ë””ë ‰í† ë¦¬ě— ěťě„±í•ęł  ę°ę°ěť 컴포넌트는 다른 컴포넌트 ě•ě—서 import í•ě—¬ 사용í•는 ę˛ěť´ 권장ë©ë‹ë‹¤. ë§Śě•˝ 여러분들이 컴포넌트 Cě—서 컴포넌트 A와 B를 사용í•ęł  싶다면 ě•„ëžě™€ 같은 설정을 해야 í•©ë‹ë‹¤.

    import ComponentA from './ComponentA'
    import ComponentB from './ComponentC'
    
    export default {
      components: {
        ComponentA,
        ComponentB
      }
    }

    ěś„ěť ę˛˝ěš° 컴포넌트 A와 컴포넌트 B는 컴포넌트 Cěť í…śí”Śë¦żě—서 사용할 ě ěžěеë‹ë‹¤.

    ě „ě—­ ë“±ëˇťěť ę˛˝ěš°, 공통ě ěśĽëˇś 사용ë는 컴포넌트를 ę°ę°ěť 파일ě—서 export해야합ë‹ë‹¤. í•지만 webpack과 같은 유명한 ë˛ë“¤ëź¬ë“¤ěť€ require.context라는 문법을 이용해서 컴포넌트를 쉽게 ě „ě—­ě ěśĽëˇś 등록할 ě ěžę˛Ś 해줍ë‹ë‹¤.

    import Vue from 'vue'
    import upperFirst from 'lodash/upperFirst'
    import camelCase from 'lodash/camelCase'
    
    const requireComponent = require.context(
      // The relative path of the components folder
      './components',
      // Whether or not to look in subfolders
      false,
      // The regular expression used to match base component filenames
      /Base[A-Z]\w+\.(vue|js)$/
    )
    
    requireComponent.keys().forEach(fileName => {
      // Get component config
      const componentConfig = requireComponent(fileName)
    
      // Get PascalCase name of component
      const componentName = upperFirst(
        camelCase(
          // Strip the leading `./` and extension from the filename
          fileName.replace(/^\.\/(.*)\.\w+$/, '$1')
        )
      )
    
      // Register component globally
      Vue.component(
        componentName,
        // Look for the component options on `.default`, which will
        // exist if the component was exported with `export default`,
        // otherwise fall back to module's root.
        componentConfig.default || componentConfig
      )
    })
  35. Prop í€ěž…ěť ě˘…ëĄëŠ”?

    propsě—는 í€ěž…ěť„ 지정할 ě도, 지정í•ě§€ 않을 ě도 ěžěеë‹ë‹¤. í•지만 일ë°ě ěśĽëˇś í€ěž…ěť„ 지정í•ë©´ 다른 ę°śë°śěžë“¤ěť´ 해당 코드ě—서 ěžëŞ»ëś í€ěž…ěť props를 ë„겨주는 실ě를 줄여주기 때문ě—, 가능í•ë©´ í€ěž…ěť„ 지정해주는 ę˛ěť´ 좋습ë‹ë‹¤.

    props: {
      name: String,
      age: Number,
      isAuthenticated: Boolean,
      phoneNumbers: Array,
      address: Object
    }

    props ę°ťě˛´ěť ě†Ťě„±ęłĽ ę°’ěť„ 선언함으로서, í€ěž…ěť„ 선언할 ě ěžěеë‹ë‹¤.

  36. propsě— ěťí•ś 데이터 íťë¦„은?

    모든 props는 í•ěś„ 속성과 ěěś„ 속성 사이ě—서 단방향 바인딩을 í•성합ë‹ë‹¤. 즉, ěěś„ 속성이 변경ë는 ę˛ěť€ í•ěś„ 속성ě—게 전달ë지만, ę·¸ ë°ëŚ€ëŠ” ě•ë©ë‹ë‹¤. ě›ěą™ě ěśĽëˇś, í•ěś„ 컴포넌트ě—서는 ěěś„ 컴포넌트ě—서 받은 propsěť„ ě정해서는 ě•ë©ë‹ë‹¤.

    í•ěś„ 컴포넌트ě—서 props ěě •ěť í•„ěš”ě„±ěť„ ëŠë‚„ ě ěžëŠ” 몇 가지 경우가 ěžëŠ”ëŤ°, ě•„ëžě™€ 같은 방법으로 해결할 ě ěžěеë‹ë‹¤.

    1. ěěś„ ě»´íŹ¬ë„ŚíŠ¸ěť props는 í•ěś„ ě»´íŹ¬ë„ŚíŠ¸ěť ě´ę¸°ę°’ 설정ě—ë§Ś 사용ëęł  ę·¸ 이후ě—는 로컬 데이터 속성으로 활용ë는 경우:

    ěť´ 경우, í•ěś„ 컴포넌트ě—서 사용할 속성을 dataě— ě„ ě–¸í•ęł , ę·¸ ę°’ěť„ props로 ě´ę¸°í™”í•ë©´ ë©ë‹ë‹¤.

    props: ['defaultUser'],
    data: function () {
      return {
        username: this.defaultUser
      }
    }
    1. ěěś„ 컴포넌트ě—서 props로 전해주는 ę°’ěť´ ěě •ë는 경우

    ěť´ 경우, í•ěś„ 컴포넌트ě—서 computed 속성을 이용해 propsěť ę°’ěť´ 바뀔 때ë§ë‹¤ ě‹ ę·ś ę°’ěť„ 얻을 ě ěžěеë‹ë‹¤.

    props: ['environment'],
    computed: {
      localEnvironment: function () {
        return this.environment.trim().toUpperCase()
      }
    }
  37. Props가 아닌 속성은?

    propsę°€ 아닌 속성이란, ě»´íŹ¬ë„ŚíŠ¸ě— ě „ë‹¬ë기는 í•지만 해당 propsę°€ í•ěś„ 컴포넌트ě—서 ě •ěťë지는 않은 속성을 ë§í•©ë‹ë‹¤. ë§Śě•˝ data-tooltip 속성을 요구í•는 컴포넌트를 사용í•ęł  ěžë‹¤ęł  가정해봅시다. ěť´ 속성을 컴포넌트 ěť¸ěŠ¤í„´ěŠ¤ě— ë‹¤ěťŚęłĽ 같이 추가 í•  ě ěžěеë‹ë‹¤.

    <custom-input data-tooltip="Enter your input" />

    ěěś„ 컴포넌트ě—서부터 propsę°€ 아닌 속성을 ë„겨주려 한다면, í•ěś„ 컴포넌트ě—서 같은 이름을 가진 속성은 덮어씌워집ë‹ë‹¤. í•지만 classë‚ style같은 props는 ě외로, ěť´ 값들은 í•ěś„ 컴포넌트와 í•©ěłě§‘ë‹ë‹¤.

    //Parent component
    <custom-input class="custom-class" />
    
    //Child component
    <input type="date" class="date-control">
  38. props를 검증í•는 방법은?

    Vueě—서는 í€ěž…, í•„ě 여부, 디폴트 ę°’ 등 propsěť ěś íš¨ě„± 검증을 ě śęłµí•ęł  ěžěеë‹ë‹¤. ě•„ëžě™€ 같이 props를 검증í•는 규칙이 속성으로 담긴 객체를 ě śęłµí•ë©´ ë©ë‹ë‹¤.

    Vue.component('user-profile', {
      props: {
        // Basic type check (`null` matches any type)
        age: Number,
        // Multiple possible types
        identityNumber: [String, Number],
        // Required string
        email: {
          type: String,
          required: true
        },
        // Number with a default value
        minBalance: {
          type: Number,
          default: 10000
        },
        // Object with a default value
        message: {
          type: Object,
          // Object or array defaults must be returned from
          // a factory function
          default: function () {
            return { message: 'Welcome to Vue' }
          }
        },
        // Custom validator function
        location: {
          validator: function (value) {
            // The value must match one of these strings
            return ['India', 'Singapore', 'Australia'].indexOf(value) !== -1
          }
        }
      }
    })
  39. 컴포넌트ě—서 v-modelěť„ ě‚¬ěš©ěž ě •ěťí•는 방법은?

    일ë°ě ěť¸ 컴포넌트ě—서 v-model 지시ěžëŠ” value를 props로 사용í•ęł  inputěť„ 이벤트로 사용í•지만, ě˛´í¬ ë°•ěŠ¤ë‚ ëťĽë””ě¤ ë˛„íŠĽę°™ěť€ 일부 ěž…ë Ą í€ěž…은 다른 목ě ěśĽëˇś value 속성을 사용할 ě ěžěеë‹ë‹¤. ěť´ëź° 경우ě—는 v-modelěť„ 커스터ë§ěť´ě§•해서 사용í•는 ę˛ěť´ 좋습ë‹ë‹¤.

    Vue.component('custom-checkbox', {
      model: {
        prop: 'checked',
        event: 'change'
      },
      props: {
        checked: Boolean
      },
      template: `
        <input
          type="checkbox"
          v-bind:checked="checked"
          v-on:change="$emit('change', $event.target.checked)"
        >
      `
    })

    ěť´ 컴포넌트ě—서 v-model은 다음과 같이 사용할 ě ěžěеë‹ë‹¤.

    <custom-checkbox v-model="selectFramework"></custom-checkbox>

    selectFramework 속성은 props 중 checked로 ë„ě–´ę° ę˛ěť´ęł , ě˛´í¬ ë°•ěŠ¤ 컴포넌트ě—서 ę°’ěť´ 변경ëë©´ 이벤트를 ë°śěťě‹śí‚¬ ę˛ěž…ë‹ë‹¤.

  40. íŠ¸ëžśě§€ě… íš¨ęłĽëĄĽ 넣을 ě ěžëŠ” 방법은?

    Vueě—서는 항목들이 DOMě—서 추가, 갱신 ë는 ě‚­ě śë  ë•Ś, 다양한 방법으로 íŠ¸ëžśě§€ě… íš¨ęłĽëĄĽ ěž…íž ě ěžěеë‹ë‹¤.

    1. CSS 트랜지ě…과 ě• ë‹ë©”ěť´ě…ěť„ 위한 í´ëžěŠ¤ëĄĽ ěžëŹ™ěśĽëˇś ě ěš©
    2. Animate.css와 같은 써드파티 CSS ě• ë‹ë©”ěť´ě… ëťĽěť´ë¸Śëź¬ë¦¬ 통합
    3. íŠ¸ëžśě§€ě… í›… ě¤‘ě— JavaScript를 사용í•ě—¬ DOMěť„ ě§ě ‘ 조작
    4. Velocity.js와 같은 써드파티 JavaScript ě• ë‹ë©”ěť´ě… ëťĽěť´ë¸Śëź¬ë¦¬ 통합
  41. Vue Router란?

    Vue Router는 Vueě—서 동작í•는 공식ě ěť¸ 라우팅 라이브러리입ë‹ë‹¤.

    1. ě¤‘ě˛©ëś ëťĽěš°íŠ¸/ë·° 매핑
    2. 모ë“í™”ëś, 컴포넌트 기ë°ěť 라우터 설정
    3. 라우터 파라미터, 쿼리, 와일드카드
    4. Vueěť íŠ¸ëžśě§€ě… ě‹śěŠ¤í…śěť„ 이용한 íŠ¸ëžśě§€ě… íš¨ęłĽ
    5. 세밀한 ë„¤ëą„ę˛Śěť´ě… ě»¨íŠ¸ëˇ¤
    6. active CSS í´ëžěŠ¤ëĄĽ ěžëŹ™ěśĽëˇś 추가해주는 ë§í¬
    7. HTML5 ížěŠ¤í† ë¦¬ 모드 ë는 해시 모드(IE9ě—서 ěžëŹ™ěśĽëˇś 폴백)
    8. ě‚¬ěš©ěž ě •ěť ę°€ëŠĄí•ś 스í¬ëˇ¤ 동작
  42. Vue Router를 사용í•는 방법은?

    Vue를 사용í•ęł  ěžë‹¤ë©´, 쉽게 Vue Router를 통합할 ě ěžěеë‹ë‹¤.

    Step 1: 먼저 템플릿ě—서 <router-link>íśę·¸ëĄĽ 설정합ë‹ë‹¤.

    <script src="https://unpkg.com/vue/dist/vue.js"></script>
    <script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>
    
    <div id="app">
      <h1>Welcome to Vue routing app!</h1>
      <p>
        <!-- use router-link component for navigation using `to` prop. It rendered as an `<a>` tag -->
        <router-link to="/home">Home</router-link>
        <router-link to="/services">Services</router-link>
      </p>
      <!-- route outlet in which component matched by the route will render here -->
      <router-view></router-view>
    </div>

    Step 2: main.jsě—서 Vue와 Vue 라우터를 importí•ęł  Vue.use()함ě를 이용해 í¸ě¶śí•©ë‹ë‹¤.

    import Vue from 'vue';
    import VueRouter from 'vue-router';
    
    Vue.use(VueRouter)

    Step 3: 라우트 컴포넌트를 ě •ěťí•ę±°ë‚ importí•©ë‹ë‹¤.

    const Home = { template: '<div>Home</div>' }
    const Services = { template: '<div>Services</div>' }

    Step 4: 라우트를 ě •ěťí•©ë‹ë‹¤. ę° ëťĽěš°íŠ¸ëŠ” ë°ë“śě‹ś 컴포넌트와 매핑ë어야 í•©ë‹ë‹¤.

    const routes = [
      { path: '/home', component: Home },
      { path: '/services', component: Services }
    ]

    Step 5: routes ěµě…과 í•¨ę» router 인스턴스를 ë§Śë“­ë‹ë‹¤.

    const router = new VueRouter({
      routes // short for `routes: routes`
    })

    Step 6: 루트 Vue 인스턴스를 만들고 mountí•©ë‹ë‹¤.

    const app = new Vue({
      router
    }).$mount('#app')

    ěť´ě ś Vue 어플리케이ě…ě—서 다른 íŽěť´ě§€(Home, Services)로 네비게이트 í•  ě ěžěеë‹ë‹¤.

  43. ëŹ™ě  ëťĽěš°íŠ¸ 매칭이란?

    주어진 패턴을 가진 라우트를 동일한 ě»´íŹ¬ë„ŚíŠ¸ě— ë§¤í•‘í•´ě•Ľí•는 경우가 ěžěŁĽ ěžěеë‹ë‹¤. ëŹ™ě  ě„¸ę·¸ë¨ĽíŠ¸ëĄĽ 이용해 /user/john/post/123ë‚ /user/jack/post/235와 같이 ë§¤í•‘ëś URLěť„ 가지는 컴포넌트를 만들어봅시다.

    const User = {
      template: '<div>User {{ $route.params.name }}, PostId: {{ route.params.postid }}</div>'
    }
    
    const router = new VueRouter({
      routes: [
        // dynamic segments start with a colon
        { path: '/user/:name/post/:postid', component: User }
      ]
    })
  44. 라우터 params를 ë°ěť‘ě ěśĽëˇś 만드는 방법은?

    매개 변ě와 í•¨ę» ëťĽěš°íŠ¸ëĄĽ 사용할 때 ěŁĽěť í•´ě•Ľí•  ě ěť€ 사용ěžę°€ /user/fooě—서 /user/bar로 이동할 때 동일한 컴포넌트 인스턴스가 재사용ëśë‹¤ëŠ” ę˛ěž…ë‹ë‹¤. ë‘ ëťĽěš°íŠ¸ ëŞ¨ë‘ ëŹ™ěťĽí•ś 컴포넌트를 렌더ë§í•므로 ěť´ě „ 인스턴스를 ě‚­ě ś 한 다음 ě 인스턴스를 만드는 ę˛ëł´ë‹¤ 효율ě ěž…ë‹ë‹¤. ę·¸ëź¬ë‚ ěť´ëŠ” ë한 ě»´íŹ¬ë„ŚíŠ¸ěť ëťĽěť´í”„ ě‚¬ěť´í´ í›…ěť´ í¸ě¶śëě§€ 않음을 ěťëŻ¸í•©ë‹ë‹¤.

    동일한 ě»´íŹ¬ë„ŚíŠ¸ěť params 변경 ě‚¬í•­ě— ë°ěť‘í•려면 $route 객체를 ëł´ë©´ë©ë‹ë‹¤.

    1. watchě—서 $route 관찰í•기:
    const User = {
      template: '<div>User {{ $route.params.name }} </div>',
      watch: {
        '$route' (to, from) {
          // react to route changes...
        }
      }
    }
    1. beforeRouteUpdate ë„¤ëą„ę˛Śěť´ě… ę°€ë“śëĄĽ 사용í•기:
    const User = {
      template: '<div>User {{ $route.params.name }} </div>',
      beforeRouteUpdate (to, from, next) {
        // react to route changes and then call next()
      }
    }

    beforeRouteEnter 가드ě—서는 thisě— ě ‘ę·Ľí•  권한이 없다는 ę˛ěť„ 기억í•세요. 대신, next 콜백 함ě를 이용해 ěť¸ěŠ¤í„´ěŠ¤ě— ě ‘ę·Ľí•  ě ěžěеë‹ë‹¤.

  45. ëťĽěš°íŠ¸ěť ěš°ě„  ěśěś„는?

    동일한 URLěť´ 여러 라우트와 일ěąí•는 경우가 ěžěеë‹ë‹¤. ěť´ 경우 일ěąí•는 ěš°ě„  ěśěś„는 라우트 ě •ěťěť ěśě„śě— 따라 결정ë©ë‹ë‹¤. 즉, 경로가 더 먼저 ě •ěť ë ě록 ěš°ě„  ěśěś„ę°€ 높아집ë‹ë‹¤.

    const router = new VueRouter({
           routes: [
             // dynamic segments start with a colon
             { path: '/user/:name', component: User } // This route gets higher priority
             { path: '/user/:name', component: Admin }
             { path: '/user/:name', component: Customer }
           ]
         })
  46. ě¤‘ě˛©ëś ëťĽěš°íŠ¸ëž€?

    일ë°ě ěśĽëˇś 어플리케이ě…은 여러 ë‹¨ęł„ěť ě¤‘ě˛©ëś ě»´íŹ¬ë„ŚíŠ¸ëˇś 이루어져 ěžěеë‹ë‹¤. URLěť ě„¸ę·¸ë¨ĽíŠ¸ 역시 ě¤‘ě˛©ëś ě»´íŹ¬ë„ŚíŠ¸ěť íŠąě • 구조와 일ěąí•©ë‹ë‹¤. ě¤‘ě˛©ëś ě•„ě›ë ›ě—서 컴포넌트를 렌더ë§í•려면 VueRouter ěťě„±ěžě—서 config로 childreněť„ 설정해야 í•©ë‹ë‹¤.

    프로필과 포스트들이 ě대ě ěť¸ 경로로 ě„¤ě •ëś ě–´í”Śë¦¬ěĽ€ěť´ě…ěť„ 만들어봅시다. 매칭ë는 í•ěś„ 라우트가 없을 ę˛˝ěš°ě— ë ŚëŤ”ë§ë는 라우트 컴포넌트를 설정할 ě ěžěеë‹ë‹¤.

    const router = new VueRouter({
      routes: [
        { path: '/user/:id', component: User,
          children: [
            {
              // UserProfile will be rendered inside User's <router-view> when /user/:id/profile is matched
              path: 'profile',
              component: UserProfile
            },
            {
              // UserPosts will be rendered inside User's <router-view> when /user/:id/posts is matched
              path: 'posts',
              component: UserPosts
            },
              // UserHome will be rendered inside User's <router-view> when /user/:id is matched
            {  path: '',
               component: UserHome },
          ]
        }
      ]
    })
  47. 싱글 파일 컴포넌트란?

    ě•„ë§ í•ë‚ěť íŽěť´ě§€ě—서 HTML, CSS, JavaScriptěť„ 다른 파일로 분리해 관리해본 경í—ěť´ ěžěť„ ę˛ěž…ë‹ë‹¤. í•지만 싱글 파일 컴포넌트ě—서는 템플릿과 스í€ěťĽ, 로ě§ë“¤ěť„ í•ë‚ěť íŚŚěťĽě— ě •ë¦¬í•©ë‹ë‹¤.

    <template>
        <div>
            <h1>Welcome {{ name }}!</h1>
        </div>
    </template>
    
    <script>
        module.exports = {
           data: function() {
               return {
                   name: 'John'
               }
           }
        }
    </script>
    
    <style scoped>
        h1 {
            color: #34c779;
            padding: 3px;
        }
    </style>
  48. 관심사 분리(separation of concerns)이란?

    주목해야 í•  중요한 ě ěť€ 관심사 분리가 파일 í€ěž… 분리와 같지 않다는 ę˛ěž…ë‹ë‹¤. í„대ě ěť¸ UI ę°śë°śě—서 코드베이스를 서로 ě–˝í€ěžëŠ” 세 ę°śěť ę±°ëŚ€í•ś ë ěť´ě–´ëˇś ë‚ë„는 대신, ëŠěЍí•게 결합 ëś ě»´íŹ¬ë„ŚíŠ¸ëˇś ë‚ë„ęł  구성í•는 ę˛ěť´ 더 중요합ë‹ë‹¤. 컴포넌트 ë‚´ë¶€ě—서 템플릿, ëˇśě§ ë°Ź 스í€ěťĽěť´ 본ě§ě ěśĽëˇś 결합ëě–´ ë°°ěąëë©´ ě»´íŹ¬ë„ŚíŠ¸ěť ěť‘ě§‘ë ĄęłĽ ěś ě§€ ëł´ě성이 í–Ąěë©ë‹ë‹¤.

    싱글 파일 ě»´íŹ¬ë„ŚíŠ¸ě— ëŚ€í•ś 아이디어가 ë§ěťŚě— 들지 않더라도 JavaScript와 CSS를 ëł„ëŹ„ěť íŚŚěťĽëˇś 분리í•ě—¬ í•« 리로드 ë°Ź 사전 컴파일 기능을 활용할 ě ěžěеë‹ë‹¤.

    <template>
      <div>This section will be pre-compiled and hot reloaded</div>
    </template>
    <script src="./my-component.js"></script>
    <style src="./my-component.css"></style>
  49. 싱글 파일 컴포넌트는 왜 필요할까?

    복잡한 í”„ëˇśě ťíŠ¸ěť ę˛˝ěš° ë는 프론트엔드가 JavaScript 기ë°ěť¸ 경우 단ě ěť´ 분명해집ë‹ë‹¤. 싱글 파일 컴포넌트가 아닌 경우ě—는 ě•„ëžě™€ 같은 문제ě ěť´ ěžěť„ ě ěžěеë‹ë‹¤.

    1. ě „ě—­ ě •ěť ëŞ¨ë“  구성 ěš”ě†Śě— ëŚ€í•´ 고유한 이름을 지정í•도록 ę°•ěš”ë©ë‹ë‹¤.
    2. 문ěžě—´ 템플릿 구문 강조가 약해 여러 줄로 ëś HTMLě— ëł´ę¸° ě•좋은 슬ëžě‹śę°€ ë§Žěť´ 필요합ë‹ë‹¤.
    3. CSS ě§€ě› ě—†ěťŚ HTML ë°Ź JavaScriptę°€ 컴포넌트로 모ë“í™” ëě–´ ěžěśĽë‚ CSSę°€ ëą ě ¸ ěžëŠ” ę˛ěť„ ë§í•©ë‹ë‹¤.
    4. 빌드 단계 없음 Pug (ěť´ě „ěť Jade) ë°Ź Babel과 같은 ě „ě˛ë¦¬ę¸°ę°€ 아닌 HTML ë°Ź ES5 JavaScript로 제한ë©ë‹ë‹¤.

    싱글 파일 컴포넌트는 JavaScript 기ë°ě—서 ë°śěťí•는 문제ě ěť„ 해결í•기 위해, ëł„ëŹ„ěť .vue 확장ěžěť 파일로 작성합ë‹ë‹¤.

  50. filter란?

    filter는 텍스트 í•식화를 위해 사용ë©ë‹ë‹¤. ěť´ 필터들은 ěžë°”스í¬ë¦˝íЏ 표í„ě‹ťě— íŚŚěť´í”„(|) 기í¸ě™€ í•¨ę» ě¶”ę°€ë어야 í•©ë‹ë‹¤. í¬ę˛Ś ë‘ ę°€ě§€ 경우ě—서 ě‚¬ěš©ë  ě ěžěеë‹ë‹¤.

    1. ě¤‘ę´„í¸ ëł´ę°„ë˛•
    2. v-bind 표í„식

    첫 글ěžëĄĽ 대문ěžëˇś 만드는 로컬 필터를 ě •ěťí•´ë´…시다.

    filters: {
      capitalize: function (value) {
        if (!value) return ''
        value = value.toString()
        return value.charAt(0).toUpperCase() + value.slice(1)
      }
    }

    ěť´ 필터를 ě¤‘ę´„í¸ ëł´ę°„ë˛• ë는 v-bind 표í„식 í•¨ę» ě‚¬ěš©í•  ě ěžěеë‹ë‹¤.

    <!-- in mustaches -->
    {{ username | capitalize }}
    
    <!-- in v-bind -->
    <div v-bind:id="username | capitalize"></div>
  51. filter를 ě „ě—­ě  ë는 지역ě ěśĽëˇś 만드는 법은?

    1. 지역 í•„í„°(Local filters): 지역 필터는 ě»´íŹ¬ë„ŚíŠ¸ěť ěµě…ě—서 ě •ěťí•  ě ěžěеë‹ë‹¤. ěť´ 경우, 필터는 해당 컴포넌트ě—서만 사용 가능합ë‹ë‹¤.
    filters: {
      capitalize: function (value) {
        if (!value) return ''
        value = value.toString()
        return value.charAt(0).toUpperCase() + value.slice(1)
      }
    }
    1. ě „ě—­ í•„í„°(Global filters): Vue 인스턴스를 만들기 ě „ě— ě „ě—­ě ěśĽëˇś 필터를 ě •ěťí•  ě ěžěеë‹ë‹¤. ěť´ 경우 Vue 인스턴스 ë‚´ěť ëŞ¨ë“  컴포넌트ě—서 필터를 사용할 ě ěžěеë‹ë‹¤.
    Vue.filter('capitalize', function (value) {
      if (!value) return ''
      value = value.toString()
      return value.charAt(0).toUpperCase() + value.slice(1)
    })
    
    new Vue({
      // ...
    })
  52. filter를 연속해 쓰는 방법은?

    일ë°ě ěśĽëˇś ě•„ëžě™€ 같이, 표í„식ě—서 í•„í„° ë’¤ě— ë 다른 필터를 사용할 ě ěžěеë‹ë‹¤.

    {{ message | filterA | filterB | filterC ... }}

    ę°ę°ěť 필터는 파이프(|)로 구분ëë©°, message는 filterAěť ę˛°ęłĽę°€ filterBěť ěí–Ąěť„ 받고, ę·¸ 결과가 다시 filterCěť ěí–Ąěť„ 받습ë‹ë‹¤.

    ě를 들어, ë‚ ě§ś í•ě‹ťěť ëŤ°ěť´í„°ëĄĽ 변경한 ë’¤ 대문ěžëˇś 변경í•ęł  싶다면 ě•„ëžě™€ 같이 사용할 ě ěžěеë‹ë‹¤.

    {{ birthday | dateFormat | uppercase }}
  53. filterě— íŚŚëťĽëŻ¸í„°ëĄĽ 전달할 ě ěžěť„까?

    필터는 기본ě ěśĽëˇś ěžë°”스í¬ë¦˝íЏ 함ě이기 때문ě—, ě•„ëžě™€ 같이 ë‘ ę°ś ěť´ěěť ěť¸ě를 받을 ě ěžěеë‹ë‹¤.

    {{ message | filterA('arg1', arg2) }}

    여기서 filterA는 세 ę°śěť ěť¸ě를 받는 함ě로 ě •ěťëě—습ë‹ë‹¤. messageěť ę°’ěť€ 첫ë˛ě§¸ 인ě로 ě „ë‹¬ë  ę˛ěť´ë©°, ěśě 문ěžě—´ěť¸ 'arg1'은 ë‘ë˛ě§¸ 인ě로 ě „ë‹¬ë  ę˛ěť´ë©°, ěžë°”스í¬ë¦˝íЏ 표í„식인 arg2는 표í„식이 ě‹¤í–‰ëś ěť´í›„ě— ě„¸ë˛ě§¸ 인ě로 ě „ë‹¬ë  ę˛ěž…ë‹ë‹¤.

    {{ 2 | exponentialStrength(10) }} // prints 2 power 10 = 1024
  54. 플러그인이란?

    플러그인은 일ë°ě ěśĽëˇś ě „ě—­ ě준 기능을 Vue 어플리케이ě…ě— ě¶”ę°€í•©ë‹ë‹¤.

    1. ě „ě—­ 메소드 ë는 속성 추가(<vue-custom-element>)
    2. í•ë‚ ěť´ěěť ę¸€ëˇśë˛Ś ě—ě…‹ 추가(지시ěž, í•„í„°, 트랜지ě…)
    3. ě „ě—­ 믹스인으로 컴포넌트 ěµě…(vuex)
    4. Vue.prototype를 이용해 Vueě— ěť¸ěŠ¤í„´ěŠ¤ 메소드를 추가
    5. ěś„ěť ę¸°ëŠĄęłĽ í•¨ę» ěžě˛´ API를 ě śęłµí•는 라이브러리(vue-router)
  55. 플러그인을 만드는 방법은?

    플러그인ě—서는 install 메소드를 ě •ěťí•´ě•Ľ í•©ë‹ë‹¤. ěť´ 메소드는 첫 ë˛ě§¸ 인ěžëˇś Vue ěťě„±ěžě™€ 외부ě—서 설정 가능한 ěµě…ěť„ 파라미터로 전달받습ë‹ë‹¤.

    MyPlugin.install = function (Vue, options) {
      // 1. add global method or property
      Vue.myGlobalMethod = function () {
        // some logic ...
      }
    
      // 2. add a global asset
      Vue.directive('my-directive', {
        bind (el, binding, vnode, oldVnode) {
          // some logic ...
        }
        ...
      })
    
      // 3. inject some component options
      Vue.mixin({
        created: function () {
          // some logic ...
        }
        ...
      })
    
      // 4. add an instance method
      Vue.prototype.$myMethod = function (methodOptions) {
        // some logic ...
      }
    }
  56. 플러그인을 사용í•는 방법은?

    Vue.use() ě „ě—­ 메소드를 í¸ě¶śí•ě—¬ 플러그인을 사용할 ě ěžěеë‹ë‹¤. ěť´ 함ě는 ěťě„±ěž new Vue()로 Vue 인스턴스를 ěťě„±í•기 ě „ě— í¸ě¶śë어야 í•©ë‹ë‹¤.

    // calls `MyPlugin.install(Vue, { someOption: true })`
    Vue.use(MyPlugin)
    
    new Vue({
      //... options
    })
  57. 믹스인이란?

    Mixins는 Vue ě»´íŹ¬ë„ŚíŠ¸ě— ěž¬ě‚¬ěš© 가능한 기능을 배포í•는 유연한 방법입ë‹ë‹¤. ëŻąěŠ¤ěť¸ě— ěˇ´ěž¬í•는 기능들은 í¸ě¶śëś ě»´íŹ¬ë„ŚíŠ¸ěť ę¸°ëŠĄë“¤ęłĽ í•©ěłě§‘ë‹ë‹¤.

    mixin 객체는 모든 구성 요소 ěµě…ěť„ 포함할 ě ěžěеë‹ë‹¤. 다른 컴포넌트ě—서 ěž¬ě‚¬ěš©ë  ě ěžëŠ” created ëťĽěť´í”„ě‚¬ěť´í´ í›…ěť„ 가진 믹스인을 작성해봅시다.

    const myMixin = {
      created(){
        console.log("Welcome to Mixins!")
      }
    }
    var app = new Vue({
      el: '#root',
      mixins: [myMixin]
    })

    Note: 여러 믹스인은 ë°°ě—´ěť í•íśëˇś 사용할 ě ěžěеë‹ë‹¤.

  58. 전역 믹스인이란?

    Vue 어플리케이ě…ěť ëŞ¨ë“  ě»´íŹ¬ë„ŚíŠ¸ě— ëŹ™ěťĽí•ś ěµě…ěť´ë‚ ę¸°ëŠĄěť„ 확장해 사용할 필요가 ěžěť„ ě ěžěеë‹ë‹¤. ěť´ 경우, ě „ě—­ 믹스인을 활용해 Vueěť ëŞ¨ë“  ě»´íŹ¬ë„ŚíŠ¸ě— ěí–Ąěť„ 줄 ě ěžěеë‹ë‹¤.

    Vue.mixin({
       created(){
         console.log("Write global mixins")
       }
    })
    
    new Vue({
      el: '#app'
    })

    ěś„ěť ě „ě—­ 믹스인은 해당 Vue 인스턴스ě—서 ę° ě»´íŹ¬ë„ŚíŠ¸ę°€ ěťě„±ë  때ë§ë‹¤ created í›…ě—서 로그를 ë°śěťě‹śí‚µë‹ë‹¤. 즉 모든 단일 Vue ěť¸ěŠ¤í„´ěŠ¤ě— ěí–Ąěť„ 주기 ë•Śë¬¸ě— ě ę˛Ś ěť´ěš©í•ęł  신중í•게 사용해야 í•©ë‹ë‹¤.

  59. CLI í™ę˛˝ě—서 믹스인을 사용í•는 법은?

    Vue CLI를 사용한다면, 믹스인은 일ë°ě ěśĽëˇś /src/mixins 디렉토리ě—서 .js파일로 작성합ë‹ë‹¤. export 키워드로 ě™¸ë¶€ě— ë‚´ëł´ë‚¸ë‹¤ëŠ” ę˛ěť„ 선언해야 í•ë©° 사용할 Vue 컴포넌트ě—서 import 키워드로 ë¶ëź¬ě¬ ě ěžěеë‹ë‹¤.

  60. ëŻąěŠ¤ěť¸ěť ěµě…ěť´ ě»´íŹ¬ë„ŚíŠ¸ěť ěµě…과 충돌한다면?

    믹스인과 컴포넌트ě—서 충돌í•는 ěµě…ěť´ ěžë‹¤ë©´, ěµě…은 몇 가지 방법을 통해 충돌í•는 ěµě…ěť„ 병합합ë‹ë‹¤.

    1. data는 재귀ě ěśĽëˇś 병합í•ë, 충돌ë는 속성은 ě»´íŹ¬ë„ŚíŠ¸ěť ëŤ°ěť´í„°ę°€ ěš°ě„ ě ěśĽëˇś 병합ë©ë‹ë‹¤.
    var mixin = {
      data: function () {
        return {
          message: 'Hello, this is a Mixin'
        }
      }
     }
    new Vue({
      mixins: [mixin],
      data: function () {
        return {
          message: 'Hello, this is a Component'
        }
      },
      created: function () {
        console.log(this.$data); // => { message: "Hello, this is a Component'" }
      }
    })
    1. ëťĽěť´í”„ě‚¬ěť´í´ í›… 함ě는 믹스인 함ěę°€ 먼저 실행ëęł , ę·¸ ë‹¤ěťŚě— ě»´íŹ¬ë„ŚíŠ¸ěť í•¨ěę°€ 실행ë©ë‹ë‹¤.
    const myMixin = {
      created(){
        console.log("Called from Mixin")
      }
    }
    
    new Vue({
      el: '#root',
      mixins:[myMixin],
      created(){
        console.log("Called from Component")
      }
    })
    
    //Called from Mixin
    //Called from Component
    1. methods, components, directives 역시 재귀ě ěśĽëˇś 병합í•ë, 이러한 ę°ťě˛´ě— ě¶©ëŹŚí•는 키가 ěžěť„ 경우 ě»´íŹ¬ë„ŚíŠ¸ěť ěµě…ěť´ ěš°ě„ ěśěś„를 갖습ë‹ë‹¤.
    var mixin = {
      methods: {
        firstName: function () {
          console.log('John')
        },
        contact: function () {
          console.log('+65 99898987')
        }
      }
    }
    
    var vm = new Vue({
      mixins: [mixin],
      methods: {
        lastName: function () {
          console.log('Murray')
        },
        contact: function () {
          console.log('+91 893839389')
        }
      }
    })
    
    vm.firstName() // "John"
    vm.lastName() // "Murray"
    vm.contact() // "+91 893839389"
  61. ëŻąěŠ¤ěť¸ěť ëł‘í•© 방법을 ě‚¬ěš©ěž ě •ěťí•는 방법은?

    Vueě—서는 ě‚¬ěš©ěž ě§€ě • ěµě…ěť„ 병합할 때 기본ě ěśĽëˇś 기존 ę°’ěť„ 덮어는 방법을 이용합ë‹ë‹¤. ë§Śě•˝ ě‚¬ěš©ěž ě •ěťěť 로ě§ěť„ 사용해 커스텀 ěµě…ěť„ 병합í•려면,Vue.config.optionMergeStrategiesě— í•¨ě를 추가할 필요가 ěžěеë‹ë‹¤.

    Vue.config.optionMergeStrategies.myOption = function (toVal, fromVal) {
      // return mergedVal
    }

    더 고급 ě제는 Vuexěť 1.x 병합 ě „ëžµě—서 확인í•실 ě ěžěеë‹ë‹¤.

    const merge = Vue.config.optionMergeStrategies.computed
    Vue.config.optionMergeStrategies.vuex = function (toVal, fromVal) {
      if (!toVal) return fromVal
      if (!fromVal) return toVal
      return {
        getters: merge(toVal.getters, fromVal.getters),
        state: merge(toVal.state, fromVal.state),
        actions: merge(toVal.actions, fromVal.actions)
      }
    }
  62. ě‚¬ěš©ěž ě •ěť ě§€ě‹śěž(Custom directive)란?

    지시ěžëŠ” DOM ě—ë¦¬ë¨ĽíŠ¸ě— ë¶€ě°©í•  ě ěžëŠ” 명령어입ë‹ë‹¤. ěś„ě—서 본 ę˛ě˛ëźĽ v-로 시작í•는 문법을 사용해 Vueę°€ ěť´ 명령어를 인식할 ě ěžëŹ„ëˇť 해야 í•©ë‹ë‹¤. 일ë°ě ěśĽëˇś í•ěś„ ěě¤€ěť DOMěť„ ě śě–´í•기 위해 ě§ě ‘ 접근해야 í•  필요가 ěžěť„ 때 ěś ěš©í•게 사용ë©ë‹ë‹¤.

    íŽěť´ě§€ę°€ ëˇśë“śë  ë•Ś inputě— ěžëŹ™ěśĽëˇś 포커싱ë는 ě‚¬ěš©ěž ě •ěť ě§€ě‹śěžëĄĽ 전역으로 만들어봅시다.

    // Register a global custom directive called `v-focus`
    Vue.directive('focus', {
      // When the bound element is inserted into the DOM...
      inserted: function (el) {
        // Focus the element
        el.focus()
      }
    })

    ěť´ě ś ěť´ 지시ěžëŠ” v-focus라는 문법과 í•¨ę» ě–´ë–¤ 컴포넌트ě—서든 ě‚¬ěš©ë  ě ěžěеë‹ë‹¤.

    <input v-focus>
  63. 지시ěžëĄĽ 지역 등록í•는 방법은?

    지시ěžëĄĽ 지역 등록í•기 위해서는 directives ěµě…ěť„ 이용합ë‹ë‹¤.

    directives: {
      focus: {
        // directive definition
        inserted: function (el) {
          el.focus()
        }
      }
    }

    ěť´ 지시ěžëŠ” ě„ ě–¸ëś í•´ë‹ą 컴포넌트ě—서만 ě‚¬ěš©ë  ě ěžěеë‹ë‹¤.

    <input v-focus>
  64. 지시ěžě— ěťí•´ ě śęłµë는 라이프 ě‚¬ěť´í´ í›…ěť€?

    ě§€ě‹śěž ę°ťě˛´ę°€ ë“±ëˇťë  ë•Ś 몇 ę°śěť ëťĽěť´í”„ ě‚¬ěť´í´ í›…ěť„ 제공합ë‹ë‹¤.

    1. bind: 지시ěžę°€ ě˛ěťŚ ě—ë¦¬ë¨ĽíŠ¸ě— ë¶€ě°©ë  ë•Ś 한 ë˛ í¸ě¶śë©ë‹ë‹¤.
    2. inserted: 지시ěžę°€ ë¶€ě°©ëś ě—리먼트가 DOMě— ě‚˝ěž…ëě—ěť„ 때 í¸ě¶śë©ë‹ë‹¤.
    3. update: 해당 ě—리먼트가 업데이트 ë  ë•Ś í¸ě¶śë©ë‹ë‹¤. í•지만 ě•„ě§ í•ěś„ ě—리먼트는 업데이트 ëě§€ 않은 ěíśěž…ë‹ë‹¤.
    4. componentUpdated: í•ěś„ 컴포넌트까지 업데이트 ëś ěíśěťĽ 때 í¸ě¶śë©ë‹ë‹¤.
    5. unbind: 지시ěžę°€ ě—리먼트ě—서부터 ě‚­ě śë  ë•Ś í¸ě¶śë©ë‹ë‹¤.

    Note: ěś„ěť í›…ě—서는 특정한 전달인ěž(Argument)를 받는다.

  65. 디렉티브 í›…ěť ě „ë‹¬ěť¸ěžëŠ”?

    모든 í›…ě—서는 전달인ěžëˇś el, binding와 vnode를 ę°–ęł  ěžěеë‹ë‹¤. 그와 함ę», update와 componentUpdatedí›…ě—서는 ě 값과 ěť´ě „ ę°’ěť„ ëą„ęµí•기 위해 oldVnode를 추가ě ěśĽëˇś ę°–ęł  ěžěеë‹ë‹¤.

    1. el: 해당 지시ěžę°€ ë¶€ě°©ëś ě—리먼트로, 이를 이용해 DOMěť„ 조작할 ě ěžěеë‹ë‹¤.
    2. binding: ě•„ëžěť 속성을 가진 객체입ë‹ë‹¤.
      1. name: 지시ěžěť 이름으로, v- ě ‘ë‘사가 ě śę±°ëś ěť´ë¦„ěž…ë‹ë‹¤.
      2. value: 지시ěžě—서 전달 받은 ę°’ěž…ë‹ë‹¤. ë§Śě•˝ v-my-directive="1 + 1"라면 2ę°€ ë©ë‹ë‹¤.
      3. oldValue: ěť´ě „ 값으로, update와 componentUpdatedí›…ě—서만 사용할 ě ěžěеë‹ë‹¤. 이를 통해 ę°’ěť´ 변경ëě—는지 아닌지를 확인할 ě ěžěеë‹ë‹¤.
      4. expression: 문ěžě—´ëˇś ë°”ěť¸ë”©ëś í‘śí„식입ë‹ë‹¤. ë§Śě•˝ v-my-directive="1 + 1"라면 "1 + 1"ěť´ ë©ë‹ë‹¤..
      5. arg: 지시ěžěť 전달인ěžěž…ë‹ë‹¤. ë§Śě•˝ v-my-directive:foo라면 "foo"ę°€ ë©ë‹ë‹¤..
      6. modifiers: ě식어가 íŹ¬í•¨ëś ę°ťě˛´ěž…ë‹ë‹¤. ë§Śě•˝ v-my-directive.foo.bar라면 { foo: true, bar: true }ę°€ ë©ë‹ë‹¤.
    3. vnode: Vueěť ě»´íŚŚěťĽëź¬ě— ěťí•´ ěťě„±ëś ę°€ě 노드입ë‹ë‹¤.
    4. oldVnode: ěť´ ě „ěť ę°€ě 노드로, update와 componentUpdatedí›…ě—서만 사용할 ě ěžěеë‹ë‹¤.

    custom-directives

  66. 지시ěžě— 여러 값들을 전달í•는 방법은?

    지시ěžëŠ” 유효한 ěžë°”스í¬ë¦˝íЏ 표í„식은 ëŞ¨ë‘ ě용할 ě ěžěеë‹ë‹¤. 따라서 지사ěžě— 여러 값들을 전달í•려면, ěžë°”스í¬ë¦˝íЏ 객체 리터럴을 이용해 전달할 ě ěžěеë‹ë‹¤.

    <div v-avatar="{ width: 500, height: 400, url: 'path/logo', text: 'Iron Man' }"></div>

    ěť´ě ś v-avatar 지시ěžëĄĽ 전역으로 설정해봅시다.

    Vue.directive('avatar', function (el, binding) {
      console.log(binding.value.width) // 500
      console.log(binding.value.height)  // 400
      console.log(binding.value.url) // path/logo
      console.log(binding.value.text)  // "Iron Man"
    })
  67. ě§€ě‹śěž í›…ě—서 함ě 약어는?

    드문 경우지만, 다른 훅과는 ě관없이 bindë‚ update í›…ě—서 같은 동작을 í•기 ě›í•  ě ěžěеë‹ë‹¤. ěť´ 경우ě—는 함ě 약어를 사용할 ě ěžěеë‹ë‹¤.

    Vue.directive('theme-switcher', function (el, binding) {
      el.style.backgroundColor = binding.value
    })
  68. render 함ě를 ě‚¬ěš 341A ©í•는 이유는?

    일ë°ě ěť¸ 경우 Vueěť í…śí”Śë¦żěť„ 이용해 HTMLěť„ 작성í•는 ę˛ěť„ 권장합ë‹ë‹¤. í•지만 inputěť´ë‚ slotěť ę°’ěť„ 이용해 동ě ěť¸ 컴포넌트를 ěťě„±í•는 ę˛ě˛ëźĽ, 일부 특별한 경우ě—는 JavaScriptę°€ 필요한 경우가 ěžěеë‹ë‹¤. 이때 render 함ě를 사용í•ë©°, render함ě는 JavaScript로 작성í•기 ë•Śë¬¸ě— í”„ëˇśę·¸ëžë°Ť í™ę˛˝ěť„ ě¨ě „íž ěť´ěš©í•  ě ěžë‹¤ëŠ” 장ě ěť´ ěžěеë‹ë‹¤.

  69. render 함ě란?

    render 함ě는 createElement라는 함ě를 첫 ë˛ě§¸ 인ěžëˇś 받아 ę°€ě 노드를 ěťě„±í•는 함ěěž…ë‹ë‹¤. ë‚´ë¶€ě ěśĽëˇś Vueěť í…śí”Śë¦żěť€ 빌드 í€ěž„ě—서 render 함ě를 이용해 컴파일í•ęł  ěžěеë‹ë‹¤. 그러므로 템플릿은 render 함ě를 문법ě ěśĽëˇś 보기 쉽게 만들어 놓은 ę˛ě— 가깝습ë‹ë‹¤.

    <div> íśę·¸ëĄĽ ę°ę° 템플릿과 render 함ě를 이용해 작성해봅시다. 템플릿은 ě•„ëžě™€ 같이 작성할 ě ěžěеë‹ë‹¤.

    <template>
     <div :class="{'is-rounded': isRounded}">
       <p>Welcome to Vue render functions</p>
     </div>
    </template>

    ěś„ěť í…śí”Śë¦żěť„ render 함ě로 작성í•ë©´ ě•„ëžě™€ 같습ë‹ë‹¤.

    render: function (createElement) {
       return createElement('div', {
         'class': {
             'is-rounded': this.isRounded
         }
       }, [
         createElement('p', 'Welcome to Vue render functions')
       ]);
      },
  70. createElement 함ě란?

    createElement 함ě는 몇 ę°€ě§€ěť ě•˝ě†Ťëś ě „ë‹¬ěť¸ěžëĄĽ 받는데, 이를 이용해 템플릿ě—서 사용ë는 기능을 JavaScript 코드로 작성할 ě ěžěеë‹ë‹¤.

    // @returns {VNode}
    createElement(
      // An HTML tag name, component options, or async function resolving to one of these.
      // Type is {String | Object | Function}
      // Required.
      'div',
    
      // A data object corresponding to the attributes you would use in a template.
      //Type is {Object}
      // Optional.
      {
          // Normal HTML attributes
          attrs: {
            id: 'someId'
          },
          // Component props
          props: {
            myProp: 'somePropValue'
          },
          // DOM properties
          domProps: {
            innerHTML: 'This is some text'
          },
          // Event handlers are nested under `on`
          on: {
              click: this.clickHandler
            },
          // Similar to `v-bind:style`, accepting either a string, object, or array of objects.
           style: {
              color: 'red',
              fontSize: '14px'
           },
           //Similar to `v-bind:class`, accepting either a string, object, or array of strings and objects.
            class: {
               classsName1: true,
               classsName2: false
            },
            ....
      },
    
      // Children VNodes, built using `createElement()`, or using strings to get 'text VNodes'.
      // Type is {String | Array}
      // Optional.
      [
        'Learn about createElement arguments.',
        createElement('h1', 'Headline as a child virtual node'),
        createElement(MyComponent, {
          props: {
            someProp: 'This is a prop value'
          }
        })
      ]
    )

    ěžě„¸í•ś 내용은 공식 문서ě—서 확인할 ě ěžěеë‹ë‹¤.

  71. ę°€ě 노드를 여러 ë˛ ě‚¬ěš©í•  ě ěžëŠ” 방법은?

    컴포넌트 íŠ¸ë¦¬ěť ëŞ¨ë“  ę°€ě 노드(VNodes)는 고유해야 í•©ë‹ë‹¤. 즉, ě§ě ‘ ę°€ě 노드를 여러 ë˛ ě‚¬ěš©í•  ě는 없습ë‹ë‹¤. ë§Śě•˝ 같은 ě—ë¦¬ë¨ĽíŠ¸ë‚ ě»´íŹ¬ë„ŚíŠ¸ëĄĽ 여러 ë˛ ë°ëłµí•´ě„ś 사용해야 한다면, 팩토리 패턴을 이용해 작성해야 í•©ë‹ë‹¤.

    ě•„ëžěť render 함ě는 h1 ě—리먼트를 세 ë˛ ë°ëłµí•ë ¤ í–기 ë•Śë¬¸ě— ěś íš¨í•ě§€ 않습ë‹ë‹¤.

    render: function (createElement) {
      var myHeadingVNode = createElement('h1', 'This is a Virtual Node')
      return createElement('div', [
        myHeadingVNode, myHeadingVNode, myHeadingVNode
      ])
    }

    팩토리 패턴을 ěť´ěš©í•ë©´ ë©ë‹ë‹¤.

    render: function (createElement) {
      return createElement('div',
        Array.apply(null, { length: 3 }).map(function () {
          return createElement('h1', 'This is a Virtual Node')
        })
      )
    }
  72. render 함ě와 템플릿을 ëą„ęµí•śë‹¤ë©´?

    Vueě—서 HTMLěť„ 작성í•는데 사용ë는 템플릿과 render 함ě를 ëą„ęµí•´ë´…시다.

    템플릿(Templates) 렌더 함ě(Render function)
    v-if와 v-for를 이용해 조건문/ë°ëłµë¬¸ 실행 JavaScriptěť if else문과 map 메소드로 조건문/ë°ëłµë¬¸ 실행
    v-model로 ě–‘ë°©í–Ą 바인딩 바인딩과 이벤트를 ě§ě ‘ 설정
    Capture 이벤트 ě식어는 .passive, .capture, .once, .capture.once, .once.capture &, !, ~, ~!
    이벤트 ě식어와 키 ě식어: .stop, .prevent, .self, keys(.enter, .13) and Modifiers Keys(.ctrl, .alt, .shift, .meta) JavaScript로 해결, event.stopPropagation(), event.preventDefault(), if (event.target !== event.currentTarget) return, if (event.keyCode !== 13) return, if (!event.ctrlKey) return
    슬롯 속성 활용 렌더 함ěěť this.$slots와 this.$scopedSlots 활용
  73. 함ěí• ě»´íŹ¬ë„ŚíŠ¸(Functional component)란?

    함ěí• ě»´íŹ¬ë„ŚíŠ¸ëŠ” context를 통해 전달받은 정보로만 ěťě„±ë는 간단한 컴포넌트입ë‹ë‹¤.

    1. ěíś ě—†ěťŚ(Stateless): 즉 dataę°€ 없습ë‹ë‹¤
    2. 인스턴스 없음(Instanceless): 즉 thisę°€ 없습ë‹ë‹¤

    ěť´ 경우, functional: true 속성을 이용해 컴포넌트를 함ěí•으로 작성할 ě ěžěеë‹ë‹¤.

    Vue.component('my-component', {
      functional: true,
      // Props are optional
      props: {
        // ...
      },
      // To compensate for the lack of an instance,
      // we are now provided a 2nd context argument.
      render: function (createElement, context) {
        // ...
      }
    })
  74. Vue와 Reactěť ęłµí†µě ěť€?

    1. ë‘ í”„ë ěž„ě›Śí¬ ëŞ¨ë‘ ę°€ě DOM 모델을 사용합ë‹ë‹¤.
    2. ë°ěť‘ě ěť´ęł  조합 가능한 컴포넌트를 제공합ë‹ë‹¤.
    3. 코어 라이브러리ě—ë§Ś 집중í•ęł  ěžęł , 라우팅 ë°Ź ěíś ę´€ë¦¬ě™€ 같은 라이브러리가 부가ě ěśĽëˇś ěžěеë‹ë‹¤.
  75. Vue와 Reactěť ě°¨ěť´ě ěť€?

    특징 Vue React
    í€ěž… JavaScript MVC 프ë ěž„ě›Śí¬ JavaScript 라이브러리
    플랫폼 웹을 ěš°ě„ ě ěśĽëˇś 웹과 네이티브 모ë‘
    복잡도 ě대ě ěśĽëˇś 간단 ě대ě ěśĽëˇś 복잡
    빌드 ě–´í”Śë¦¬ěĽ€ěť´ě… Vue-cli CRA (Create-React-App)
  76. Vueę°€ Reactě— ëą„í•´ ë‚은 ě ěť€?

    1. 가볍고 빠릅ë‹ë‹¤.
    2. 템플릿이 ę°śë°ś 과정을 쉽게 만들어줍ë‹ë‹¤.
    3. JSXě— ëą„í•´ 가벼운 JavaScript 문법을 사용합ë‹ë‹¤.
  77. Reactę°€ Vueě— ëą„í•´ ë‚은 ě ěť€?

    1. í° ę·śëŞ¨ěť ě–´í”Śë¦¬ěĽ€ěť´ě…ěť„ ěś ě—°í•게 만들 ě ěžěеë‹ë‹¤.
    2. 테스트가 쉽습ë‹ë‹¤.
    3. 모바일 앱 ě śěž‘ě—도 ě í•©í•©ë‹ë‹¤.
    4. ěťíśęł„ę°€ í¬ęł  풍부합ë‹ë‹¤.
  78. Vue와 AngularJSěť ě°¨ěť´ě ěť€?

    Vueěť ę°śë°ś ě´ę¸° 단계ě—서 AngularJS를 참고í–기 때문ě—, Vue와 AngularJSěť ë¬¸ë˛•ěť€ ěë‹ąíž ëą„ěŠ·í•©ë‹ë‹¤. í•지만 ě°¨ěť´ě  ě—­ě‹ś 존재합ë‹ë‹¤.

    특징 Vue AngularJS
    복잡도 배우기 쉬운 API와 ë””ěžěť¸ 프ë ěž„워í¬ę°€ 꽤 í¬ęł  í€ěž…스í¬ë¦˝íЏ ë“±ěť ě§€ě‹ť í•„ěš”
    데이터 바인딩 양방향 바인딩 단방향 바인딩
    ě´ę¸° ë¦´ë¦¬ě¦ 2014 2016
    모델 ę°€ě DOM ę¸°ë° MVC
    ěž‘ě„±ëś ě–¸ě–´ JavaScript TypeScript
  79. ëŹ™ě  ě»´íŹ¬ë„ŚíŠ¸ëž€?

    <component> íśę·¸ě—서 v-bind:is로 ë°”ěť¸ë”©ëś ě»´íŹ¬ë„ŚíŠ¸ëĄĽ 동ě ěśĽëˇś ě „í™í•  ě ěžěеë‹ë‹¤.

    new Vue({
      el: '#app',
      data: {
        currentPage: 'home'
      },
      components: {
        home: {
          template: "<p>Home</p>"
        },
        about: {
          template: "<p>About</p>"
        },
        contact: {
          template: "<p>Contact</p>"
        }
      }
    })

    ěť´ě ś 템플릿ě—서 <component> íśę·¸ě— 바인딩 ë  ě»´íŹ¬ë„ŚíŠ¸ëĄĽ 설정할 ě ěžěеë‹ë‹¤.

    <div id="app">
       <component v-bind:is="currentPage">
           <!-- component changes when currentPage changes! -->
           <!-- output: Home -->
       </component>
    </div>
  80. keep-alive íśę·¸ëž€?

    <keep-alive>는 ě»´íŹ¬ë„ŚíŠ¸ěť ěíśëĄĽ 보존해서 재 렌더ë§ěť„ 막아주는 ě¶”ě 컴포넌트입ë‹ë‹¤. ë§Śě•˝ 동ě ěť¸ 컴포넌트를 <keep-alive> íśę·¸ëˇś ę°ě‹Ľë‹¤ë©´, 컴포넌트 인스턴스를 없애지 않고 ë©”ëŞ¨ë¦¬ě— ěś ě§€í•´ 보존합ë‹ë‹¤.

    <!-- Inactive components will be cached! -->
    <keep-alive>
      <component v-bind:is="currentTabComponent"></component>
    </keep-alive>

    ë§Śě•˝ 조건문이 ěžë‹¤ë©´, 해당 ěˇ°ę±´ěť í•ěś„ 컴포넌트만 렌더ë§ë©ë‹ë‹¤.

    <!-- multiple conditional children -->
    <keep-alive>
      <comp-a v-if="a > 1"></comp-a>
      <comp-b v-else></comp-b>
    </keep-alive>

    Note: <keep-alive>는 DOMě— ë ŚëŤ”ë§ ëě§€ 않습ë‹ë‹¤.

  81. 비동기 컴포넌트(Async component)란?

    대규모 응용 프로그램ě—서는 응용 프로그램을 더 작은 덩어리로 ë‚ë„ęł  실제로 필요할 때만 서버ě—서 컴포넌트를 로드해야 í•  ě도 ěžěеë‹ë‹¤. Vue를 사용í•ë©´ 컴포넌트 ě •ěťëĄĽ 비동기식으로 해결í•는 팩토리 함ě로 컴포넌트를 ě •ěť í•  ě ěžěеë‹ë‹¤.

    Vue.component('async-webpack-example', function (resolve, reject) {
      // Webpack automatically split your built code into bundles which are loaded over Ajax requests.
      require(['./my-async-component'], resolve)
    })

    Vue는 Vue는 컴포넌트가 렌더ë§ë어야 í•  때만 팩토리 함ě를 실행시키고, ěť´í›„ěť ë‚ě¤‘ě— ěžěť„ 리렌더ë§ěť„ 위해 결과를 ěşě‹śí•©ë‹ë‹¤.

  82. 비동기 컴포넌트 팩토리 패턴이란?

    비동기 컴포넌트 팩토리는 다음 í•íśěť 객체를 ë°í™í•  ě ěžěеë‹ë‹¤.

    const AsyncComponent = () => ({
      // The component to load (should be a Promise)
      component: import('./MyComponent.vue'),
      // A component to use while the async component is loading
      loading: LoadingComponent,
      // A component to use if the load fails
      error: ErrorComponent,
      // Delay before showing the loading component. Default: 200ms.
      delay: 200,
      // The error component will be displayed if a timeout is
      // provided and exceeded. Default: Infinity.
      timeout: 3000
    })
  83. 인라인 템플릿(inline templates)이란?

    í•ěś„ ě»´íŹ¬ë„ŚíŠ¸ě— inline-template 속성이 존재할 때, 컴포넌트는 ë‚´ë¶€ 컨í…츠를 템플릿으로 사용합ë‹ë‹¤. 따라서 보다 유연한 템플릿 작성이 가능합ë‹ë‹¤.

    <my-component inline-template>
       <div>
           <h1>Inline templates</p>
           <p>Treated as component component owne content</p>
       </div>
    </my-component>

    Note: inline-template은 í…śí”Śë¦żěť ë˛”ěś„ëĄĽ 추론í•기 어렵게 ë§Śë“­ë‹ë‹¤. 가장 좋은 방법은 template ěµě…ěť„ 사용í•ę±°ë‚ .vue íŚŚěťĽěť template ě—리먼트를 사용í•ě—¬ 컴포넌트 ë‚´ë¶€ě— í…śí”Śë¦żěť„ ě •ěťí•는 ę˛ěž…ë‹ë‹¤.

  84. X-Templates이란?

    템플릿를 ě •ěťí•는 ë 다른 방법은 text/x-template ěś í•ěť ěŠ¤í¬ë¦˝íЏ ě—리먼트 ë‚´ë¶€ěť ID로 템플릿을 참조í•는 ę˛ěž…ë‹ë‹¤.

    <script type="text/x-template" id="script-template">
      <p>Welcome to X-Template feature</p>
    </script>
    Vue.component('x-template-example', {
      template: '#script-template'
    })
  85. 재귀 컴포넌트(recursive components)란?

    컴포넌트는 ěžě‹ ěť 템플릿ě—서 ěžę¸° ěžě‹ ěť„ 재귀ě ěśĽëˇś í¸ě¶śí•  ě ěžěеë‹ë‹¤.

    Vue.component('recursive-component', {
      template: `<!--Invoking myself!-->
                 <recursive-component></recursive-component>`
    });

    재귀 컴포넌트는 ë¸”ëˇśę·¸ěť ëŤ§ę¸€ěť´ë‚ ë©”ë‰´ě˛ëźĽ ěěś„ 컴포넌트와 í•ěś„ 컴포넌트가 동등한 기능을 í•  때 유용합ë‹ë‹¤.

    Note: 위와 같은 컴포넌트는 최대 ěŠ¤íť í¬ę¸° ě´ęłĽ ě¤ëĄę°€ ë°śěťí•므로 재귀 í¸ě¶śěť´ 조건부인지 확인해야 í•©ë‹ë‹¤.

  86. 컴포넌트 ě‚¬ěť´ěť ěśí™ 참조 해결 방법은?

    복잡한 어플리케이ě…ě—서 Vue 컴포넌트가 서로가 서로를 í¸ě¶śí•ęł  ěžëŠ” ě황이 ë°śěťí•  ě ěžěеë‹ë‹¤. 컴포넌트 A와 컴포넌트 Bę°€ 서로 ěśí™ 참조를 í•ęł  ěžëŠ” ě황을 살펴봅시다.

    //ComponentA
    <div>
      <component-b >
    </div>
    //ComponentB
    <div>
      <component-a >
    </div>

    ěť´ëź° 경우는 beforeCreate 라이프 ě‚¬ěť´í´ í›… 시ě ęąŚě§€ 기다렸다가 해당 컴포넌트를 등록í•ę±°ë‚, ě›ąíŚ©ěť ëą„ëŹ™ę¸° import를 활용합ë‹ë‹¤.

    Solution1:

    beforeCreate: function () {
     this.$options.components.componentB = require('./component-b.vue').default
    }

    Solution2:

    components: {
     componentB: () => import('./component-b.vue')
    }
  87. CSP í™ę˛˝ě—서 Vue 어플리케이ě…ěť„ 빌드í•는 법은?

    Google í¬ëˇ¬ 앱과 같은 일부 í™ę˛˝ě—서는 CSP(컨í…츠 ëł´ě• ě •ě±…)를 ě ěš©í•ě—¬ 표í„식을 평가í•는 데 new Function() ěť„ 사용할 ě 없습ë‹ë‹¤. 전체 빌드는 ěť´ 기능을 사용í•ě—¬ 템플릿을 컴파일í•므로 이러한 í™ę˛˝ě—서는 사용할 ě 없습ë‹ë‹¤.

    ë°ë©´ ëź°í€ěž„ ě „ěš© 빌드는 CSP와 완벽í•게 í¸í™ë©ë‹ë‹¤. Webpack + vue-loader ë는 Browserify + vueify로 ëź°í€ěž„ ě „ěš© 빌드를 사용í•는 경우 템플릿은 CSP í™ę˛˝ě—서 완벽í•게 작동í•는 render 함ě로 미리 컴파일ë©ë‹ë‹¤.

  88. 전체 빌드와 ëź°í€ěž„ ëąŚë“śěť ě°¨ěť´ě ěť€?

    1. 전체 빌드(Full): 컴파일러와 ëź°í€ěž„ 빌드를 ëŹ™ě‹śě— íŹ¬í•¨í•©ë‹ë‹¤. 템플릿을 작성한 경우 필요합ë‹ë‹¤.

    2. ëź°í€ěž„ 빌드(Runtime): Vue 인스턴스 ěťě„±ęłĽ render 함ě, ę°€ě 돔을 포함í•ęł  ěžě§€ë§Ś 컴파일러 빌드를 포함í•ęł  ěžě§€ 않습ë‹ë‹¤.

  89. Vueěť ëąŚë“ś 종ëĄëŠ”?

    í€ěž… UMD CommonJS ES Module (for bundlers) ES Module (for browsers)
    전체 빌드 vue.js vue.common.js vue.esm.js vue.esm.browser.js
    ëź°í€ěž„ 빌드 vue.runtime.js vue.runtime.common.js vue.runtime.esm.js NA
    전체 빌드 (배포 모드) vue.min.js NA NA vue.esm.browser.min.js
    ëź°í€ěž„ 빌드 (배포 모드) vue.runtime.min.js NA NA NA
  90. 웹팩ě—서 Vue 설정을 í•는 방법은?

    alias를 이용해 Vue를 설정할 ě ěžěеë‹ë‹¤.

    module.exports = {
      // ...
      resolve: {
        alias: {
          'vue$': 'vue/dist/vue.esm.js' // 'vue/dist/vue.common.js' for webpack 1
        }
      }
    }
  91. Vue ě»´íŚŚěťĽëź¬ěť ëŞ©ě ěť€?

    Vue는 컴파일러를 이용해 템플릿을 render 함ě로 변í™í•©ë‹ë‹¤.

    // this requires the compiler
    new Vue({
      template: '<div>{{ message }}</div>'
    })
    
    // this does not
    new Vue({
      render (h) {
        return h('div', this.message)
      }
    })
  92. DevTool이란?

    DevTool은 Vue 어플리케이ě…ěť„ ě‚¬ěš©ěž ěąśí™”ě ěť¸ 인터íŽěť´ěŠ¤ëˇś 디버그 í•  ě ěžę˛Ś 도와주는 브라우저 확장 프로그램입ë‹ë‹¤.

    Note: Vue íŽěť´ě§€ę°€ 배포 모드일 경우ě—는 DevTool로 디버그할 ě 없습ë‹ë‹¤.

  93. VueJSěť ë¸ŚëťĽěš°ě € ě§€ě›ěť€?

    ECMAScript5를 ě§€ě›í•는 브라우저ě—서 동작 가능합ë‹ë‹¤. IE8 ěť´í•ěť ë¸ŚëťĽěš°ě €ě—서는 ě§€ě›í•ě§€ 않습ë‹ë‹¤.

  94. CDN으로 Vue를 사용í•는 방법은?

    Vue는 jsdelivr, unpkg, cdnjsě—서 ě śęłµí•는 CDNěť„ 이용해서도 사용이 가능합ë‹ë‹¤. 일ë°ě ěśĽëˇś ě´ę¸° 기획, 학습용으로 ě í•©í•©ë‹ë‹¤.

    <script src="https://cdn.jsdelivr.net/npm/vue@2.6.7/dist/vue.js"></script>
    <script type="module">
      import Vue from 'https://cdn.jsdelivr.net/npm/vue@2.6.7/dist/vue.esm.browser.js'
    </script>

    Note: 버전 정보를 지우면 í•­ě 최신 버전을 가져ěµë‹ë‹¤.

  95. 강제로 업데이트를 ë°śěťě‹śí‚¤ëŠ” 방법은?

    매우 드문 경우지만, 데이터가 변경ëě§€ 않ě•음ě—도 재 렌더ë§ěť„ 위해 강제로 업데이트를 ë°śěťě‹śěĽśě•Ľ í•  ě도 ěžěеë‹ë‹¤. ěť´ 경우 vm.$forceUpdate() API 메소드를 이용할 ě ěžěеë‹ë‹¤.

    Note: 모든 í•ěś„ 컴포넌트ě—는 ěí–Ąěť´ 미ěąě§€ 않으며, 슬롯 ę·¸ ěžě˛´ę°€ ě‚˝ěž…ëś ěŠ¬ëˇŻ ěžě˛´ ë°Ź í•ěś„ 컴포넌트ě—ë§Ś ěí–Ąěť„ 미칩ë‹ë‹¤.

  96. 템플릿ě—서 once 지시ěžëĄĽ 쓰는 이유는?

    많은 ě–‘ěť ě •ě  ě»¨í…츠를 ë ŚëŤ”ë§ í•  때, 성능 í–Ąěěť„ 위해 ě—리먼트 ë°Ź 컴포넌트를 한ë˛ë§Ś 렌더ë§í•는 용도로 사용합ë‹ë‹¤.

    Vue.component('legal-terms', {
      template: `
        <div v-once>
          <h1>Legal Terms</h1>
          ... a lot of static content goes here...
        </div>
      `
    })

    Note: ě •ě  ě»¨í…츠가 많아서 ëŠë ¤ě§€ëŠ” 일이 ë°śěťí•ě§€ 않는 한, 과다í•게 사용í•ě§€ 않는 ę˛ěť´ 좋습ë‹ë‹¤.

  97. 루트 Vue ěť¸ěŠ¤í„´ěŠ¤ě— ě ‘ę·Ľí•는 방법은?

    루트 Vue 인스턴스(new Vue())는 $root 속성을 이용해 ě ‘ę·Ľí•  ě ěžěеë‹ë‹¤.

    // The root Vue instance
    new Vue({
      data: {
        age: 26
      },
      computed: {
        fullName: function () { /* ... */ }
      },
      methods: {
        interest: function () { /* ... */ }
      }
    })

    루트 ěť¸ěŠ¤í„´ěŠ¤ěť ëŤ°ěť´í„°ě™€ 메소드들을 í•ěś„ 컴포넌트ě—서 ě•„ëžě™ 10000 € 같은 방법으로 ě ‘ę·Ľí•  ě ěžěеë‹ë‹¤.

    // Get root data
    this.$root.age
    
    // Set root data
    this.$root.age = 29
    
    // Access root computed properties
    this.$root.fullName
    
    // Call root methods
    this.$root.interest()

    ěíś ę´€ë¦¬ëĄĽ 위한 용도라면 Vuex를 사용í•는 ę˛ěť´ 낫습ë‹ë‹¤.

  98. Vue를 사용í•ęł  ěžëŠ” 기업들은?

    ě•„ëžëŠ” Vue를 사용í•ęł  ěžëŠ” 유명 기업들입ë‹ë‹¤.

    1. Facebook
    2. Netflix
    3. Adobe
    4. Xiaomi
    5. Alibaba
    6. WizzAir
    7. EuroNews
    8. Laracasts
    9. GitLab
    10. Laracasts
  99. renderError ë©”ě†Śë“śěť ëŞ©ě ěť€?

    기본 render 함ěę°€ ë ŚëŤ”ë§ ëŹ„ě¤‘ ě—러가 ë°śěťí•ë©´, 대체ë는 ë ŚëŤ”ë§ ę˛°ęłĽëĄĽ 제공합ë‹ë‹¤. renderErrorěť ë‘ ë˛ě§¸ 전달인ěžëˇś ě—러가 전달ë©ë‹ë‹¤.

    new Vue({
      render (h) {
        throw new Error('An error')
      },
      renderError (h, err) {
        return h('div', { style: { color: 'red' }}, err.stack)
      }
    }).$mount('#app')
  100. í•ěś„ 컴포넌트ě—서 ěěś„ 컴포넌트로 ě§ě ‘ ě ‘ę·Ľí•는 방법은?

    ěěś„ 컴포넌트ě—서는 í•ěś„ 컴포넌트들을 $children 배열로 참조í•ë©°, í•ěś„ 컴포넌트ě—서 ěěś„ 컴포넌트를 $parent 속성으로 참조합ë‹ë‹¤.

  101. vuex란?

    Vuex는 Vue.js 애플리케이ě…ěť„ 위한 ěíś ę´€ë¦¬ 패턴 + 라이브러리(Fluxě—서 ěę°ěť„ 받은 ě• í”Śë¦¬ěĽ€ěť´ě… ě•„í‚¤í…Ťě˛)ěž…ë‹ë‹¤. ě측 가능한 방식으로만 ěíśę°€ ëł€ę˛˝ë  ě ěžëŹ„ëˇť 보장í•는 규칙을 가지고 ěžëŠ” 애플리케이ě…ěť ëŞ¨ë“  컴포넌트를 위한 중앙 집중식 저장소입ë‹ë‹¤.

  102. ěíś ę´€ë¦¬ íŚ¨í„´ěť ěŁĽěš” 구성 요소는 무엇입ë‹ęąŚ?

    ěíś ę´€ë¦¬ěť ěŁĽěš” 구성요소는 ěíś ë°Ź ë·°, 액ě…ěž…ë‹ë‹¤. 이러한 ęµ¬ě„±ěš”ě†Śě— ë”°ëĄ¸ 패턴을 애플리케이ě…ě—서 ěíś ę´€ë¦¬ 패턴이라고 í•©ë‹ë‹¤. ě•„ëžě— ěžě„¸í•ś 구성 요소가 ěžě„¸íž 설명ëě–´ ěžěеë‹ë‹¤.

    1. ěíśëŠ” 앱을 구동시키는 ě›ě˛śěž…ë‹ë‹¤.
    2. 뷰는 단지 ěíśěť ě„ ě–¸ě  ë§¤í•‘ěž…ë‹ë‹¤.
    3. 액ě…은 ë·°ě—서 ě‚¬ěš©ěž ěž…ë Ąě— ë°ěť‘í•ě—¬ ěíśę°€ 변할 ě ěžëŹ„ëˇť í•는 방법입ë‹ë‹¤. ěś„ěť 3가지 구성요소와 í•¨ę» ěíś ę´€ë¦¬ 패턴을 따르는 ěą´ěš´í„° ě를 들어보겠습ë‹ë‹¤.
    new Vue({
      // state
      data () {
        return {
          count: 0
        }
      },
      // view
      template: `
        <div>{{ count }}</div>
      `,
      // actions
      methods: {
        increment () {
          this.count++
        }
      }
    })
  103. Vuexě—서 단방향 데이터 íťë¦„ 모델을 어떻게 표í„í•©ë‹ęąŚ?

    Vue.js는 props 속성을 통해 단방향 데이터 íťë¦„ 모델을 표í„í•©ë‹ë‹¤. vuexě—서 이와 동일한 ę°śë…은 ě•„ëžě™€ 같이 ë‚í€ë‚Ľ ě ěžěеë‹ë‹¤.

  104. vuejs loader는 무엇입ë‹ęąŚ?

    Vue loader는 Vue 컴포넌트를 싱글 파일 컴포넌트(SFC, SFCs)라고 í•는 í•식으로 작성할 ě ěžëŠ” 웹팩용 로더입ë‹ë‹¤. ě를 들어 HelloWorld 라는 SFC를 작성í•ë©´ ě•„ëžě™€ 같습ë‹ë‹¤.

    <template>
      <div class="greeting">{{ message }}</div>
    </template>
    
    <script>
    export default {
      data () {
        return {
          message: 'Hello world for vueloader!'
        }
      }
    }
    </script>
    
    <style>
    .greeting {
      color: blue;
    }
    </style>
  105. 웹팩ě—서 vue loader를 설정í•는 방법은?

    Vue-Loaderěť ě„¤ě •ěť€ 웹팩 ě„¤ě •ě— Vue Loaderěť í”Śëź¬ę·¸ěť¸ěť„ 추가í•기 ë•Śë¬¸ě— ë‹¤ëĄ¸ 로더와는 약간 다릅ë‹ë‹¤. Vue 로더 플러그인은 ě •ěťëś 다른 ę·śěą™(js ë°Ź css ę·śěą™)ěť„ 복제í•ě—¬ .vue 파일ě—서 해당 언어 블록(script ë°Ź style)ě— ě ěš©í•기 위해 필요합ë‹ë‹¤. Vue ëˇśëŤ”ě— ëŚ€í•ś 웹팩 ęµ¬ě„±ěť ę°„ë‹¨í•ś ě는 다음과 같습ë‹ë‹¤.

    // webpack.config.js
    const VueLoaderPlugin = require('vue-loader/lib/plugin')
    
    module.exports = {
      mode: 'development',
      module: {
        rules: [
          {
            test: /\.vue$/,
            loader: 'vue-loader'
          },
          // this will apply to both plain `.js` files and `<script>` blocks in `.vue` files
          {
            test: /\.js$/,
            loader: 'babel-loader'
          },
          // this will apply to both plain `.css` files and `<style>` blocks in `.vue` files
          {
            test: /\.css$/,
            use: [
              'vue-style-loader',
              'css-loader'
            ]
          }
        ]
      },
      plugins: [
        // make sure to include the plugin for cloning and mapping them to respective language blocks
        new VueLoaderPlugin()
      ]
    }
  106. vue-loaderěť Asset URL í•¸ë“¤ë§ ę·śěą™ěť€?

    1. ě ëŚ€ 경로(Absolute path): ë§Śě•˝ URL 경로가 /images/loader.png와 같은 ě ëŚ€ 경로라면 그대로 보존ë©ë‹ë‹¤.
    2. ě대 경로(Relative path): ë§Śě•˝ URL 경로가 ./images/loader.png와 같은 ě ëŚ€ 경로라면 ě대 ëŞ¨ë“ ěš”ě˛­(require(./images/loader.png))으로 컴파일ëęł  파일 ě‹śěŠ¤í…śěť íŹ´ëŤ” 구조를 기ë°ěśĽëˇś 해결ë©ë‹ë‹¤.
    3. ~로 시작í•는 경로(URLs starts with ~ symbol): ë§Śě•˝ URL 경로가 ./some-node-package/loader.png와 같은 ~로 시작ëśë‹¤ë©´, ëŞ¨ë“ ěš”ě˛­ěśĽëˇś 컴파일ë©ë‹ë‹¤.
    4. @로 시작í•는 경로(URLs starts with @ symbol): ë§Śě•˝ URL 경로가 @로 시작ëśë‹¤ë©´, ëŞ¨ë“ ěš”ě˛­ěśĽëˇś 컴파일ë©ë‹ë‹¤. ěť´ę˛ěť€ 웹팩 configě— @ě— ëŚ€í•ś 별칭이 ěžëŠ” ę˛˝ěš°ě— ěś ěš©í•ë©°, 기본ě ěśĽëˇś vue-clię°€ ë§Śë“  모든 프로젝트ě—서 /src를 가리킵ë‹ë‹¤.
  107. vue loaderě—서 ě „ě˛ë¦¬ę¸°ëĄĽ 사용í•는 경우라면?

    Vue-loader는 ěž‘ě„±ëś ě–¸ě–´ ë¸”ëˇťěť lang 속성을 이용해 ě ě í•ś 로더를 ě ěš©í•ęł  웹팩 ě„¤ě •ě— ě ěš©ëś 규칙을 따릅ë‹ë‹¤. Vue-loaderě—서 SASS, LESS, Stylusë‚ PostCSS 같은 ě „ě˛ë¦¬ę¸°ëĄĽ 사용할 ě ěžěеë‹ë‹¤.

  108. 범위 CSS(Scoped CSS)란?

    범위를 가지는 CSS(Scoped CSS)는 Vueě—서 싱글 파일 컴포넌트ě—서 해당 ě»´íŹ¬ë„ŚíŠ¸ě— ěž‘ě„±ëś CSSę°€ 다른 ě»´íŹ¬ë„ŚíŠ¸ě— ěí–Ąěť„ 미ěąě§€ 않도록 ę·¸ ě ěš© 범위를 제한í•는 ę˛ěť„ ěťëŻ¸í•©ë‹ë‹¤. 즉, <style> íśę·¸ę°€ scoped 속성을 가지고 ěžë‹¤ë©´, 해당 CSS는 해당 컴포넌트ě—서만 ěí–Ąěť„ 미칩ë‹ë‹¤.

    <style scoped>
    .greeting {
      color: green;
    }
    </style>
    <template>
      <div class="greeting">Let's start Scoped CSS</div>
    </template>

    ěś„ěť ě˝”ë“śëŠ” ě•„ëžëˇś 변í™ë©ë‹ë‹¤.

     <style scoped>
     .greeting[data-v-f3f3eg9] {
       color: green;
     }
     </style>
    <template>
      <div class="greeting" data-v-f3f3eg9>Let's start Scoped CSS</div>
    </template>
  109. 범위 CSS와 ě „ě—­ CSS를 í•¨ę» ě“¸ ě ěžěť„까?

    범위가 ě§€ě •ëś ěŠ¤í€ěťĽęłĽ 범위가 지정ëě§€ 않은 스í€ěťĽěť€ 동일한 ě»´íŹ¬ë„ŚíŠ¸ě— íŹ¬í•¨í•  ě ěžěеë‹ë‹¤.

    <style>
    /* global styles */
    </style>
    
    <style scoped>
    /* local styles */
    </style>
  110. 범위 CSSę°€ ěžě‹ť ě»´íŹ¬ë„ŚíŠ¸ě— ěí–Ąěť„ 미ěąę˛Ś í•는 방법은?

    범위가 ě§€ě •ëś CSSě—서, ěžě‹ť ě»´íŹ¬ë„ŚíŠ¸ě— ěí–Ąěť„ 미ěąę˛Ś í•는 방법은 >>> ě—°ě‚°ěžëĄĽ 사용í•ë©´ ë©ë‹ë‹¤.

    <style scoped>
    .class1 >>> .class2 { /* ... */ }
    </style>

    ěś„ěť CSS는 ě•„ëžëˇś 컴파일ë©ë‹ë‹¤.

    .class1[data-v-f3f3eg9] .class2 { /* ... */ }

    Note: SASSě—서는 >>> ě—°ě‚°ěžę°€ 제대로 작동í•ě§€ 않을 ě ěžěеë‹ë‹¤. 이때는 /deep/ ë는 ::v-deep ě„ íťěžëĄĽ 대신 이용합ë‹ë‹¤.

  111. ěěś„ ě»´íŹ¬ë„ŚíŠ¸ěť ë˛”ěś„ CSSę°€ í•ěś„ ě»´íŹ¬ë„ŚíŠ¸ě— ěí–Ąěť„ 주는가?

    일ë°ě ěśĽëˇś ěěś„ ě»´íŹ¬ë„ŚíŠ¸ěť ěŠ¤í€ěťĽěť€ í•ěś„ ě»´íŹ¬ë„ŚíŠ¸ě— ěí–Ąěť„ 미ěąě§€ 않습ë‹ë‹¤. í•지만 í•ěś„ ě»´íŹ¬ë„ŚíŠ¸ěť ëŁ¨íŠ¸ 노드는 ěěś„ 컴포넌트와 í•ěś„ ě»´íŹ¬ë„ŚíŠ¸ěť ěŠ¤í€ěťĽě— ëŞ¨ë‘ ěí–Ąěť„ 받습ë‹ë‹¤. 즉, í•ěś„ ě»´íŹ¬ë„ŚíŠ¸ěť ëŁ¨íŠ¸ ë…¸ë“śě— ěěś„ 컴포넌트ě—서 ě‚¬ěš©ëś í´ëžěФ氀 사용ëśë‹¤ë©´, ěěś„ ě»´íŹ¬ë„ŚíŠ¸ěť ěŠ¤í€ěťĽěť´ í•ěś„ 컴포넌트ě—도 ěí–Ąěť„ ëĽěą©ë‹ë‹¤. 이는 ěěś„ 컴포넌트ě—서 ë ěť´ě•„ě›ěť„ 위해 í•ěś„ ě»´íŹ¬ë„ŚíŠ¸ě— ěí–Ąěť„ 미칠 ě ěžëŹ„ëˇť ë””ěžěť¸ëś ę˛ěž…ë‹ë‹¤. ě•„ëžěť ě시는 ěěś„ ě»´íŹ¬ë„ŚíŠ¸ěť backgroundę°€ í•ěś„ 컴포넌트ě—까지 ěí–Ąěť„ 미ěąëŠ” ěě śěž…ë‹ë‹¤.

    // parent.vue
    <template>
      <div class="wrapper">
        <p>parent</p>
        <ChildMessageComponent/>
      </div>
    </template>
    
    <script>
    import ChildMessageComponent from "./components/child";
    
    export default {
      name: "App",
      components: {
        ChildMessageComponent
      }
    };
    </script>
    
    <style scoped>
    .wrapper {
      background: blue;
    }
    </style>
    //child.vue
    <template>
      <div class="wrapper">
        <p>child</p>
      </div>
    </template>
    
    <script>
    export default {
      name: "Hello, Scoped CSS",
    };
    </script>
    <style scoped>
    .wrapper {
      background: red;
    }
    </style>

    í•ěś„ ě»´íŹ¬ë„ŚíŠ¸ěť wrapper í´ëžěŠ¤ěť ë°°ę˛˝ě‰ěť€ 빨간ě‰ěť´ ě•„ë‹ëťĽ 파란ě‰ěť´ ë©ë‹ë‹¤.

  112. 동ě ěśĽëˇś ěťě„±ëś 컨í…ě¸ ě— ë˛”ěś„ CSS를 ě ěš©ě‹śí‚¤ëŠ” 방법은?

    범위 CSS는 v-html 지시ěžëˇś 동ě ěśĽëˇś ěťě„±ëś ë‚´ěš©ě— ěí–Ąěť„ 주지 않습ë‹ë‹¤. ěť´ 경우, deep ě„ íťěžëĄĽ 통해 문제를 해결할 ě ěžěеë‹ë‹¤.

  113. Vueě—서 CSS 모ë“ěť„ 사용할 ě ěžěť„까?

    CSS 모ë“은 CSS를 모ë“í™”í•ęł  구성í•는데 ë„리 사용ë는 시스템입ë‹ë‹¤. vue-loader는 시뮬ë ěť´íŠ¸ëś ë˛”ěś„ CSSěť ëŚ€ě•으로 CSS 모ë“과 í•¨ę» 1급 í´ëžěŠ¤ëˇśěť í†µí•©ěť„ 제공합ë‹ë‹¤.

  114. 모든 í…śí”Śë¦żě— ëŚ€í•´ ëź°í€ěž„ 빌드를 í•  ě ěžëД氀?

    ě• ë©ë‹ë‹¤. Vueě—서 사용ë는 템플릿은 ě¤ě§ .vue 파일ě—서만 사용ëë©°, 다른 경우라면 render 함ěę°€ 필요합ë‹ë‹¤.

  115. Vueě—서 CSS 모ë“ěť„ 사용í•는 방법은?

    1. CSS ëŞ¨ë“ í™śě„±í™”: webpack.config.jsěť css-loaderě—서 modules: true ěµě…ěť„ 활성화해줍ë‹ë‹¤.
    // webpack.config.js
    {
      module: {
        rules: [
          // ... other rules omitted
          {
            test: /\.css$/,
            use: [
              'vue-style-loader',
              {
                loader: 'css-loader',
                options: {
                  // enable CSS Modules
                  modules: true,
                  // customize generated class names
                  localIdentName: '[local]_[hash:base64:8]'
                }
              }
            ]
          }
        ]
      }
    }
    1. ëŞ¨ë“ ě†Ťě„± 추가: <style> íśę·¸ě— module 속성을 추가합ë‹ë‹¤.
    <style module>
    .customStyle {
      background: blue;
    }
    </style>
    1. CSS ëŞ¨ë“ ěŁĽěž…: computed 속성인 $styleěť„ 통해 CSS 모ë“ěť„ 객체로 ě ‘ę·Ľí•  ě ěžěеë‹ë‹¤.
    <template>
      <div :class="$style.blue">
        Background color should be in blue
      </p>
    </template>

    :classěť ę°ťě˛´, ë°°ě—´ 문법ě—도 동작합ë‹ë‹¤.

  116. CSS 모ë“ěť„ ě „ě˛ë¦¬ę¸°ě—서 사용할 ě ěžëД氀?

    CSS 모ë“ěť„ ě „ě˛ë¦¬ę¸°ě—서 사용할 ě ěžěеë‹ë‹¤. ě를 들어, Sass ě „ě˛ë¦¬ę¸°ëŠ” 웹팩ě—서 ě•„ëžě™€ 같이 설정할 ě ěžěеë‹ë‹¤.

    // webpack.config.js -> module.rules
    {
      test: /\.scss$/,
      use: [
        'vue-style-loader',
        {
          loader: 'css-loader',
          options: { modules: true }
        },
        'sass-loader'
      ]
    }
  117. CSS 모ë“ě— ě‚¬ěš©ěž ě •ěťěť 이름을 사용할 ě ěžëД氀?

    ěŁĽěž…ëś CSS 모ë“ě— module 속성을 부여해서, 모ë“ěť ěť´ë¦„ěť„ 커스터ë§ěť´ě§•í•  ě ěžěеë‹ë‹¤. *.vue 파일ě—서 ë‘ ěť´ěěť <style> íśę·¸ę°€ 존재할 때, 스í€ěťĽěť´ 서로 덮어쓰지 않게 í•는 데 유용합ë‹ë‹¤. ě를 들어, ě•„ëžě™€ 같이 속성을 줄 ě ěžěеë‹ë‹¤.

    <style module="a">
      /* identifiers injected as a */
    </style>
    
    <style module="b">
      /* identifiers injected as b */
    </style>
  118. 핫 리로드(Hot Reload)란?

    í•« 리로드는 *.vue 파일을 편집할 때 단ěśíž íŽěť´ě§€ëĄĽ 다시 로드í•는 ę˛ěť´ ě•„ë‹™ë‹ë‹¤. í•« 리로드 기능을 사용í•ë©´ *.vue 파일을 편집할 때 해당 ě»´íŹ¬ë„ŚíŠ¸ěť ëŞ¨ë“  인스턴스가 íŽěť´ě§€ëĄĽ 리로딩í•ě§€ 않고 변경ë©ë‹ë‹¤. 심지어 ě•±ěť í„재 ěíśě™€ ëł€ę˛˝ëś ě»´íŹ¬ë„ŚíŠ¸ëĄĽ 보존합ë‹ë‹¤. ěť´ę˛ěť€ 템플릿 ë는 ě»´íŹ¬ë„ŚíŠ¸ěť ěŠ¤í€ěťĽěť„ ěě •í•  때 ę°śë°ś í™ę˛˝ěť´ í¬ę˛Ś ę°śě„ ë©ë‹ë‹¤.

  119. í•« 리로드가 비활성화 ë  ë•ŚëŠ”?

    í•« 리로드는 ě•„ëžěť ě황ě—서는 비활성화 ëě–´ěžěеë‹ë‹¤.

    1. ě›ąíŚ©ěť targetěť´ node일 때 (SSR)
    2. 웹팩이 코드를 minify할 때
    3. process.env.NODE_ENV === 'production'일 때
  120. í•« 리로드를 명시ě ěśĽëˇś 비활성화í•는 방법은?

    hotReload: false ěµě…ěť„ 웹팩 로더ě—서 설정í•ë©´ ë©ë‹ë‹¤.

    module: {
      rules: [
        {
          test: /\.vue$/,
          loader: 'vue-loader',
          options: {
            hotReload: false // disables Hot Reload
          }
        }
      ]
    }
  121. í•« 리로드를 활성화í•는 방법은?

    vue-loader 플러그인은 ë‚´ë¶€ě ěśĽëˇś í•« 리로드를 사용í•ęł  ěžěеë‹ë‹¤. ë§Śě•˝ vue-cli를 이용해 프로젝트를 시작í–다면, í•« 리로드를 바로 사용할 ě ěžěеë‹ë‹¤. ë§Śě•˝ 프로젝트를 ě§ě ‘ 세팅í–다면, webpack-dev-server --hotěµě…으로 프로젝트를 시작해 활성화 í•  ě ěžěеë‹ë‹¤.

  122. í•« 리로드ě—서 ěíśę°€ 보존ë는 규칙은?

    1. ě»´íŹ¬ë„ŚíŠ¸ěť <template>ěť„ ěě •í•  때, ěě •ëś ě»´íŹ¬ë„ŚíŠ¸ëŠ” 모든 ěíśëĄĽ 보존한 채로 다시 렌더ë§ë©ë‹ë‹¤.
    2. ě»´íŹ¬ë„ŚíŠ¸ěť <script>를 ěě •í•  때, ěě •ëś ě»´íŹ¬ë„ŚíŠ¸ëŠ” 해체(destroy) ëś í›„ 다시 ěťě„±(re-create)ë©ë‹ë‹¤.
    3. ě»´íŹ¬ë„ŚíŠ¸ěť <style>ěť„ ěě •í•  때, í•« 리로드는 vue-style-loaderě— ěťí•´ 실행ëë©° ěíśě— ěí–Ąěť„ ëĽěąě§€ 않습ë‹ë‹¤.
  123. Vue loader를 이용해 함ěí• ě»´íŹ¬ë„ŚíŠ¸ëĄĽ ěťě„±í•는 방법은?

    functional 속성을 í…śí”Śë¦żě— ě¶”ę°€í•´ 함ěí• ě»´íŹ¬ë„ŚíŠ¸ëĄĽ ěťě„±í•  ě ěžěеë‹ë‹¤.

    <template functional>
      <div>{{ props.msg }}</div>
    </template>
  124. 함ěí• ě»´íŹ¬ë„ŚíŠ¸ě—서 ě „ě—­ ě†Ťě„±ě— ě ‘ę·Ľí•는 방법은?

    Vue.prototypeě— ě „ě—­ěśĽëˇś ě •ěťëś ě†Ťě„±ě— ě ‘ę·Ľí•´ě•Ľ 한다면, parent 속성을 이용해 ě ‘ę·Ľí•  ě ěžěеë‹ë‹¤.

    <template functional>
      <div>{{ parent.$someProperty }}</div>
    </template>
  125. Vueě—서 테스트 í•는 방법은?

    1. vue-cli: ěś ë‹› 테스트와 e2e 테스트 í™ę˛˝ěť´ 미리 설정ëě–´ ě śęłµë©ë‹ë‹¤.
    2. ě§ě ‘ 세팅: @vue/test-utilsě—서 mocha-webpackěť´ë‚ jest를 *.vue 파일을 대ě으로 ě§ě ‘ 설정합ë‹ë‹¤.
  126. CSSě— Lint를 설정í•는 방법은?

    Stylelint를 이용해 Vueěť ě‹±ę¸€ 파일 ě»´íŹ¬ë„ŚíŠ¸ěť ěŠ¤í€ěťĽ ë¶€ë¶„ěť Lint를 설정할 ě ěžěеë‹ë‹¤. 특정 .vue íŚŚěťĽěť Lint는 ě•„ëžě™€ 같이 실행합ë‹ë‹¤.

    stylelint MyComponent.vue

    다른 방법은 웹팩ě—서 stylelint-webpack-plugin를 dev-dependency로 설ěąí•ęł , 웹팩 설정ě—서 ě•„ëžě™€ 같이 설정í•는 방법입ë‹ë‹¤.

    // webpack.config.js
    const StyleLintPlugin = require('stylelint-webpack-plugin');
    module.exports = {
      // ... other options
      plugins: [
        new StyleLintPlugin({
          files: ['**/*.{vue,htm,html,css,sss,less,scss,sass}'],
        })
      ]
    }
  127. eslint 플러그인을 사용í•는 방법은?

    공식 eslint-plugin-vue 플러그인은 Vueěť ě‹±ę¸€ 파일 ě»´íŹ¬ë„ŚíŠ¸ěť í…śí”Śë¦żęłĽ 스í¬ë¦˝íЏ ë¶€ë¶„ě— ëŚ€í•´ Lint를 제공합ë‹ë‹¤.

    // .eslintrc.js
    module.exports = {
      extends: [
        "plugin:vue/essential"
      ]
    }

    특정 íŚŚěťĽě— ëŚ€í•ś Lint는 ě•„ëžě™€ 같이 실행할 ě ěžěеë‹ë‹¤.

    eslint --ext js,vue MyComponent.vue
  128. eslint-loader를 사용í•는 이유는?

    eslint-loader를 ěť´ěš©í•ë©´ ę°śë°ś ëŹ„ě¤‘ě— ěžëŹ™ěśĽëˇś *.vue íŚŚěťĽë“¤ě— ëŚ€í•´ Lint를 ě ěš©ě‹śí‚¬ ě ěžěеë‹ë‹¤.

    ěš°ě„  ě•„ëžě™€ 같이 NPM 모ë“ěť„ 설ěąí•´ě•Ľ í•©ë‹ë‹¤.

    npm install -D eslint eslint-loader

    ę·¸ 후 ě›ąíŚ©ěť ě„¤ě •ě— ě¶”ę°€í•´ě•Ľ í•©ë‹ë‹¤.

    // webpack.config.js
    module.exports = {
      // ... other options
      module: {
        rules: [
          {
            enforce: 'pre',
            test: /\.(js|vue)$/,
            loader: 'eslint-loader',
            exclude: /node_modules/
          }
        ]
      }
    }
  129. CSS 단일 파일 추출이란?

    CSS 단일 파일 추출(CSS Extraction)은 모든 Vue 컴포넌트ě—서 ě‚¬ěš©ëś CSS를 단일 CSS 파일로 추출í•는 ę˛ěť„ ěťëŻ¸í•©ë‹ë‹¤.

    npm install -D mini-css-extract-plugin

    ę·¸ 후 ě›ąíŚ©ěť ě„¤ě •ě— ě¶”ę°€í•´ě•Ľ í•©ë‹ë‹¤.

    // webpack.config.js
    var MiniCssExtractPlugin = require('mini-css-extract-plugin')
    
    module.exports = {
      // other options...
      module: {
        rules: [
          // ... other rules omitted
          {
            test: /\.css$/,
            use: [
              process.env.NODE_ENV !== 'production'
                ? 'vue-style-loader'
                : MiniCssExtractPlugin.loader,
              'css-loader'
            ]
          }
        ]
      },
      plugins: [
        // ... Vue Loader plugin omitted
        new MiniCssExtractPlugin({
          filename: 'style.css'
        })
      ]
    }
  130. ě‚¬ěš©ěž ě •ěť ë¸”ëˇťěť´ëž€?

    ě‚¬ěš©ěž ě •ěť ë¸”ëˇť(Custom block)은 *.vue 파일ě—서 사용할 ě ěžëŠ” <template>, <script>, <style> íśę·¸ 블록 ěť´ě™¸ěť ë¸”ëˇťěť„ ě •ěťí•는 ę˛ěť„ ë§í•©ë‹ë‹¤. lang 속성, íśę·¸ 이름, 웹팩 ě„¤ě •ěť resourceQuery ě†Ťě„±ě— ěťí•´ ě •ěťí•  ě ěžěеë‹ë‹¤. ě•„ëž ě시는 *.vue 파일ě—서 <message>로 ě •ěťëś íśę·¸ëĄĽ 찾는 방법입ë‹ë‹¤.

    {
      module: {
        rules: [
          {
            resourceQuery: /blockType=message/,
            loader: 'loader-to-use'
          }
        ]
      }
    }
  131. What are the features of stylelint?

    Below are the list of major stylelint features

    1. It has more than 160 built-in rules to catch errors, apply limits and enforce stylistic conventions
    2. Understands latest CSS syntax including custom properties and level 4 selectors
    3. It extracts embedded styles from HTML, markdown and CSS-in-JS object & template literals
    4. Parses CSS-like syntaxes like SCSS, Sass, Less and SugarSS
    5. Supports Plugins for reusing community plugins and creating own plugins
  132. What are the principles for vuex application structure?

    Vuex enforces below rules to structure any application.

    1. Application-level state is centralized in the store.
    2. The only way to mutate the state is by committing mutations, which are synchronous transactions.
    3. Asynchronous logic should be encapsulated in, and can be composed with actions. The project structure for any non-trivial application would be as below,
  133. Is Vuex supports hot reloading?

    Yes, Vuex supports hot-reloading for mutations, modules, actions and getters during development. You need to use either webpack's hot module replacement API or browserify's hot module replacement plugin.

  134. What is the purpose of hotUpdate API of vuex store?

    The store.hotUpdate() API method is used for mutations and modules. For example, you need to configure vuex store as below,

    // store.js
    import Vue from 'vue'
    import Vuex from 'vuex'
    import mutations from './mutations'
    import myModule from './modules/myModule'
    
    Vue.use(Vuex)
    
    const state = { message: "Welcome to hot reloading" }
    
    const store = new Vuex.Store({
      state,
      mutations,
      modules: {
        moduleA: myModule
      }
    })
    
    if (module.hot) {
      // accept actions and mutations as hot modules
      module.hot.accept(['./mutations', './modules/newMyModule'], () => {
        // Get the updated modules
        const newMutations = require('./mutations').default
        const newMyModule = require('./modules/myModule').default
        //swap in the new modules and mutations
        store.hotUpdate({
          mutations: newMutations,
          modules: {
            moduleA: newMyModule
          }
        })
      })
    }
  135. How do you test mutations?

    Since mutations are just functions that completely rely on their arguments it will be easier to test. You need to keep mutations inside your store.js file and should also export the mutations as a named export apart from default export. Let's take an example of increment mutations,

    // mutations.js
    export const mutations = {
      increment: state => state.counter++
    }

    And test them using mocha and chai as below,

    // mutations.spec.js
    import { expect } from 'chai'
    import { mutations } from './store'
    
    // destructure assign `mutations`
    const { increment } = mutations
    
    describe('mutations', () => {
      it('INCREMENT', () => {
        // mock state
        const state = { counter: 10 }
        // apply mutation
        increment(state)
        // assert result
        expect(state.counter).to.equal(11)
      })
    })
  136. How do you test your getters?

    It is easier to test getters similar to mutations. It is recommended to test these getters if they have complicated computation. Let's take a simple todo filter as a getter

    // getters.js
    export const getters = {
      filterTodos (state, status) {
        return state.todos.filter(todo => {
          return todo.status === status
        })
      }
    }

    And the test case for above getter as follows,

    // getters.spec.js
    import { expect } from 'chai'
    import { getters } from './getters'
    
    describe('getters', () => {
      it('filteredTodos', () => {
        // mock state
        const state = {
          todos: [
            { id: 1, title: 'design', status: 'Completed' },
            { id: 2, title: 'testing', status: 'InProgress' },
            { id: 3, title: 'development', status: 'Completed' }
          ]
        }
        // mock getter
        const filterStatus = 'Completed'
    
        // get the result from the getter
        const result = getters.filterTodos(state, filterStatus)
    
        // assert the result
        expect(result).to.deep.equal([
          { id: 1, title: 'design', status: 'Completed' },
          { id: 2, title: 'development', status: 'Completed' }
        ])
      })
    })
  137. What is the procedure to run tests in node?

    By proper mocking, you can bundle tests with webpack and run them on node without having depenceny on Browser API. It involves 2 steps,

    1. Create webpack config: Create webpack config with proper .babelrc
    // webpack.config.js
    module.exports = {
      entry: './test.js',
      output: {
        path: __dirname,
        filename: 'test-bundle.js'
      },
      module: {
        loaders: [
          {
            test: /\.js$/,
            loader: 'babel-loader',
            exclude: /node_modules/
          }
        ]
      }
    }
    
    1. ** Run testcases:** First you need to bundle and then run them using mocha as below,
    webpack
    mocha test-bundle.js
  138. What is the procedure to run tests in browser?

    Below are the steps to run tests in real browser,

    1. Install mocha-loader.
    2. Configure webpack config entry point to 'mocha-loader!babel-loader!./test.js'.
    3. Start webpack-dev-server using the config.
    4. Go to localhost:8080/webpack-dev-server/test-bundle to see the test result
  139. What is the purpose of strict mode in vuex?

    In strict mode, whenever Vuex state is mutated outside of mutation handlers, an error will be thrown. It make sure that all state mutations can be explicitly tracked by debugging tools. You can just enable this by passing strict: true while creating the vuex store.

    const store = new Vuex.Store({
      // ...
      strict: true
    })
  140. Can I use strict mode in production environment?

    No, it is not recommended to use strict mode in production environment. Strict mode runs a synchronous deep watcher on the state tree for detecting inappropriate mutations and it can be quite expensive when you perform large amount of mutations. i.e, It can impact performance if you enable in production mode. Hence it should be handled through build tools,

    const store = new Vuex.Store({
      // ...
      strict: process.env.NODE_ENV !== 'production'
    })
  141. What is vuex plugin?

    The vuex plugin is an option hat exposes hooks for each mutation. It is a normal function that receives the store as the only argument. You can create your own plugin or use built-in plugins. The plugin skeleton would be as below,

    const myPlugin = store => {
      // called when the store is initialized
      store.subscribe((mutation, state) => {
        // called after every mutation.
        // The mutation comes in the format of `{ type, payload }`.
      })
    }

    After that plugin can be configured for plugins options as below,

    const store = new Vuex.Store({
      // ...
      plugins: [myPlugin]
    })
  142. How do you mutate state in plugins?

    Similar to components you can't mutate state directly but they can trigger changes by by committing mutations. This way a plugin can be used to sync a data source to the store. For example, createWebSocketPlugin plugin is used to sync a websocket data source to the store.

    export default function createWebSocketPlugin (socket) {
      return store => {
        socket.on('data', data => {
          store.commit('receiveData', data)
        })
        store.subscribe(mutation => {
          if (mutation.type === 'UPDATE_DATA') {
            socket.emit('update', mutation.payload)
          }
        })
      }
    }

    And then configure plugin in vuex store as below

    const plugin = createWebSocketPlugin(socket)
    
    const store = new Vuex.Store({
      state,
      mutations,
      plugins: [plugin]
    })
  143. What is vuex store?

    A Vuex "store" is basically a container that holds your application state. The store creation is pretty straightforward. Below are the list of instructions to use vuex in an increment application,

    1. Configure vuex in vuejs ecosystem
    import Vuex from "vuex";
    Vue.use(Vuex)
    1. Provide an initial state object and some mutations
    // Make sure to call Vue.use(Vuex) first if using a module system
    
    const store = new Vuex.Store({
      state: {
        count: 0
      },
      mutations: {
        increment (state) {
          state.count++
        }
      }
    })
    1. Trigger state change with commit and access state variables,
    store.commit('increment')
    
    console.log(store.state.count) // -> 1
  144. What are the differences of vuex store and plain global object?

    Below are the two major differences between vuex store and plain global object

    1. Vuex stores are reactive: If the store's state changes then vue components will reactively and efficiently get updated
    2. Cannot directly mutate the store's state: The store's state is changed by explicitly committing mutations to ensure that every state change leaves a track-able record for tooling purpose
  145. What is the reason not to update the state directly?

    We want to explicitly track application state in order to implement tools that can log every mutation, take state snapshots, or even perform time travel debugging. So we need to commit a mutation instead of changing store's state directly.

  146. What is Single state tree?

    Vuex's single state tree is single object contains all your application level state and serves as the "single source of truth". It does not conflict with modularity when you split state and mutations into sub modules.

  147. How do you install vuex?

    You can install vuex using npm or yarn as below,

    npm install vuex --save
    (or)
    yarn add vuex

    In a module system, you must explicitly install Vuex via Vue.use()

    import Vue from 'vue'
    import Vuex from 'vuex'
    
    Vue.use(Vuex)

    (OR) You can also install it using CDN links such as unpkg.cpm which provides NPM-based CDN links. Just include vuex after Vue and it will install itself automatically.

    <script src="https://unpkg.com/vue.js"></script>
    <script src="https://unpkg.com/vuex.js"></script>

    Note: You can use a specific version/tag via URLs like https://unpkg.com/vuex@2.0.0. If you don't mention any version then it will point to latest version.

  148. Do I need promise for vuex?

    Yes, Vuex requires Promise. If your supporting browsers do not implement Promise (e.g. IE), you can use a polyfill library, such as es6-promise using npm or yarn.

    npm install es6-promise --save # NPM
    yarn add es6-promise # Yarn

    After that import into anywhere in your application,

    import 'es6-promise/auto'
  149. How do you display store state in vue components?

    Since Vuex stores are reactive, you can retrieve" state from store by simply returning store's state from within a computed property. i.e, Whenever store state changes, it will cause the computed property to re-evaluate, and trigger associated DOM updates. Let's take a hello word component which display store's state in the template,

    // let's create a hello world component
    const Greeting = {
      template: `<div>{{ greet }}</div>`,
      computed: {
        greet () {
          return store.state.msg
        }
      }
    }
  150. How do you inject store into child components?

    Vuex provides a mechanism to "inject" the store into all child components from the root component with the store option. It will be enabled by vue.use(vuex). For example, let's inject into our app component as below,

    const app = new Vue({
      el: '#app',
      // provide the store using the "store" option.
      // this will inject the store instance to all child components.
      store,
      components: { Greeting },
      template: `
        <div class="app">
          <greeting></greeting>
        </div>
      `
    })

    Now the store will be injected into all child components of the root and will be available on them as this.$store

     // let's create a hello world component
         const Greeting = {
           template: `<div>{{ greet }}</div>`,
           computed: {
             greet () {
               return this.$store.state.msg
             }
           }
         }
  151. What is mapState helper?

    In Vuex application, creating a computed property every time whenever we want to access the store's state property or getter is going to be repetitive and verbose, especially if a component needs more than one state property. In this case, we can make use of the mapState helper of vuex which generates computed getter functions for us. Let's take an increment example to demonstrate mapState helper,

    // in full builds helpers are exposed as Vuex.mapState
    import { mapState } from 'vuex'
    
    export default {
      // ...
      computed: mapState({
        // arrow functions can make the code very succinct!
        username: state => state.username,
    
        // passing the string value 'username' is same as `state => state.username`
        usernameAlias: 'username',
    
        // to access local state with `this`, a normal function must be used
         greeting (state) {
          return this.localTitle + state.username
        }
      })
    }

    We can also pass a string array to mapState when the name of a mapped computed property is the same as a state sub tree name

    computed: mapState([
      // map this.username to store.state.username
      'username'
    ])
  152. How do you combine local computed properties with mapState helper?

    You can use object spread operator syntax in order to combine mapState helper(which returns an object) with other local computed properties. This way it simplify merging techniques using utilities.

    computed: {
      localComputed () { /* ... */ },
      // mix this into the outer object with the object spread operator
      ...mapState({
        // ...
      })
    }
  153. Do you need to replace entire local state with vuex?

    No, if a piece of state strictly belongs to a single component, it could be just fine leaving it as local state. i.e, Eventhough vuex used in the application, it doesn't mean that you need to keep all the local state in vuex store. Other the code becomes more verbose and indirect although it makes your state mutations more explicit and debuggable.

  154. What are vuex getters??

    Vuex getters acts as computed properties for stores to compute derived state based on store state. Similar to computed properties, a getter's result is cached based on its dependencies, and will only re-evaluate when some of its dependencies have changed. Let's take a todo example which as completedTodos getter to find all completed todos,

    const store = new Vuex.Store({
      state: {
        todos: [
          { id: 1, text: 'Vue course', completed: true },
          { id: 2, text: 'Vuex course', completed: false },
          { id: 2, text: 'Vue Router course', completed: true }
        ]
      },
      getters: {
        completedTodos: state => {
          return state.todos.filter(todo => todo.completed)
        }
      }
    })

    **Note:**Getters receive state as first argument.

  155. What is a property style access?

    You can access values of store's getter object(store.getters) as properties. This is known as property style access. For example, you can access todo's status as a property,

    store.getters.todosStatus

    The getters can be passed as 2nd argument for other getters. For example, you can derive completed todo's count based on their status as below,

    getters: {
      completedTodosCount: (state, getters) => {
        return getters.todosStatus === 'completed'
      }
    }

    Note: The getters accessed as properties are cached as part of Vue's reactivity system.

  156. What is a method style access?

    You can access store's state in a method style by passing arguments. For example, you can pass user id to find user profile information as below,

    getters: {
      getUserProfileById: (state) => (id) => {
        return state.users.find(user => user.id === id)
      }
    }

    After that you can access it as a method call,

    store.getters.getUserProfileById(111); {id: '111', name: 'John', age: 33}
  157. What is mapGetter helper??

    The mapGetters is a helper that simply maps store getters to local computed properties. For example, the usage of getters for todo app would be as below,

    import { mapGetters } from 'vuex'
    
    export default {
      computed: {
        // mix the getters into computed with object spread operator
        ...mapGetters([
          'completedTodos',
          'todosCount',
          // ...
        ])
      }
    }
  158. What are mutations?

    Vuex mutations are similar to any events with a string type and a handler. The handler function is where we perform actual state modifications, and it will receive the state as the first argument. For example, the counter example with increment mutation would be as below,

    const store = new Vuex.Store({
      state: {
        count: 0
      },
      mutations: {
        increment (state) {
          // mutate state
          state.count++
        }
      }
    })

    You can't directly invoke mutation instead you need to call store.commit with its type. The above mutation would be triggered as folows

    store.commit('increment')
  159. How do you commit with payload?

    You can also pass payload for the mutation as an additional argument to store.commit. For example, the counter mutation with payload object would be as below,

    mutations: {
      increment (state, payload) {
        state.count += payload.increment
      }
    }

    And then you can trigger increment commit

    store.commit('increment', {
      increment: 20
    })

    Note: You can also pass primitives as payload.

  160. What is object style commit?

    You can also commit a mutation is by directly using an object that has a type property.

    store.commit({
      type: 'increment',
      value: 20
    })

    Now the entire object will be passed as the payload to mutation handlers(i.e, without any changes to handler signature).

    mutations: {
      increment (state, payload) {
        state.count += payload.value
      }
    }
  161. What are the caveats with vuex mutations?

    Since a Vuex store's state is made reactive by Vue, the same reactivity caveats of vue will apply to vuex mutations. These are the rules should be followed for vuex mutations,

    1. It is recommended to initialize store's initial state with all desired fields upfront
    2. Add new properties to state Object either by set method or object spread syntax
    Vue.set(stateObject, 'newProperty', 'John')

    (OR)

    state.stateObject = { ...state.stateObject, newProperty: 'John' }
  162. Why mutations should be synchronous?

    You need to remember that mutation handler functions must be synchronous. This is why because any state mutation performed in the callback is essentially un-trackable. It is going to be problematic when the devtool will need to capture a "before" and "after" snapshots of the state during the mutations.

    mutations: {
      someMutation (state) {
        api.callAsyncMethod(() => {
          state.count++
        })
      }
    }
  163. How do you perform mutations in components?

    You can commit mutations in components with either this.$store.commit('mutation name') or mapMutations helper to map component methods to store.commit calls. For example, the usage of mapMutations helper on counter example would be as below,

    import { mapMutations } from 'vuex'
    
    export default {
      methods: {
        ...mapMutations([
          'increment', // map `this.increment()` to `this.$store.commit('increment')`
    
          // `mapMutations` also supports payloads:
          'incrementBy' // map `this.incrementBy(amount)` to `this.$store.commit('incrementBy', amount)`
        ]),
        ...mapMutations({
          add: 'increment' // map `this.add()` to `this.$store.commit('increment')`
        })
      }
    }
  164. Is it mandatory to use constants for mutation types?

    No, it is not mandatory. But you might observed that State management implementations such Flux and Redux use constants for mutation types. This convention is just a preference and useful to take advantage of tooling like linters, and putting all constants in a single file allows your collaborators to get an at-a-glance view of what mutations are possible in the entire application. For example, the mutations can be declared as below,

    // mutation-types.js
    export const SOME_MUTATION = 'SOME_MUTATION'

    And you can configure them in store as follows,

    // store.js
    import Vuex from 'vuex'
    import { SOME_MUTATION } from './mutation-types'
    
    const store = new Vuex.Store({
      state: { ... },
      mutations: {
        // ES2015 computed property name feature to use a constant as the function name
        [SOME_MUTATION] (state) {
          // mutate state
        }
      }
    })
  165. How do you perform asynchronous operations?

    In Vuex, mutations are synchronous transactions. But if you want to handle asynchronous operations then you should use actions.

  166. What are differences between mutations and actions?

    Actions are similar to mutations, but there are two main differences,

    1. Mutations perform mutations on the state, actions commit mutations.
    2. Actions can contain arbitrary asynchronous operations unlike mutations.

About

VueJS interview questions in Korean language

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Contributors 5

0