메뉴

문서정보

목차

Vue.js Component

웹 사이트들은 서로 다른 여러 컴포넌트들고 구성이 된다. 이들 컴포넌트들은 더 작은 컴포넌트들로 구성되기도 하며, 재사용되기도 한다. Vue 컴포넌트는 일종의 함수로, 코드를 재사용 할 수 있게 하고 가독성을 높여준다.

일반적인 사이트는 헤더, 탑 메뉴, 사이드바, 컨텐츠, 바닥 글 등의 독립적인 컴포넌트로 구성된다. 이들을 함께 배치해서 사용자 인터페이스가 만들어진다. Vue의 컴포넌트를 이용해서 사용자 인터페이스의 각 요소들을 재 사용 가능한 캡슐화된 코드로 만들 수 있다. Vue 컴포넌트는 HTML 엘리먼트를 확장 할 수 있다. 예를 들어 블로그 사이트는 아래와 같이 구성 할 수 있다.
<header></header>
<aside>
  <sidebar-item v-for="item in items"></sidebar-item>
</aside>
<main>
  <blog-post></blog-post>
</main>
<footer></footer>
위 구성의 장점은 완전히 재사용 가능하고 HTML 그 자체가 문서화된다는 거다. HTML의 section과 같은 태그를 사용하는 대신에 "blog-post", "posts-list"와 같은 의미를 명확히 전달 할 수 있는 이름을 사용 할 수 있다.

전역 컴포넌트 등록

Vue.component(tagName, options)로 컴포넌트를 등록 할 수 있다.
Vue.component('my-component', {
  // 옵션
})

// vue 인스턴스 생성
var vue = new Vue({
})

간단한 예제다.
사용한 코드다.
<div id="example01">
  <my-component01></my-component01>
</div>

<script>
Vue.component('my-component01', {
    template: '<div>테스트 컴포넌트</div>'
})
new Vue({
  el: '#example01' 
})
</script>

예제 : 버튼 카운터

<div id="components-demo">
  <button-counter></button-counter>
</div>
<script>
Vue.component('button-counter', {
  template: '<button type="button" class="button" v-on:click="count++">{{ count }}번 클릭했습니다.</button>',
  data: function () {
    return {
      count: 0
    }
  }
})
new Vue({el:'#components-demo'})
</script>

컴포넌트의 이름은 "button-counter"이다. 버튼을 클릭하면 count 값을 +1 해서 출력한다.

hello 컴포넌트 개발

약간 더 복잡한 컴포넌트를 개발하기로 했다. 이 녀석은 "/api/hello" 라는 RESTful API를 호출한다. 내 사이트(joinc.co.kr)에서 테스트목적으로 서비스하고 있는 api 다. curl로 먼저 테스트해보자.
$ curl https://www.joinc.co.kr/api/hello -i
HTTP/1.1 200 OK
Server: nginx/1.4.6 (Ubuntu)
Date: Tue, 01 May 2018 15:43:30 GMT
Content-Type: text/html
Content-Length: 19
Connection: keep-alive
X-Upstream: 127.0.0.1:8100

{"name":"yundream"}
hello 컴포넌트는 1. submit 버튼을 누르면, 2. /api/hello를 호출하고 3. 그 결과를 화면에 출력하는 일을 한다. 지금까지 Ajax 호출은 jQuery를 사용했는데, 이번에는 axios를 사용하기로 했다. axios를 선택한 이유는 jQuery 노가다가 왠지 싫어서, Vue.js를 키워드로 검색해보니 axios가 딸려나와서 이다. 헤더에 vue.js와 axios를 추가했다. 컴포넌트를 등록했다.
<div class="row">
    <div class="large-4 column">    
    <div id="app">
        <test-item></test-item>
    </div>
    </div>
</div>

<script>
Vue.component('test-item', {
    template: `
<form class="" method="post" @submit.prevent="postNow">
    <div class="input-group">
        <input type="text" name="" value="" v-model="name">
        <div class="input-group-button">
        <button type="submit" name="button" class="button">Submit</button>                                                                                              
        </div>
    </div>
</form>`,
  data: function() {
    return {
        name: [] 
    }
  },
  methods: {
    postNow: function() {
        axios.post('/api/hello', this.name, {headers: {
       'Content-type': 'application/json',
        }}).then(response => {
            this.name = response.data.name
        });
    }
  } 
}); 
new Vue({
	el: '#app'
})
</script>

화면에 출력해보자. Submit 하면 데이터를 받아온다. 어떤 값을 넣고 Submit 하든 동일한 값을 읽어온다. 테스트니까 그러려니 하자.
코드를 분석해 보자.
new Vue({
	el: '#app'
})
Vue 앱은 Vue인스턴스를 만드는 것으로 시작한다. 인스턴스에는 데이터, 템플릿, 마운트할 엘리먼트, 콜백 등등의 옵션을 포함할 수 있다. 여기에서 만든 Vue 앱은 app앨리먼트만 마운트 하고 있다.

Vue.component('test-item', {
    template: `
<form class="" method="post" @submit.prevent="postNow">
    <div class="input-group">
        <input type="text" name="" value="" v-model="name">
        <div class="input-group-button">
        <button type="submit" name="button" class="button">Submit</button>                                                                                              
        </div>
    </div>
</form>`,
  data: function() {
    return {
        name: [] 
    }
  },
  methods: {
    postNow: function() {
        axios.post('/api/hello', this.name, {headers: {
       'Content-type': 'application/json',
        }}).then(response => {
            this.name = response.data.name
        });
    }
  } 
}); 
"test-item"이라는 컴포넌트를 만들었다. 컴포넌트는 Vue 인스턴스와 마찬가지로 데이터, 템플릿, 콜백등을 모두 포함 할 수 있다. test-item 컴포넌트는 UI요소까지 템플릿으로 포함하고 있다. 완전한 배포단위로 재활용 할 수 있다는 얘기다.

v-model은 input 앨리먼트의 값과 데이터를 양방향으로 바인딩하기 위해서 사용하는 지시문(Directive)다. 여기에서는 /aip/hello 결과 값을 input에 출력하기 위해서 사용했다. submit.prevent는 submit 이벤트가 페이지를 다시 로딩하지 않도록 한다.

Vue앱이 실행할 메서드는 methods에 정의 한다. postNow 메서드는 /api/hello api를 호출하고 그 결과를 바인딩된 "name" input에 출력하는 일을 한다.

GoLang + Vuejs

Vue 관련 문서를 보면 주로 node와 많이 사용하는 것 같기는 하지만, 언어에 종속성이 있는 건 아니다. 나는 go 언어를 사용하는데 go template가 "{{ }}"를 사용하기 때문에, 함께 쓰면 템플릿을 제대로 해석하지 못한다. Vue.options.delimiters 로 delimiter를 변경해서 사용하고 있다.
<script>Vue.options.delimiters = ['<%', '%>']</script>