vue를 사용함에 있어서 가장 짜증나는 부분은 바로 반응이 언제되는가이다.
왜냐하면 이를 모르면 여러분은 값을 변화를 주더라도 실제로는 반영되지 않는 경우가 많다.
가령 아래와 같은 코드를 보자.
코드가 기니까 조금 잘라서보자.
// session.js
export default {}
session은 그냥 빈객체다.
created() {
console.log(this)
this.instance = 0
},
data() {
return {
value: 0,
session
}
},
여러분은 현재 이 vue컴포넌트는 this로 호출할 수 있다는 것을 알 수 있다.
그럼 위 같은 코드가 존재할경우 this변수는 총 3가지가 있다.
instance, value, session이렇게 세종류가 있는데 이 셋은 작동하는 원리가 서로 다르다.
그 이유에 대해서 설명하기 전에 각각의 처한 상황을 보도록 하자.
value - data로 선언한 기본 변수
session - data로 선언한 object
instance - data로 선언하지 않은 기본 변수
이 셋의 구동원리는 다르다.
그럼먼저 예제를 한번 작동시켜보자.
여러분이 이 예제를 실행시켜본다면 value를 눌렀을때는 화면에 반영이 된다. 하지만 instance를 눌렀을 때는 반영이 되지 않는다.
또한 session역시 값을 추가할 경우 값이 변동되지 않는다.
하지만 갑자기 value를 누르면 값이 변동된다.
이 이유는 뭘까??
vue에서 data에 변수선언하는건 단순히 data 탭에 변수를 선언하는데서 끝나는게 아니다.
이 data에서 변수선언은 "난 data의 변동을 추적하겠다."라고 선언하는 것과 같다.
더 자세한 설명은 딱히 하지 않을 생각이지만 어떤 현상이 일어나는지는 볼 필요가 있다.
데이터를 출력해보면 실제로 session과 instance, value모두 값이 만들어졌다는걸 알 수 있다.
다만 session과 value는 data에도 변수가 들어있다.
그리고 아래 보면 value와 session은 getter와 setter가 생성된걸 확인할 수 있다.
data에 선언하면 Object.defineProperty를 사용해서 getter와 setter를 만들게 되고
이 getter와 setter에 추적 코드를 끼워넣는다.
그러면 이를 watcher라는 녀석이 계속해서 감시하며 변동사항이 있으면 이를 반영하게 된다.
정말 다행이게도 이 watcher라는 녀석이 감지하지 못하는 변수도 화면에 재렌더링은 하게 된다.
왜냐하면 여러분이 vue구문을 사용해서 (예를 들마면 v-bind나 {{}})선언한 변수들은
변수가 바뀌면 다시 바뀐값을 집어 넣는다.
문제는 data에 선언한 변수가 아니라면 이 바뀐타이밍 자체를 모르기 때문에
나중에 바뀐녀석이 바뀔때 일괄적용이 되게 된다. 그래서 여러분이 변동을 추적하기 위해서는 반드시 data로 선언한다.
이제 여러분인 instance가 왜 변동이 안되고 value가 변동될때 일괄 변동되는지 알 수 있다.
근데 문제는 object녀석이다.
session은 data로 선언했음에도 불구하고 왜 바뀌지 않는걸까?
이 역시 간단한데 session자체는 바뀌기 않았기 떄문이다.
session은 안바뀌고 session내부가 바뀐것이다.
이 바뀐것은 추적할 수 없다.
이는 object뿐만아니라 array역시 마찬가지이다.
그러면 해결법은 두개로 요약된다.
1.object나 array를 변동시킨다.
2.아니면 다른 제공된 방식을 사용한다.
<template>
<div id="app">
{{session}}<br>
<input type="button" value="session add" @click="onclicks"><br>
</div>
</template>
<script>
import session from './js/session.js'
let i = 0;
let j = 10;
export default {
name: 'app',
components: {},
created() {
},
data() {
return {
session
}
},
methods: {
onclicks() {
this.session[i++ + 'hi'] = j++ + 'hi'
this.session = Object.assign({}, this.session)
},
}
}
</script>
<style>
</style>
1번방식으로 다른 Object를 붙히는 방식이다.
그러기위해서 Object.assign을 사용한다. 이 방식은 객체의 크기가 작을 때는 별 문제가 없다.
하지만 크다면 값의 복사가 빈번하게 일어나기 때문에 권장하는 방식은 아니다,
<template>
<div id="app">
{{session}}<br>
<input type="button" value="session add" @click="onclicks"><br>
</div>
</template>
<script>
import session from './js/session.js'
let i = 0;
let j = 10;
export default {
name: 'app',
components: {},
created() {
},
data() {
return {
session
}
},
methods: {
onclicks() {
this.$set(this.session,i++ + 'hi',j++ + 'hi')
},
}
}
</script>
<style>
</style>
this.$set(<object>,<key>,<value>)
또다른 방식은 this.$set을 사용하는것이다. 이는 vue에서 재공하는 방식인데 이 녀석을 호출하면 object나 array의 변동사항을 감지할 수 있다.
array의 경우 splice를 사용할 경우 추적할 수 있다. 거기에 대한 설명은 이 포스팅을 참조하는 것이 좋다.
'Usage > JavaScript-Vue' 카테고리의 다른 글
[JavaScript][Vue]Istanbul을 vue-cli(3.0)에 적용해서 커버리지테스트하기 (0) | 2019.07.25 |
---|---|
[JavaScript][Vue]vue3.0 cli에서 페이지 단위로 쪼개서 빌드하기 (1) | 2019.03.19 |
[JavaScript][Vue]vue에서 부모가 자식에게 값넘길때 이는 값의 복제일까? 참조일까? (0) | 2019.02.18 |
[JavaScript][Vue]vue 컴포넌트에 상위 컴포넌트에서 css를 적용하면? (0) | 2019.01.29 |