컴포넌트에 computed 속성과 watch 속성을 가질 수 있다
computed
- data를 변형해서 새롭게 반환하는 데이터
- 메서드들을 프로퍼티로 갖는 객체 속성형태
- 메서드들은 값을 리턴해야 한다 ⇒ 일종의 getter와 동일
- 표현식에서 데이터처럼 사용할 수 있다
- 캐싱으로 인해, 값이 바뀌지 않았으면 연산을 또 하지 않고 이전 것을 가져온다
- 메서드 내에서 쓰이는 data가 변경이 있을 때만 해당 computed 메서드가 호출된다
<div id="app"> <h1>{{ count }}</h1> <h2>{{ mul }}</h2> //count가 변경되면 같이 변경됨 <h3 v-for="fruit in toUpper"> //fruits가 대문자인 형태로 {{ fruit }} </h3> </div> <script> const app = { data() { return { count: 0, fruits: ['banana', 'apple'] } }, computed: { mul() { //count가 변경 있을 때만 호출 return this.count*2 }, toUpper() { //fruits가 변경될 때만 호출 return this.fruits.map(fruit => fruit.toUpperCase()) } } } const vm = Vue.createApp(app).mount('#app') </script>
- 메서드가 아닌 객체를 프로퍼티로 가질 수도 있다
- 해당 객체에는 get, set 메서드를 프로퍼티로 가진다
get()
⇒ 기존의 computed의 메서드 프로퍼티와 같은 역할. 값을 return해주면 됨set(newVal)
⇒ computed 속성에 바로 값을 할당할 수 있게 한다.- computed 속성에 값을 할당하면 호출된다
- 할당한 값이 매개변수로 들어온다.
- proxy이므로.. get, set은 특정 시점에 호출만 될 뿐이지 안에 코드는 직접 구현해야한다.
<div id="app"> <h1>{{fullName}}</h1> <h3>{{lastName}}</h3> <h3>{{firstName}}</h3> </div> <script> const app = { data() { return { lastName: "An", firstName: "jjong" } }, computed: { fullName: { get() { // == fullName() { return } return `${this.lastName} ${this.firstName}` }, set(newVal) { //vm.fullName = '' 처럼 할당될 때 호출됨 const names = newVal.split(' ') this.lastName = names[0] this.firstName = names[names.length-1] } } } } const vm = Vue.createApp(app).mount('#app') </script>
watch
반응형 데이터(data, computed)가 바뀌면 실행되는 메서드들을 프로퍼티 속성으로 가지는 컴포넌트의 속성
- 반응형 데이터와 같은 이름으로 메서드를 만들면 된다
- 매개변수를 받지 않을 수도 있고, (newVal, oldVal)처럼 받을 수 있다.
- 이름은 상관 없고 위치만 중요.
- newVal → 새로운 값, oldVal → 기존의 값
- data() 데이터를 watch : 어떤 식으로든(method, v-model, v-on 등) 데이터가 변경되면 해당 watch 메소드가 실행된다
- computed 데이터를 watch : setter로 watch하는 데이터를 바꾸면 해당 watch 메서드가 동작한다
<script> const app = { data() { return { lastName: "An", firstName: "jjong" //watch됨 } }, computed: { fullName: { .. set(newVal) { .. this.firstName = names[names.length-1] //computed를 바꾸면 firstName도 바뀐다 => watch 동작 } } }, watch : { firstName() { //fistName 데이터가 바뀌면 해당 로직 수행 console.log("firstName is changed") } } } .. </script>
- watch 멤버 메서드는 사실 멤버 속성의 handler 메서드의 축약형이다
- 또한, handler외에 deep, immediate를 멤버 속성으로 가질 수 있다
deep
: 객체 데이터의 속성이나 배열 데이터의 요소만 변경되어도 handler가 동작하도록 하는 여부(default는 false)immediate
: 데이터가 변경되지 않아도, 데이터가 초기화 될 때 최초 실행 된다
<div id="app"> <ul v-for="fruit in fruits"><li>{{fruit.name}}</li></ul> </div> <script> const app = { data() { return { fruits: [ //배열 data {id: 1, name: 'apple'}, {id: 2, name: 'banana'}, {id: 3, name: 'cherry'}, ] } }, watch : { fruits: { //메서드에서 객체로 변경 handler(newVal, oldVal) { //기존 메서드 형태와 동일 console.log("fruits has changed") }, deep: true, //ex) vm.fruits[0] = 'a' 로 바꿔도 handler 실행 됨 immediate: true // 무조건 처음에 handler가 실행됨 } } } const vm = Vue.createApp(app).mount('#app') </script>