템플릿 문법 ({{ }}
)은 편하지만 코드가 길어지면 가독성이 떨어지고 유지보수가 어려움 , 따라서 이럴 때 사용하는 것이 계산된 속성 computed property
메서드와 동일 한 결과를 얻을 수 있지만 computed
는 결과가 캐쉬되기 때문에 computed
내 반응형 데이터가 변경된 경우에만 다시 계산된다.
computed
는 기본적으로 getter전용, 즉 readonly기 때문에 새 값을 할당하기 위해서는 getter
와 setter
를 이용
<template>
<div>
<h2>{{teacher.name}}</h2>
<h3>강의가 있습니까?</h3>
<!-- 수정에 복잡하다. -->
<!-- <p>{{ teacher.lectures.length > 0 ? "있음":"없음"}}</p> -->
<!-- 결과는 같지만 computed가 비용이 적게듬 -->
<!-- computed는 변경되지 않은 경우 캐쉬되었기 때문에 계속 로드되지 않음 -->
<h3>{{hasLecture}}</h3>
<h3>{{hasLecture}}</h3>
<h3>{{hasLecture}}</h3>
<!-- 메서드는 계속 로드 -->
<h3>{{existLecture()}}</h3>
<h3>{{existLecture()}}</h3>
<h3>{{existLecture()}}</h3>
<button v-on:click="counter++">Counter : {{counter}}</button>
<h2>이름</h2>
<p>{{fullName}}</p>
</div>
</template>
<script>
import { computed , ref} from '@vue/reactivity'
import { reactive } from 'vue'
export default {
setup () {
const teacher = reactive({
name : "짐코딩",
lectures : [
'html/css',
'javascript',
'vue3'
]
})
//computed는 한번 호출하면 캐쉬로 저장해둠
// 다시 계산되는 경우는 반응형 데이터가 변화될때
const hasLecture = computed(()=>{
console.log('computed');
return teacher.lectures.length > 0 ? "있음":"없음"
})
// 메서드로 computed 같은 출력 만들기
const existLecture = ()=>{
console.log('method');
return teacher.lectures.length > 0 ? "있음":"없음";
};
const counter = ref(0);
const firstName = ref('홍');
const lastName = ref('길동');
// const fullName = computed(()=>{
// return firstName.value + ' '+lastName.value;
// })
// console.log('console.log : ',fullName.value);
// fullName.value = '짐 코딩';
//getter와 setter로 새로운 값 할당
const fullName = computed({
get(){
return firstName.value + ' '+lastName.value;
},
set(value){
console.log('value ',value);
[firstName.value , lastName.value] = value.split(' ');
}
})
fullName.value = '짐 코딩';
return {
teacher,
hasLecture,
existLecture,
counter,
fullName
}
}
}
</script>
<style lang="scss" scoped>
</style>
객체 바인딩
:class
를 사용해서 바인딩class
속성과 공존 가능computed
에 바인딩 가능배열에 바인딩
:class
에 바인딩<template>
<div>
<!-- class 와 v-bind가 공존 -->
<!-- :class는 여러개 가능 -->
<div class="text" :class="{active: isActive , 'text-danger': hasError}">텍스트입니다.</div>
<div class="text" :class="classObject">텍스트입니다.</div>
<div class="text" :class="[activeClass,errorClass,classObject]">배열.</div>
<button v-on:click="toggle">toggle</button>
<button v-on:click="hasError = !hasError">toggle Error</button>
</div>
</template>
<script>
import { computed } from '@vue/reactivity';
import { reactive, ref } from 'vue'
export default {
setup () {
const isActive = ref(true);
const toggle = ()=>{
isActive.value = !isActive.value;
}
const hasError = ref(false);
// const classObject = reactive({
// active:true,
// 'text-danger':false
// })
const classObject = computed(()=>{
return {
active:true,
'text-danger':false,
'text-blue':true,
}
})
const activeClass = ref('active');
const errorClass = ref('error');
return {
isActive,
toggle,
hasError,
classObject,
activeClass,
errorClass}
}
}
</script>
<style scoped>
.active{
font-weight: bold
}
.text-danger{
color: red;
}
</style>
:style
로 바인딩
배열에 :style
바인딩 가능
<template>
<div>
<div :style="styleObject">
Lorem ipsum dolor sit amet consectetur adipisicing elit. Consequuntur iure error enim incidunt dolor nihil ipsam, similique modi amet, earum eum facere voluptatem. Animi enim nulla asperiores, in fugit voluptate!
</div>
<button v-on:click="fontSize--">-</button>
<button v-on:click="fontSize++">+</button>
</div>
</template>
<script>
import { computed } from '@vue/reactivity'
import { reactive ,ref} from 'vue'
export default {
setup () {
// const styleObject = reactive({
// color:'red',
// // 카멜케이스로
// fontSize: '13px'
// })
const styleObject = computed(()=>{
return {
color:'red',
// 카멜케이스로
fontSize: fontSize.value+ 'px',
}
})
const fontSize = ref(13);
return {
styleObject,
fontSize,
}
}
}
</script>
<style lang="scss" scoped>
</style>