data에 대해 Vue가 하는 일 중 가장 핵심적인 작업
= data 객체를 반응형 data 객체로 바꾸는 일
🧐 반응성이 뭔데?
Vue가 data의 특정 값을 추적하고, 해당 값에 새로운 값이 할당될 때마다 이를 Vue가 인식하고 제어하는 HTML 코드를 스캔하고, 위치를 파악하여 사용자에게 노출되는 페이지를 업데이트 하는 것.
🧐 어떻게 그게 가능하지?
프로퍼티를 JavaScript의 Proxy로 래핑함으로써 가능하다!
let message= 'Hello!';
let longMessage = message + 'World!';
console.log(longMessage);
message = 'Hello!!!!';
console.log(longMessage); // Hello! World! 출력
JavaScript는 반응형이 아니므로, 변수에 변경 사항이 생기더라도 변경 사항을 반영하지 않는다.
const data= {
message: 'Hello!',
longMessage: 'Hello! World!'
};
const handler = {
set(target, key, value) {
if(key === 'message') {
target.longMessage = value + 'World!';
}
target.message = value;
}
};
const proxy = new Proxy(data, handler);
proxy.message = 'Hello!!!!';
console.log(proxy.longMessage); //Hello!!!! World!
Proxy로 data를 감싸, data의 변화에 따라 값이 변경하도록 코드를 구현했다.
이 코드를 통해 대략적으로 어떤 방식을 통해 Vue가 반응형을 구현했는지 알 수 있다. 이 같은 반응형 작업을 Vue가 내부적으로 수행하고 있는 것이다.
(실제로는 이 코드보다 훨씬 복잡한 연산 과정을 거친다.)
페이지당 하나의 앱이 아닌, 여러 앱을 만들 수도 있다.
<header>
<h1>Vue Behind The Scenes</h1>
</header>
<section id="app">
<h2>How Vue Works</h2>
<input type="text" @input="saveInput">
<button @click="setText">Set Text</button>
<p>{{ message }}</p>
</section>
<section id="app2">
<p> {{ message }}</p> // Dose Not Work!!!!
<p> {{ Pazza }}</p>
</section>
const app = Vue.createApp({
data() {
return {
message: '안녕'
}
}
});
app.moount('#app');
const app2 = Vue.createApp({
data() {
return {
food: 'Pizza'
}
}
});
app.moount('#app2');
이 때, 각각의 Vue 앱들은 독립적으로 움직인다. app에서는 Pizza 데이터 프로퍼티에 접근할 수 없고, app2는 message 데이터 프로퍼티에 접근할 수 없다. 이는 두 앱들 사이에 연결 고리가 없기 때문이다.
따라서, 독립적이지 않고 서로 연동 되어야 하는 경우 해당하는 부분은 모두 동일한 Vue 앱으로 작성되어야 한다!
현재 코드의 구현 방식이 다음과 같다.
<section id="app">
<h2>How Vue Works</h2>
<input type="text" @input="saveInput">
<button @click="setText">Set Text</button>
<p>{{ message }}</p>
</section>
data() {
return {
currentUserInput: '',
message: 'Vue is great!',
};
},
methods: {
saveInput(event) {
this.currentUserInput = event.target.value;
},
setText() {
this.message = this.currentUserInput;
},
},
input 값을 가져와서 currentUserInput에 잠깐 넣어두고, 이후 message에 해당 문자를 삽입하는 방식이다. input 바인딩 대신에 v-model을 사용할 수도 있다.
Vue에는 필요할 때만 DOM 요소로부터 값을 가져오는 기능이 있다. 이 기능을 ref라고 부른다.
<h2>How Vue Works</h2>
<input type="text" ref="userText">
<button @click="setText">Set Text</button>
<p>{{ message }}</p>
methods: {
saveInput(event) {
this.currentUserInput = event.target.value;
},
setText() {
this.message = this.$refs.userText.value // input 엑세스 획득
console.log(this.$refs.userText)
},
},
$
: Vue가 지원하는 모든 프로퍼티는 $로 시작한다.(내장 프로퍼티임을 표현하기 위함)🧐 뷰는 어떤 방식으로 DOM을 업데이트하는걸까?
뷰는 화면 전체가 아니라 값이 달라진 일부만 부분적으로 수정한다. 어떻게 이런것이 가능할까? 뷰는 가상 DOM(Virtual DOM)으로 업데이트를 진행한다. 가상 DOM은 무엇이고, 왜 이 방식으로 업데이트를 진행하는걸까?
한쪽에는 개발자가 작업하는 Vue Instance가 있고, 그 끝부분에 최종적으로 웹사이트에 제공되는 BrowserDOM이 있다고 가장하자.
{{ message }}
=> <p>WoW!</p>
🧐 어떻게 이런 것들이 가능하지?
🤔 가설: 매번 이전의 DOM과 새로운 DOM을 비교해서 콘텐츠의 차이가 있으면 즉각적으로 업데이트하면 되지않을까?
이는 큰 성능저하를 야기하므로 실제로는 이렇게 진행하지 않는다.
대신, 가상 DOM이란 개념을 사용한다.
title: 'Hello!', text:'Not the title'
{el:'h2', child:'Hello!}, ...
<h2>Hello!</h2> <p>Not the title</p>
📋 정리해보자, 화면에서 변화가 발생할때, Vue의 내부에는 무슨 일이 벌어질까?
Udemy:【한글자막】 Vue - 완벽 가이드 (Router 및 Composition API 포함)
정보 감사합니다.