[Vue.js] 입문하기 - 기본 문법

kim unknown·2022년 10월 10일
1

Vue.js

목록 보기
1/2
post-thumbnail

Vue

MVVM 패턴의 ViewModel 레이어에 해당하는 화면(View)단 라이브러리

✨Vue의 핵심 - Reactivity (반응성)
-> 데이터가 바뀌면 변화를 감지하고 알아서 화면에 반영함


1. 뷰 인스턴스(instance)

인스턴스는 뷰로 화면을 개발하기 위한 생성 단위이다.

Vue를 생성자라고 함 → 필요한 모든 기능을 생성자에 미리 정의해 놓고 사용자가 그 기능을 재정의하여 편리하게 사용하기 때문

인스턴스 생성 방법

 new Vue();

인스턴스 속성

new Vue({
  el: ,
  template: ,
  data: ,
  methods: ,
  created: ,
  watch: ,
});
  • el : 인스턴스가 그려지는 화면의 시작점 (특정 HTML 태그)
  • template : 화면에 표시할 요소 ( HTML, CSS 등)
  • data : 뷰의 반응성(Reactivity)이 반영된 데이터 속성
  • method : 화면의 동작과 이벤트 로직을 제어하는 메서드
  • created : 뷰의 라이프 사이틀과 관련된 속성
  • watch : data에서 정의한 속성이 변화했을 때 추가 동작을 수행할 수 있게 정의하는 속성
var vm = new Vue({
  // body 태그 안에서#app을 찾아 해당 인스턴스를 붙이겠다는 의미
  // el을 정의하지 않으면 속성들을 정의하더라도#app에서 사용할 수 없음
  // 즉, 무조건 el을 특정 태그에 붙여줘야만 사용 가능
  el : '#app'
});

2. 템플릿 문법

2-1. 데이터 바인딩

뷰 인스턴스에서 정의한 속성들을 화면에 표시하는 방법. 콧수염 괄호 {{ }}

<div>{{ message }}</div>

new Vue({
	data: {
		message: 'Hello World';
	}
})

2-2. 디렉티브

화면 요소를 조작하기 위한 문법.

  • v-text → 자바스크립트 innerText
<span v-text="msg"></span>
<!-- 같은 방법 -->
<span>{{msg}}</span>
  • v-html → 자바스크립트 innerHTML
<div v-html="html"></div>
  • v-if → 조건부 렌더링
  • v-else
  • v-else-if
<!-- v-if - loading이 참일 때 보임 -->
<div v-if="loading">Loading...</div>

<!-- v-else - loading이 거짓일 때 보임 -->
<div v-else>test user has been logged in</div>

new Vue({
	data: {
		loading: false
	}
})
  • v-show
    v-if와 비슷하게 조건에 따라 엘리먼트 표시
<div v-show="loading">Loading...</div>

new Vue({
	data: {
		loading: true
	}
})
  • v-if와 v-show의 차이
    v-show를 엘리먼트는 항상 렌더링 되어 DOM에 남아있다. 즉, v-show는 단순히 display 속성(display:none)을 변경하는 것이고, v-if는 조건에 따라 실제로 돔을 제거하고 생성한다.
  • v-for
    데이터 속성의 개수만큼 화면의 요소를 반복하여 출력
<ul>
  <li v-for="(item,i) in items">{{ item }}</li>
</ul>

new  Vue({
	data: {
		items: ['Home', 'About', 'Login']
	}
})
  • v-bind
    동적으로 엘리먼트 속성 설정
<div v-bind:속성="사용할 속성명(data)"></div>

🍀예시

<!-- id, class 바인딩 -->
<p v-bind:id="uuid" v-bind:class="name">{{number}}</p>

<script>
  new Vue({
    el: "#app",
    data: {
      uuid: "abc123",
      name: "text-blue",
    },
  });
</script>
  • v-on
    이벤트 처리
<button v-on:이벤트 이름="실행할 메소드"></button>

🍀예시

<!-- 클릭할 때마다 이벤트 실행 -->
<button v-on:click="logText">Click Me!</button>
<!-- 키보드를 누를 때마다 이벤트 실행 -->
<input type="text" v-on:keypress="logText" />
<!-- 엔터키를 누를 때마다 이벤트 실행 -->
<input type="text" v-on:keypress.enter="logText" />

<script>
  new Vue({
    el: "#app",
    methods: {
      // 이벤트 함수
      logText: function () {
        console.log("clicked");
      },
    },
  });
</script>

*v-on:이벤트이름.prevent - 이벤트 새로고침 막기 (event.preventDefault()와 동일)

  • v-model
    input 값 구하기
<input type="text" v-model="message" />
<p>{{message}}</p>

<script>
  new Vue({
    el: "#app",
    data: {
			// input 값이 바뀔 때마다 자동으로 message가 변경됨
      message: "",
    },
  });
</script>

2-3. this

인스턴스 안의 메서드에서 사용되는 this는 해당 인스턴스를 가리킨다.

→ 객체에 속한 메서드에서 사용될 때 this가 해당 메서드를 호출한 객체를 가리키는 것과 비슷한 관점에서 바라보면 됨

2-4. computed 속성

간단한 연산 수행 → data가 변경되면 연산 수행

computed 속성은 반응형(reactive) 종속성에 기반하여 캐시된다

<script>
new Vue({ 
  el: "#app",
  data: {
    number: 100,
  },
  // number의 값이 바뀌면 doubleNum도 같이 바뀜
  computed: {
    doubleNum: function () {
      return this.number * 2;
    },
  },
});
</script>

2-5. watch 속성

매번 실행되기 부담스러운 무거운 로직 (ex. 데이터 요청)

<script>
  new Vue({
    el: "#app",
    data: {
      num: 10,
    },
	// watch - 데이터의 변화에 따라 특정 로직을 실행
    watch: {
      num: function () {
        this.logText();
      },
    },
    methods: {
      addNum: function () {
        this.num++;
      },
      logText: function () {
        console.log(`${this.num} changed`);
      },
    },
  });
</script>

*왠만하면 watch보다는 computed를 사용하는걸 추천


3. 뷰 컴포넌트

컴포넌트는 화면의 영역을 구분하여 개발할 수 있는 뷰의 기능이다.
컴포넌트 기반으로 화면을 개발하게 되면 코드의 재사용성이 올라가고 빠르게 화면을 제작할 수 있다.

컴포넌트는 전역 컴포넌트와 지역 컴포넌트로 구분하여 생성할 수 있다.

  • 전역 컴포넌트는 인스턴스를 생성할 때마다 따로 등록할 필요 없이 모든 인스턴스에서 사용 가능
  • 지역 컴포넌트는 해당 인스턴스 내에서만 사용 가능, 인스턴스마다 새로 생성해야 함

전역 컴포넌트 생성 방법

Vue.component('컴포넌트 이름', {
  // 컴포넌트 내용
});

지역 컴포넌트 생성 방법

new Vue({
  el: "#app", // #app에서만 사용할 수 있는 지역 컴포넌트
  components: {
    // '컴포넌트 이름' : { 컴포넌트 내용 },
  }
});

🍀예시

// 표시
<div id="app">
  <app-header></app-header>
</div>

// 생성
Vue.component("app-header", {
  template: "<h1>Header</h1>",
});

4. 컴포넌트간의 통신 방식

상위에서 하위로는 데이터를 내려주고, 하위에서 상위로는 이벤트를 올려준다.

  • 하위 컴포넌트 → (이벤트 발생) → 상위 컴포넌트
  • 상위 컴포넌트 → (props 전달) → 하위 컴포넌트

4-1. props (상위→하위)

props에도 Reactivity가 반영된다.

props 사용 방식

// 하위 컴포넌트의 내용
var childComponent = {
  props: ['프롭스 속성 명']
}

<!-- 상위 컴포넌트의 템플릿 -->
<div id="app">
  <child-component v-bind:프롭스 속성 명="상위 컴포넌트의 data 속성"></child-component>
</div>

🍀예시

<div id="app">
	<app-header v-bind:propsData="message"></app-header>
</div>

<script>
  // 컴포넌트를 분리하여 작성하고 등록하는 방식으로 가독성을 높임
  var appHeader = {
    template: "<h1>{{ propsData }}</h1>",
    props: ["propsData"], // props 속성 이름 지정
  };

  new Vue({
    el: "#app",
    components: {
      "app-header": appHeader,
    }
    data: {
      message: "hi",
    },
  });
</script>

4-2. 이벤트 (하위→상위)

// 하위 컴포넌트의 내용
this.$emit('이벤트 명');

<!-- 상위 컴포넌트의 템플릿 -->
<div id="app">
  <child-component v-on:하위 컴포넌트에서 발생한 이벤트 명="상위 컴포넌트의 실행할 메서드 이름"></child-component>
</div>

🍀예시

<div id="app">
	<app-header v-on:pass="logText"></app-header>
</div>

<script>
  var appHeader = {
    template: "<button v-on:click='passEvent'>Click Me</button>",
    methods: {
      passEvent: function () {
        this.$emit("pass");  // 이벤트 명
      },
    },
  };

  new Vue({
    el: "#app",
    components: {
      "app-header": appHeader,
    },
    methods: {
			// 이벤트 발생시 실행할 메서
      logText: function () {
        console.log("hi");
      },
    },
  });
</script>

4-3. 같은 레벨의 컴포넌트 간의 통신 방식

이벤트로 Root로 전달하고 Root에서 props로 전달

var appContent = {
  template:
    "<div>content<button v-on:click='passNum'>pass</button></div>",
  methods: {
    passNum: function () {
      // 10을 같은 레벨인 appHeader에 전달하기 위해서
      // 먼저 Root로 올려 전달하고 Root에서 appHeader로 내려 전달하는 방식
      // 상위로 올릴 때는 event 내릴 때는 props
      this.$emit("pass", 10);
    },
  },
};

5. 뷰 라우터

뷰 라우터는 뷰 라이브러리를 이용하여 SPA를 구현할 때 사용하는 라이브러리이다.

설치 방법

  • CDN
<script src="https://unpkg.com/vue-router@3.5.3/dist/vue-router.js">
  • NPM
npm install vue-router

라우터 인스턴스 생성

// 라우터 인스턴스 생성
var router = new VueRouter({
  // 라우터 옵션
})

// 인스턴스에 라우터 등록
new Vue({
  router: router
})

라우터 옵션

  • routes : 페이지의 라우팅 정보 (라우팅할 url과 컴포넌트)
    • path : 페이지의 url
    • component : 해당 url에서 표시될 컴포넌트
  • mode : URL의 해쉬 값(#) 제거 속성

router-view

url에 따라 해당하는 컴포넌트를 보여주는 태그로 뷰 인스턴스에 라우터를 연결해야 사용 가능하다.

<router-view></router-view>

특정 url로 이동시켜주는 태그로 html a태그와 같은 역할을 한다.

<router-link to="이동할 url"></router-link>

<div id="app">
  <div>
    <!-- 특정 페이지로 이동시켜줌 -->
    <router-link to="/login">Login</router-link>
    <router-link to="/home">Home</router-link>
  </div>
    <!-- url에 따라 해당 하는 컴포넌트를 보여줌 -->
  <router-view></router-view>
</div>

<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
<!-- CDN vue-router -->
<script src="https://unpkg.com/vue-router@3.5.3/dist/vue-router.js"></script>

<script>
var LoginComponent = {
  template: "<div>login</div>",
};
var HomeComponent = {
  template: "<div>home</div>",
};

new VueRouter({
  mode: 'history',  // url 해시값 제거
  routes: [
		// '/login'에서 LoginComponent 컴포넌트 표시
    { path: '/login', component: LoginComponent },
		// '/home'에서 HomeComponent 컴포넌트 표시
    { path: '/home', component: HomeComponent }
  ]
})

new Vue({
    // 인스턴스에 라우터 연결
    router: router,
  });
</script>

6. Vue CLI

CLI (Command Line Interface) : 명령어를 통해 특정 액션을 실행하는 도구.

프로젝트 생성

vue create '프로젝트 폴더 위치'

프로젝트 실행

npm run serve

7. 싱글 파일 컴포넌트

파일 구조

<template>
<!-- HTML -->
</template>

<script>
// Javascript - 인스턴스 속성들
</script>

<style>
/* css */
</style>

*템플릿 루트는 무조건 하나여야 한다. -> 전체 태그를 하나의 태그가 감싸고 있어야 함

*파스칼 케이스로 네이밍 + 최소 두단어 이상으로 조합


참고 자료
📝 Vue.js 시작하기 - Age of Vue.js 강의
📝 Cracking Vue.js

profile
과거의 나에게 묻기 위한 기록

0개의 댓글