이전 글: Vue.js: 기초 사용 방법 + 예제: 이름으로 보는 운세

 

요구사항: Home, Portfolio, Guestbook 3개의 메뉴로 된 홈페이지를 만들되 각 메뉴는 Vue.js의 컴포넌트를 사용하여 작성하시오.

<!DOCTYPE html>
<html lang="ko">
<head>
  <meta charset="UTF-8">
  <title>Homepage</title>
  <link rel="stylesheet" href="[부트스트랩-cdn-주소]">
</head>

<body class=container>

  <nav id="home-nav" class="navbar navbar-expand-lg navbar-dark bg-dark">
    <a class="navbar-brand" href="#">{{ title }}</a>
    <button class="navbar-toggler" type="button">
      <span class="navbar-toggler-icon"></span>
    </button>

    <div class="collapse navbar-collapse" id="navbarColor02">
      <ul class="navbar-nav mr-auto">
        <li class="nav-item" v-for="item in menus">
          <a class="nav-link" href="#" v-on:click="moveMenu">{{ item }}</a>
        </li>
      </ul>
    </div>
  </nav>

  <!-- 컴포넌트 부분, :contents 는 article객체의 currentContents에 있는 내용을 불러온다. -->
  <article id="home-article" class="row">
    <display-article :contents="currentContents">

    </display-article>
  </article>

  <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
  <script src="./index.js"></script>
</body>
</html>

<article>은 HTML5에 나오는 태그로 웹사이트에서 읽을 거리 등 주요 내용이 들어가는 의미를 가진(semantic) 구역(div) 태그입니다. 하위에 위치한  <display-article>이 컴포넌트가 들어갈 자리입니다. 이 태그의 이름은 실제 HTML5 스펙에는 없는 이름으로 Vue.js의 컴포넌트의 이름은 만드는 사람 마음대로 지을 수 있다는 것이 특징입니다.

컴포넌트는 HTML 상에서는 껍데기 부분만 선언해놓고 실제 내용은 다른 곳에서 작성된다는 특징이 있습니다. 보통 규모가 있는 개발 환경에서는 *.Vue 라는 확장자의 파일로 따로 작성되는데, 지금은 예제이므로 단순하게 컴포넌트를 스크립트 부분에 선언해 보겠습니다.

:contentsv-bind:contents의 약자로 currentContents 의 내용이 (실시간으로) 컴포넌트의 propscontents에 대입된다는 의미입니다.

 

Vue.component('display-article', {
  template: '<div class="col-12 text-primary">{{ contents }}</div>',
  props: ['contents']
})

컴포넌트의 전역 선언 방법입니다. 지역 스코프로 선언하는 방법도 있지만 지금은 넘어가겠습니다. 프로퍼티(props)로 contents를 지정하고, 그 contents를 템플릿 안에서 사용한다는 의미입니다. propcontents가 바뀔 때마다 템플릿 안의 내용도 바뀌게 됩니다. 그럼 이 contents라는 이름의 무언가를 다루는 방법에 대해 알아보겠습니다.

그 전에 템플릿에 대한 주의 사항이 있습니다. 템플릿(template)는 실제 컴포넌트 안에 렌더링될 내용들이 들어 있는 곳인데, 템플릿의 내용은 <display-article>의 하위 태그로 들어가는 것이 아니며, 해당 태그를 대체합니다. 즉, 렌더링된 최종 결과에서 임의로 선언한 <display-article>는 사라지고 그 자리를 템플릿의 <div> 태그가 차지할 것입니다.

 

var nav = new Vue({
  el: "#home-nav",
  data: {
    title: "홈페이지",
    menus: ["Home", "Portfolio", "Guestbook"],
    contents: {
      home: "첫화면입니다",
      portfolio: "포트폴리오입니다.",
      guestbook: "방명록입니다."
    }
  },
  methods: {
    moveMenu: function (e) {
      var menu = e.target.text.toLowerCase()
      // 클릭하면 메뉴값을 article.currnetContents에 대입한다.
      article.currentContents = this.contents[menu] 
    }
  }
})

var article = new Vue({
  el: "#home-article",
  data:{
    currentContents: ""
  }
})

// 첫 화면 지정
window.onload = function(){ 
  article.currentContents = nav.contents.home 
}

nav 변수는 내비게이터 부분인 <nav> 태그를 관리하는 Vue.js 인스턴스입니다. methodsmoveMenu라는 것이 있는데 이 메소드가 실행되면 contents[menu]의 내용이 article.currentContents에 할당합니다. 예를 들어 menuguestbook이라면 this.contents["guestbook"] 에 있는 "방명록입니다." 라는 내용을 article.currentContents에 할당하겠다는 의미와 동일합니다.

맨 위 HTML 부분의 <display-article> 태그에서 :contents="currentContents" 부분을 다시 보겠습니다. <article>이 Vue.js 인스턴스 관리 하에 있으므로 하위에 있는 <display-article>이라는 태그도 currentContents 데이터를 인식할 수 있습니다.  여기서 contents는 전역 선언한 컴포넌트 'display-article' 의 프로퍼티입니다. currentContentsnav 인스턴스의 메소드에 의해 변경되면, 그것이 컴포넌트의 프로퍼티인 contents로 전달되며, 프로퍼티는 다시 템플릿(template) 안으로 전달됩니다. 브라우저에서는 템플릿의 내용을 바탕으로 컴포넌트 안이 렌더링됩니다. 이것을 순서대로 표시하면 아래 그림과 같습니다.

 

결과화면입니다. JSFiddle에서도 볼 수 있습니다.

문의 | 코멘트 또는 ayaysir0@naver.com

donaricano-btn
카테고리: WEB: FrontendVue.js

댓글 남기기

이메일은 공개되지 않습니다. 필수 입력창은 * 로 표시되어 있습니다