본문 바로가기

FE/Vue.js

[ Vue.js ] 싱글 파일 컴포넌트

 

 

 

싱글파일 컴포넌트

 

화면의 특정 영역에 대한 HTML, CSS, JS 코드를 한 파일에서 관리하는 방법

뷰 CLI로 프로젝트를 생성하고 나면 App.vue라는 파일을 확인할 수 있다.

이처럼 vue확장자를 가진 파일을 모두 싱글파일 컴포넌트라고 한다.

 

 

동작 흐름

index.html (화면 출력) > Main.js > App.vue > 컴포넌트

 

index.html

<!DOCTYPE html>
<html lang="">
  <head>
    <meta charset="utf-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width,initial-scale=1.0" />
    <link rel="icon" href="<%= BASE_URL %>favicon.ico" />
    <title><%= htmlWebpackPlugin.options.title %></title>
  </head>
  <body>
    <noscript>
      <strong
        >We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work
        properly without JavaScript enabled. Please enable it to
        continue.</strong
      >
    </noscript>
    <div id="app"></div>
    <!-- built files will be auto injected -->
    <!-- 이 안에 표시되는 결과물이 Vue CLI로 빌드된 결과물 -->
  </body>
</html>

div태그안에서 Vue CLI로 빌드된 결과물이 나타나는것

 

 

Main.js

// 뷰 라이브러리를 들고옴
import { createApp } from "vue";
// 뷰 파일을 들고옴
import App from "./App.vue";

createApp(App).mount("#app");

여기서 App.vue를 임포트하고있고 

 

 

App.vue

<!-- HTML -->
<template>
  <img alt="Vue logo" src="./assets/logo.png" />
  <HelloWorld msg="Welcome to Your Vue.js App" />
</template>

<!-- JavaScript -->
<script>
// import 라이브러리 from '라이브러리이름'
// import 파일이름 from './파일경로'
import HelloWorld from "./components/HelloWorld.vue";

export default {
  //인스턴스 옵션 속성 > data, methods
  name: "App",
  components: {
    HelloWorld,
  },
};
</script>

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

App이라고 하는 컴포넌트에 관련된 HTML, JavaScript, CSS가 하나의 파일에 들어가있는것이

싱글파일 컴포넌트이다!

 

 

 

컴포넌트 명명 규칙 

파스칼 케이스로 작성

기존에 html이 태그 스펙상 대소문자를 구분하지 못했기 때문에 '-'을 사용했는데,

싱글파일 컴포넌트에서는 파스칼 케이스로 작성해도 된다.

 

 

 

 

싱글파일 컴포넌트 코드 작성 팁

확장 플러그인에서 미리 설치해둔 vue vscode snippets를 사용해서 코드 자동완성을 해보겠다.

 

vbc + tab

<template>
  <div>

  </div>
</template>

<script>
  export default {
    
  }
</script>

<style scoped>

</style>

위의 코드로 자동완성되어 생성

 

 

vda + tab

data() {
      return {
        key: value
      }
    },

 

v-on 은 축약어로 사용할 수 있다 >>  @

<template>
  <div>
    {{ message }}
  </div>
  <button @click="showAlert">경고</button>
</template>

<script>
export default {
  data() {
    return {
      message: "hi",
    };
  },
  methods:{
    showAlert(){
      alert('Hello')
    }
  }
};
</script>

 

 

 

 

컴포넌트를 생성해서 등록

우선 src > components > AppHeader.vue 파일 생성

파일명도 파스칼케이스로 작성

 

AppHeader.vue

<template>
  <h1>앱 헤더</h1>

</template>

<script>
  export default {
    
  }
</script>

<style scoped>

</style>

vbc + tab 자동완성해주고 template부분에 간략하게 코드작성해준다.

 

App.vue로 돌아와서

<script>에 방금 만든 AppHeader를 import를 해주는데

규칙은 

import 컴포넌트 이름 from './컴포넌트 경로'

import AppHeader from "./components/AppHeader.vue";

이렇게 작성해주고 AppHeader를 사용하기 위해 등록해준다.

export default {
  components: {
    //AppHeader: AppHeader,
    AppHeader,
  },

'컴포넌트 이름' : 컴포넌트 내용

으로 등록하면 되는데, 여기서도 파스칼케이스를 사용하여 명명해준다.

그리고 앞과 뒤, 키와 밸류값의 내용이 같으면 하나만 써도 사용이 가능하다

'AppHeader' : AppHeader   >>   AppHeader : AppHeader   >>   AppHeader 이런식으로

이제 화면단에 등록을 해준다.

<template>
  <AppHeader></AppHeader>
...

이렇게 하고 서버실행해보면

따로만든 컴포넌트가 등록되어 출력되는것을 확인할 수 있다!

 

 

AppHeader 컴포넌트에 props와 emit 연결하기

 

 

props

AppHeader의 props를 내리기위해서 AppHeader에 있는 타이틀을 제어해보자

App.vue에서 데이터의 메시지를 '앱 헤더 컴포넌트'로하고

 data() {
    return {
      message: "앱 헤더 컴포넌트",
    };
  },

 

이걸 AppHeader에 내린다고 하면

<template>
  <AppHeader v-bind:...></AppHeader>
</template>

v-bind를 사용해서 내려준다.이걸 받기위해서 이름이 정의가 되어있어야 하기때문에 AppHeader컴포넌트로 가서 

<template>
  <h1>{{ appTitle }}</h1>
</template>

<script>
export default {
  props: ["appTitle"],
};
</script>

<style scoped></style>

props를 "appTitle"로 지정하고 등록

App.vue에서 appTitle이란 이름으로 message를 내려주면 된다.

<template>
  <AppHeader v-bind:appTitle="message"></AppHeader>
</template>

 

 

 

event emit

AppHeader.vue에 버튼을 하나 추가한다. 버튼을 클릭하면 메시지가 변경되게 만들것

<template>
  <h1>{{ appTitle }}</h1>
  <button @:click="changeTitle">변경</button>
</template>

v-on(@)을 이용해서 버튼을 작동하게 하고

작동할 메서드를 하나 만들어준다.

<script>
export default {
  props: ["appTitle"],
  methods: {
    changeTitle() {
      this.$emit("change");
    },
  },
};
</script>

 

 

 

이제 App.vue로 올라가서

등록된 <AppHeader>에 v-on을 추가해주자.

<template>
  <AppHeader v-bind:appTitle="message" v-on:change="changeMassage"> </AppHeader>
</template>

그리고 change메서드가 작동할때 메시지를 변경할 수 있게끔 App.vue에도 메서드를 생성하는데

changeMessage라는 이름으로 

 methods: {
    changeMassage() {
      this.message = "변경됨";
    },
  },

이렇게 생성해줬다.

 

 

변경버튼을 클릭하면

이렇게 작동하는걸 볼 수 있다 !