컴포넌트의 필요성
- 같은 코드의 중복을 없애고 간편하고 효율적으로 개발하기 위해 컴포넌트가 필요하다.
- 컴포넌트의 활용은 여러 번 사용하는 것을 전제로 한다.
- 지난 포스팅에서 살펴본 것과 다르게 여러 개의 끝말잇기를 한 페이지에 여러 개 진행하려면?
Ex) 컴포넌트를 적용하지 않은 끝말잇기 게임
- 복사해서 여러 개의 submit 메서드를 만든다.
<hide/>
<!DOCTYPE html>
<html lang="en">
<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">
<title>Document</title>
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
</head>
<body>
<div id="root">
<div>{{word}}</div>
<form v-on:submit="onSubmitForm">
<input type="text" ref="answer" v-model="value">
<button type="submit">입력!</button>
</form>
<div>{{result}}</div>
<div>{{word1}}</div>
<form v-on:submit="onSubmitForm1">
<input type="text" ref="answer1" v-model="value1">
<button type="submit">입력!</button>
</form>
<div>{{result1}}</div>
<div>{{word2}}</div>
<form v-on:submit="onSubmitForm2">
<input type="text" ref="answer2" v-model="value2">
<button type="submit">입력!</button>
</form>
<div>{{result2}}</div>
</div>
<script>
const app = new Vue({
el: '#root',
data: {
word: '제로초',
word1: 'Vue',
word2: '좋은 아침',
result: '',
result1: '',
result2: '',
value: '',
value1: '',
value2: ''
},
methods: {
onSubmitForm(e) {
e.preventDefault();
if (this.word[this.word.length - 1] === this.value[0]) {
this.result = "딩동댕";
this.word = this.value;
this.value = '';
this.$refs.answer.focus();
} else {
this.result = "땡";
this.value = '';
this.$refs.answer.focus();
}
},
onSubmitForm1(e) {
e.preventDefault();
if (this.word1[this.word1.length - 1] === this.value1[0]) {
this.result1 = "딩동댕";
this.word1 = this.value1;
this.value1 = '';
this.$refs.answer1.focus();
} else {
this.result1 = "땡";
this.value1 = '';
this.$refs.answer1.focus();
}
},
onSubmitForm2(e) {
e.preventDefault();
if (this.word2[this.word2.length - 1] === this.value2[0]) {
this.result2 = "딩동댕";
this.word2 = this.value2;
this.value2 = '';
this.$refs.answer2.focus();
} else {
this.result2 = "땡";
this.value2 = '';
this.$refs.answer2.focus();
}
}
}
})
</script>
</body>
</html>
Note) 실행 결과
- 아래와 같이 세 개의 끝말잇기를 만들었으나
- 중복되는 부분이 너무 많다.
- 이런 비효율성을 해결할 수 있는 것이 "컴포넌트"이다.
- 최소 단위를 재사용한다.
컴포넌트 적용하기
- component() 안에는 파스칼, 케밥 표기법을 쓴다.
- 카멜 표기법(camelCase), 파스칼 표기법(PascalCase), 케밥 표기법(kebab-case)
- 카멜이랑 파스칼이랑 맨 앞문자가 대문자인지 소문자인지 여부만 다르다.
- data{} 안에는 수정사항이 있다.
- 기존 data{} 안에 객체 형식이었지만 컴포넌트 적용하는 경우는 함수로 만들어야한다.
- data 객체를 돌려주는 함수로 만든다.
- template: ``
- cf) 백틱(`)을 쓰면 줄바꿈할 때 편리함
- 아까 그 반복되는 코드를 템플릿 안에 넣어준다.
- 템플릿은 제약 조건 상 항상 하나로 감싸줘야한다.
- 템플릿 안에 형제 태그 3개가 있는데 이를 모두 하나로 감싸서 템플릿에 넣어줘야한다.
- root에 해당하는 Vue () 안에 있는 데이터를 모두 컴포넌트로 옮겨준다.
- data, methods 영역의 내용을 컴포넌트로 이동한다.
- 기존 Vue () 인스턴스 안에 내용을 모두 지운다.
Ex) 컴포넌트 적용
<hide/>
<!DOCTYPE html>
<html lang="en">
<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">
<title>Document</title>
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
</head>
<body>
<div id="root">
<word-relay></word-relay>
<word-relay></word-relay>
<word-relay></word-relay>
</div>
<script>
Vue.component('word-relay', {
template: `
<div>
<div>{{word}}</div>
<form v-on:submit="onSubmitForm">
<input type="text" ref="answer" v-model="value">
<button type="submit">입력!</button>
</form>
<div>{{result}}</div>
</div>
`,
data() {
return {
word: '제로초',
result: '',
value: ''
};
},
methods: {
onSubmitForm(e) {
e.preventDefault();
if (this.word[this.word.length - 1] === this.value[0]) {
this.result = "딩동댕";
this.word = this.value;
this.value = '';
this.$refs.answer.focus();
} else {
this.result = "땡";
this.value = '';
this.$refs.answer.focus();
}
}
}
})
</script>
<script>
const app = new Vue({
el: '#root'
})
</script>
</body>
</html>
Note) 실행 결과
- 오류
- vue.js:5108 [Vue warn]: The "data" option should be a function that returns a per-instance value in component definitions.
- 원인
- data를 객체형이 아닌 함수형으로 만들어줘야한다.
- 해결
- 위 코드를 아래와 같이 함수형으로 바꾼다.
<hide/>
data: {
word: '',
result: '',
value: ''
},
data() {
return{
word: '',
result: '',
value: ''
}
}
컴포넌트의 특성
- 컴포넌트는 렌더링(화면에 표시)하지만 중복을 제거한다.
- 데이터들은 따로 논다. 같은 컴포넌트라도 각각의 데이터를 가진다.
- 컴포넌트를 만드는 스크립트는 상단에 와야한다.
- 전역 컴포넌트(global component)라고도 한다.
props와 웹팩의 필요성
- 공통적으로 반복되는 부분이 있지만 조금씩 다른 부분이 있다면?
- 예를 들어 아래 사진에서 동그라미 안에 숫자만 다르다.
Ex) props 적용, 전역 컴포넌트
- 기존의 코드에서 각 끝말잇기의 첫 단어를 다르게 고정시키려면?
- 컴포넌트를 쓰는 쪽에서 startWord 값을 넣어주고
- 컴포넌트를 정의하는 부분에는 props를 받아준다. (startWord를 받겠다고 넣어주기. )
- 다음과 같이 "start-word"를 케밥 표기법으로 넣어줘야한다.
- Vue의 html 에서는 케밥 표기법으로 넣고 JavsScript 에서는 카멜 표기법으로 받아준다.
- html: <word-relay start-word="고양이"></word-relay>
- JavsScript: component 안 부분에 word: this.startWord 라고 넣는다.
- 이렇게 각각 넣어주면 Vue가 알아서 처리해준다.
<hide>
<!DOCTYPE html>
<html lang="en">
<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">
<title>끝말잇기</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id="root">
<word-relay start-word="고양이"></word-relay>
<word-relay start-word="아메리카노"></word-relay>
<word-relay start-word="침팬치"></word-relay>
</div>
<script>
Vue.component('word-relay', {
template: `
<div>
<div>{{word}}</div>
<form v-on:submit="onSubmitForm">
<input type="text" ref="answer" v-model="value">
<button type="submit">입력!</button>
</form>
<div>{{result}}</div>
</div>
`,
props: ['startWord'],
data() {
return {
word: this.startWord,
result: '',
value: ''
};
},
methods: {
onSubmitForm(e) {
e.preventDefault();
if (this.word[this.word.length - 1] === this.value[0]) {
this.result = "딩동댕";
this.word = this.value;
this.value = '';
this.$refs.answer.focus();
} else {
this.result = "땡";
this.value = '';
this.$refs.answer.focus();
}
}
}
})
</script>
<script>
const app = new Vue({
el: '#root'
})
</script>
</body>
</html>
Note) 실행 결과
- 전역 컴포넌트를 이용하면 공통적인 모양이 있지만 데이터를 따로 가지고 있다.
웹팩을 배우는 이유
- <script>를 많이 쓰게 되는 경우, 복잡함을 줄이기 위해 웹팩을 쓴다.
- 웹팩을 쓰면 여러 스크립트를 합칠 수 있다.
- 웹 사이트를 크게 만들려면 스크립트가 늘어나고 스크립트 관리에 대한 어려움이 생겨서 웹팩을 배우는 게 좋다.
Note
- content
찾아보기
- content
'FrontEnd > Vue를 이용한 웹 게임 만들기' 카테고리의 다른 글
Chapter 04. 반응 속도 체크 게임 (4) | 2023.04.13 |
---|---|
Chapter 03. 웹팩 적용하기와 숫자 야구 (0) | 2023.03.31 |
Chapter 01. Vue 환경 설정, 끝말잇기 게임 (0) | 2023.03.29 |