computed 계산 속성
computed 속성은 데이터를 실시간으로 계산하려 할 때 사용한다. 데이터를 실시간으로 계산한다는 것은 어떤 의미인지 왜 필요한지 예제를 통해 살펴본다.
Copy <!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>Vue computed 속성의 필요성</title>
</head>
<body>
<div id="app">
<div>
<label>
Nickname
<input type="text" v-model="nickname" v-on:input="nickname = $event.target.value">
</label>
</div>
<h5>닉네임 글자 수 : {{nickname.length}}</h5>
<h5>사용 가능 여부 : {{nickname.length >= 2 && nickname.length <= 6}}</h5>
</div>
<script src="https://unpkg.com/vue@next"></script>
<script>
const app = Vue.createApp({
data(){
return {
nickname:""
};
}
});
app.mount("#app");
</script>
</body>
</html>
예제는 2글자 이상 6글자 이하의 닉네임을 입력하면 true, 아니면 false를 출력하도록 구성되어 있다. 결론적으로 실행은 되지만 대부분의 에디터에서 구문 오류 표시가 발생한다. HTML에서 사용하기 부적합한 문자인 <
, >
때문이다. 그 외의 문제점까지 정리하면 다음과 같다.
computed 속성을 사용하면 다음과 같이 코드가 변경된다.
Copy <!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>Vue computed 속성의 필요성</title>
</head>
<body>
<div id="app">
<div>
<label>
Nickname
<input type="text" v-model="nickname" v-on:input="nickname = $event.target.value">
</label>
</div>
<h5>닉네임 글자 수 : {{nicknameLength}}</h5>
<h5>사용 가능 여부 : {{nicknameAvailable}}</h5>
</div>
<script src="https://unpkg.com/vue@next"></script>
<script>
const app = Vue.createApp({
data(){
return {
nickname:""
};
},
computed:{
nicknameLength(){
return this.nickname.length;
},
nicknameAvailable(){
return this.nickname.length >= 2 && this.nickname.length <= 6;
}
}
});
app.mount("#app");
</script>
</body>
</html>
실행 결과는 동일하지만 기존 예제의 문제점이 해결되었다.
사용법
computed 속성은 다음과 같이 작성한다.
Copy const app = Vue .createApp ({
//data(){ return {}; },
computed : {
이름(){
return 값;
} ,
}
});
computed 영역 내부에 값을 반환하는 함수를 만들어야 하며, 함수의 이름이 변수처럼 사용된다. 함수 내에서는 this 키워드를 이용하여 Vue instance 내부 요소들을 사용할 수 있다.
데모 - 아이디 형식 검사
Copy <!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>Vue computed demo</title>
</head>
<body>
<div id="app">
<div>
<label>
ID
<input type="text" v-model="id">
</label>
</div>
<h6 v-text="result"></h6>
</div>
<script src="https://unpkg.com/vue@next"></script>
<script>
const app = Vue.createApp({
data(){
return {
id:""
};
},
computed:{
result(){
const regex = /^[a-z][a-z0-9_]{7,19}$/;
if(regex.test(this.id)){
return "사용 가능한 아이디 형식입니다";
}
else {
return "아이디는 영문 소문자로 시작하는 8~20자 이내의 영문 소문자, 숫자, _로 작성해주세요";
}
},
}
});
app.mount("#app");
</script>
</body>
</html>
데모 - 이메일 작성
이메일은 @
를 기준으로 접두사(emailPrefix)와 접미사(emailSuffix)로 나눠지도록 구성하였다. 이 경우 실제 데이터는 emailPrefix
와 emailSuffix
이며, 전체 이메일은 computed 속성으로 만들어서 설정 및 확인할 수 있도록 구성한다. computed는 기본적으로 get만 가능하기 때문에 이 경우 computed를 get, set이 가능한 객체 형태로 정의할 수 있다.
Copy <!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>Vue computed getter/setter</title>
</head>
<body>
<div id="app">
<div>
Email :
<input type="text" v-model="email">
</div>
<h5>설정된 이메일 : {{email}}</h5>
</div>
<script src="https://unpkg.com/vue@next"></script>
<script>
const app = Vue.createApp({
data(){
return {
emailPrefix:"",
emailSuffix:""
};
},
computed:{
email:{
get(){
if(this.emailPrefix && this.emailSuffix){
return this.emailPrefix + "@" + this.emailSuffix;
}
else{
return "";
}
},
set(email){
const idx = email.indexOf("@");
if(idx < 0) {
return;
}
this.emailPrefix = email.substring(0, idx);
this.emailSuffix = email.substring(idx + 1);
}
},
}
});
app.mount("#app");
</script>
</body>
</html>
주의사항
computed 사용 시 주의사항은 다음과 같다.
Vue instance 내부의 다른 항목에 접근할 경우 반드시 this
키워드를 사용해야한다.
가급적 Vue data에 대한 계산을 수행하도록 구성한다.