data
props에서 가장 중요한 것은 data
에서 정의한 내용을 Vue가 지속적으로 추적한다는 것이다.
이전에 설명했듯 Vue는 이 data
객체의 모든 프로퍼티를 전역 프로퍼티와 합쳐서 내부에서 관리하는 하나의 객체로 만든다.
이때 methods
도 해당 객체에 합쳐진다. 바로 이런 작업이 Vue의 내부에서 이루어진다.
data
에 대해 Vue가 하는 작업 중 가장 핵심적인 일은 프로퍼티를 JavaScript의 기능인 프록시로 래핑해서 data 객체를 반응형 data 객체로 바꾸는 일이다.
data
프로퍼티를 래핑한다.data
내부 값이 바뀔 때마다 알리는 작업을 한다.// traps
const handler = {
set(target, key, value){
console.log(target)
console.log(key)
console.log(value)
}
}
const proxy = new Proxy(래핑할객체, traps(래핑할객체에 대한 핸들러를 담고있는 객체))
let message = "hello"
let longMessages = message + "world"
console.log(longMessages) // hello world
message = "hola~"
console.log(monMessages) // hello world
보면 중간에 message에 대한 값을 바꿔도 인식되지 않는다. 왜냐하면 JS는 기본적으로 reactive하지 않기 때문이다.
그러다면 이제 proxy를 이용해보자.
const data = {
message : "hello"
}
const handler = {
set(target, key, value){
console.log(target)
console.log(key)
console.log(value)
}
}
const proxy = new Proxy (data, handler)
proxy.message = "Hola~"
// {message : hello}
// {message}
// {Hola~}
위 코드가 가능한 이유는 data 객체를 첫 번째 인수로서 래핑하였다. 따라서 proxy를 통해서 message에 액세스할 수 있는 것이다.
또한 set함수에서 setter 함수를 정의하는데 이 함수는 proxy에 새로운 프로퍼티가 설정될 때마다 트리거된다는 것을 알 수 있다. 그리고 이를 통해 새 값이 설정된 프로퍼티가 무엇이며 설정된 새 값은 무엇이고 래핑된 원본 객체가 무엇인지 알 수 있다.
const data = {
message : "hello"
longMessages : "hello World"
}
const handler = {
set(target, key, value){
if(key === "message"){
target.longMEssages = value + "World"
}
target.message = value
}
}
const proxy = new Proxy (data, handler)
proxy.message = "Hola~"
console.log(proxy.longMessages) // Hola~ World
템플렛은 vue가 제어하는 html 코드부분을 뜻한다.
또 앱 구성 객체로서 template 속성을 사용할 수 있다.
<section id="app"><section/>
const app = Vue.creatApp({
template:`
<p>my favorite meal is {{favortieMeal}}</p>
`
data(){
return {
favoriteMeal : "Pizza"
}
}
});
app.mount("#app")
react에 있는 개념과 굉장히 유사하다. react에선 ref를 굉장히 다양한 용도로 쓴다. input값을 가져올 때도 사용하고
style을 바꾸거나 지정할 때도 사용한다.
그리고 vue도 마찬가지로 input값을 key가 눌릴때마다 가져올 필요가 없는 경우에 사용한다.
또 html 코드가 아니라서 브라우저는 이해를 못 하지만 vue는 이해할 수 있다.
또 p, header, section 등 어느곳에서 ref
속성값을 넣을 수 있다.
Vue는 ref를 감지하고 내부에 이를 저장한다.
<input type="text" ref="userText">
<button @click="setText">Set Text</button>
...
methods:{
setText() {
// this.message = this.currentUserInput;
this.message = this.$refs.userText.value
console.dir(this.$refs.userText);
},
...
내장 프로퍼티임을 표시하기 위해서 Vue가 지원하는 모든 프로퍼티는 $로 시작한다.
또 $ref
는 2가지의 속성을 갖는데, 이는 키-쌍 값으로 이루어진 객체로 이때 키는 템플릿에 설정한 ref 식별자가 된다.
이렇게 하면 해당 input 요소의 DOM 객체를 가리키는 것이 되고 DOM 요소에 액세스할 때 순수 JavaScript에서도 사용할 수 있는 JavaScript 객체가 된다.
즉, 이렇게 전체 input 요소에 대한 액세스를 얻을 수 있다는 것이다.
그래서 console.log가 아닌 console.dir을 찍어보면 해당 Input 요소에 있는 모든 프로퍼티를 JavaScript 객체로 표현한 것을 볼 수 있는데 그중 value 속성값이 있는 것을 확인할 수 있다.
우선 vue는 vue app(vue instance)와 dom이 있다. 이때 html content는 브라우저에 의해 렌더링 된다.
브라우저 DOM은 Vue가 제어하는 템플릿을 DOM에 렌더링 한다. 해당 템플릿의 콘텐츠가 DOM에 렌더링되는 것이다.
Vue가 제어하는 렌더링 프로세스 중에 동적 부분과 interpolation, 그리고 바인딩이 제거되며 실제 값이 삽입된다.
그리고 Vue에 대한 지시 사항은 템플릿이 DOM에 렌더링되고 나면 Vue에 의해 삭제되기 때문에 브라우저에서 렌더링되는 실제 DOM에서는 확인할 수 없다.
그리고 vue는 예전 dom과 최신 dom을 비교하여 차이가 있는 부분만 다시 렌더링 한다. 하지만 이때 모든 dom을 읽어들이는 것은 아니다. 왜냐하면 이렇게 읽어 들이는 것도 "expensive"한 작업이기 때문이다. 그래서 vue는 virtual dom
을 사용한다.
virtual dom
이란 실제 DOM의 가상 복사본인데 전적으로 JavaScript가 관리하므로 JS 기반 DOM이고 메모리에 위치한다.
그리고 이는 비교하고 가상 DOM에 업데이트하는 작업을 전적으로 메모리에서 수행하기 때문에 화면 렌더링으로 이어지는 실제 DOM에서 해당 작업을 하는 것보다 훨씬 효율적이다.