SlideShare a Scribd company logo
Virtual Dom
to Render
우경화
Question
export default {
data () {
return {
isBlue : true
}
},
methods : {
toggleColor () {
this.isBlue = !this.isBlue
}
},
mounted () {
makeItRed( document.querySelector(‘#btn) )
}
}
.btn-red { background: red !important}
.btn-white { background: white}
.btn-blue { background: blue}
function makeItRed (el){
el.classList.add(‘btn-red’);
}
<button id = ”btn”
:class = ”isBlue? ’btn-blue’ : ’btn-white’ ”
@click = ”toggleColor”
>click here</button>
When this component mounted, the background of the button is red
(makeItRed has been called and .btn-red beats .btn-blue by ‘!important’)
If you click the button, what would be the background of button?
DOM and Virtual DOM
Dom and Virtual Dom
DOM virtual DOM
해결?문제?
<section class=”section”>
<header class=”header”>
<h1></h1>
</header>
<article>
<div class=”box”></div>
<a href=”#”></a>
….
</article>
</section>
{
tag: ‘section’,
data: { class: ‘section’ },
children: [
{ tag: ’header’, …,
data: { class: ‘header’}
children: [ {tag: ’h1’...} ]
},
{ tag: ‘article’, … }
…..
}
document와 document 내부의 태그에 대한 정의와 api를
규격화 한 모델. 기존 BOM(Browser object model)의
크로스 브라우징이 어려워 w3c에서 권고됨.
DOM을 본따 만든 javascript object.
메모리상에 있어 생성과 수정, 삭제가 빠름. Dom 처럼
트리구조를 가짐
Virtual Dom is faster than Dom, so?
Real Dom?
Virtual Dom?
Virtual Dom prevents bad performance
bad performance?
virtual dom도 결국 dom에 patch가 되어야 하니 DOM을 직접
제어하는 코드보다 빠를수 없다.
DOM을 필요없이 읽거나 또는 잘못된 순서로 처리 되면
bad performance를 야기시킴
redux의 창시자 Dan Abramov
Virtual Dom prevents bad performance
chrome > 개발자 도구 >console drawer> rendering > paint flashing 체크
Green => reflow, repaint
DOM의 업데이트 내용을 다시 브라우저에 표시하기 위해
다시 layout을 계산하고 그리는 작업(reflow, repaint)이 발생,
변경된 DOM뿐 아니라 근처의 DOM과 node tree의 DOM
까지 영향을 주기 때문에 필요하지 않은 과정이 반복된다면
performance에 악영향을 줌
이런 layout 재작업은 DOM의 속성을 읽을 때도 발생
나도
다시
그려줘~
넌 관계도 없는데
왜?
Changing one DOM leads to..
Dom is Fast!
B.U.T
Reflow, Repaint aren’t
how many…;;;
VDom prevents unnecessary access to DOM
text
C
SS
Other Benefits
$('.img').mouseover(function(e){
if (err ) {
$('.tranvel-msg').text(err)
.show();
}
}).mouseout(function(e){
$('.tranvel-msg').hide();
})
<img src="img.png" class="img"
@mouseover="show = error && true"
@mouseout="show = false">
<div class='travel-msg'
v-show="show">{{{error}}}</div>
jQuery Vue
1. DOM과 유사한 형태로 쓰기 때문에 가독성 증가
2. 쉬운 유지 보수 확장
3. DOM의 정적인 attrs 를 functional 하게 만들어줌
Snabbdom
vue 2.0에서 채택된 기본 virtual dom library
snabbdom(https://github.com/snabbdom/snabbdom)
const snabbdom = require('snabbdom/snabbdom.js');
import h from 'snabbdom/h'; //create new virtual dom
const patch = snabbdom.init([
require('snabbdom/modules/class').default,
require('snabbdom/modules/props').default,
require('snabbdom/modules/style').default,
require('snabbdom/modules/eventlisteners').default
]);
snabbdom(https://github.com/snabbdom/snabbdom)
let oldv = document.getElementById('static_dom');
let vnode = h('div#static_dom', {
class: [ 'classed'],
style: { color: '#f00', textDecoration: ‘underline’ },
on: { click: changeToButton }
}, 'but changed by virtual dom');
setTimeout(function () { oldv = patch(oldv, vnode); }, 3000)
snabbdom(https://github.com/snabbdom/snabbdom)
let oldv = document.getElementById(‘dom’)
function createVNode () {
return h(this.tag, this.data, this.children)
}
function updateObj (oldv, data) {
return patch(oldv, createVNode.call(data)
}
oldv = updateObj(obj)
// obj 내부의 데이터에 setter로 updateObj를 호출하거나
pubsub 패턴을 더한다면 data에 따라 값이 바뀌는 원시
Vue 완성
var obj = {
tag: 'button',
data: {
type: 'button',
class: { 'btn': true, 'btn-green': true },
on: {
click: function () {
window.open('https://kr.vuejs.org/v2/guide/r
ender-function.html','_blank');}
}},
children: 'To Vue Blog'
}
snabbdom(https://github.com/snabbdom/snabbdom)
https://kellywoo.github.io/vnode/
결과물
Vue create VNode Fn
https://vuejs.org/v2/guide/render-function.html#ad
Vue render function
render: function (h) {
var vm = this // this는 현재의 component를 가리킴
var myHi = h('p', 'hi')
return h( 'div' , … //tag
{ … //data object class, staticClass, style, }⁰,
[myHi, Object.assign({}, myHi)¹]) //children
}
//0. https://kr.vuejs.org/v2/guide/render-function.htm 실제 data structure
//1. vnode는 유일무이해야한다.
Patch function(between vnodes)
OLD VNode NEW VNode
Vue process
update
data
watcher create
vnode
insert
Queue
dom
update
template
related?
duplicated
request?
any diff?
mutation
notify
Vue rendering example
https://kellywoo.github.io/vnode/
그럼 다시
Rendering example(https://kellywoo.github.io/vnode/ -2.render)
숫자가 렌더링 템플릿에 더해짐숫자가 렌더링 템플릿에 없음
show Numbers: trueshow Numbers : false
아무리 버튼을 클릭해도 숫자 증가 없음
각 숫자는 해당 컴포넌트가 새로운 virtual dom을 생성할때 마다(render function 호출 때 마다) 1씩 증가
버튼 클릭시 child component만 1씩 증가,
자식 컴포넌트인 grand-child 는 변경없음
click click4
keep-alive example(https://kellywoo.github.io/vnode/ -3.vnode)
seranio
vnode의 keep-alive 제어
child comp의 v-if 제어
classLIst.add로 dom에
.btn-red 를 더함
.btn-red{
background:red !important}
현재는 .btn-blue
{background:skyblue}
A
B
C
c를 눌러 버튼을 변경
버튼에 빨간색이 적용
B를 2번 눌러
child component를
remove => create
시킴
keep-alive example(https://kellywoo.github.io/vnode/ -3.vnode)
case: false
버튼에 빨간색이 적용이
사라짐
버튼에 빨간색이 적용이
그대로임
case: true
❋console에 vueconsole()을 입력, parent
component.$children 항목을 볼 수 있습니다.
-keep-alive: false
child destroy hook이 발생되며
component가 제거되어 create을 누르면 다시
component가 생성, element도 재생성되며
기존에 있던 .btn-red 클래스는 사라짐.
vueconsole() => (2) [a, a]
-keep-alive: true
child deactivate hook이 발생,
자식 컴포넌트가 그대로 남아있어,create을
눌렀을 때 별도의 data 변경이 없다면
render 함수가 실행되지 않아 이전의 $el을
그대로 보여줌
vueconsole() => (3) [a, a, a]
Answer : white
export default {
data () {
return {
isBlue : true
}
},
methods : {
toggleColor () {
this.isBlue = !this.isBlue
}
},
mounted () {
makeItRed( document.querySelector(‘#btn) )
}
}
.btn-red { background: red !important}
.btn-white { background: white}
.btn-blue { background: blue}
function makeItRed (el){
el.classList.add(‘btn-red’);
}
<button id = ”btn”
:class = ”isBlue? ’btn-blue’ : ’btn-white’ ”
@click = ”toggleColor”
>click here</button>
When this component mounted, the background of the button is red
(makeItRed has been called and .btn-red beats .btn-blue by ‘!important’)
If you click the button, what would be the background of button?
Again, Patch function doesn’t care the element’s state
OLD VNode NEW VNode
patch 함수 내부에선 old vnode와 new vnode 만 비교,
class 영역의 diff 발견 => element의 class 업데이트
이때 vnode와 연결되지 않은 .btn-red 클래스는 사라집니다.
Virtual Dom은 자신에게 알려지지 않은 속성들에 대해서는 책임지지 않습니다.
확인을 위해 하늘색 버튼 더블 클릭
nonetheless, vue is Javascript.
결과를 아는 것 보다, 왜 그렇게 되는 것인지 이해하는 것이
vue를 더 잘 쓸 수 있는 방법
kelly.kh.woo@gmail.com
감사합니다.

More Related Content

Similar to Virtual dom to render

안드로이드 개발자를 위한 스위프트
안드로이드 개발자를 위한 스위프트안드로이드 개발자를 위한 스위프트
안드로이드 개발자를 위한 스위프트
병한 유
 
Secrets of the JavaScript Ninja - Chapter 12. DOM modification
Secrets of the JavaScript Ninja - Chapter 12. DOM modificationSecrets of the JavaScript Ninja - Chapter 12. DOM modification
Secrets of the JavaScript Ninja - Chapter 12. DOM modification
Hyuncheol Jeon
 
FE로 취업 전에 알았으면 좋았을 것들
FE로 취업 전에 알았으면 좋았을 것들FE로 취업 전에 알았으면 좋았을 것들
FE로 취업 전에 알았으면 좋았을 것들
Taegon Kim
 
MVI on android Droid Knights 2020
MVI on android Droid Knights 2020 MVI on android Droid Knights 2020
MVI on android Droid Knights 2020
JaehoChoe3
 
Meteor2015 codelab
Meteor2015 codelab Meteor2015 codelab
Meteor2015 codelab
WebFrameworks
 
Hacosa js study 4주차
Hacosa js study 4주차Hacosa js study 4주차
Hacosa js study 4주차Seong Bong Ji
 
Hacosa j query 8th
Hacosa j query 8thHacosa j query 8th
Hacosa j query 8th
Seong Bong Ji
 
Coded ui가이드
Coded ui가이드Coded ui가이드
Coded ui가이드
SangIn Choung
 
Web Components 101 polymer & brick
Web Components 101 polymer & brickWeb Components 101 polymer & brick
Web Components 101 polymer & brickyongwoo Jeon
 
[XECon+PHPFest 2014] jQuery 개발자에서 AngularJS 개발자 되기
[XECon+PHPFest 2014] jQuery 개발자에서 AngularJS 개발자 되기[XECon+PHPFest 2014] jQuery 개발자에서 AngularJS 개발자 되기
[XECon+PHPFest 2014] jQuery 개발자에서 AngularJS 개발자 되기
Jeado Ko
 
RUCK 2017 Shiny의 또 다른 활용: RStudio addin 함수 및 패키지의 제작
RUCK 2017 Shiny의 또 다른 활용: RStudio addin 함수 및 패키지의 제작RUCK 2017 Shiny의 또 다른 활용: RStudio addin 함수 및 패키지의 제작
RUCK 2017 Shiny의 또 다른 활용: RStudio addin 함수 및 패키지의 제작
r-kor
 
Shiny의 또 다른 활용
Shiny의 또 다른 활용Shiny의 또 다른 활용
Shiny의 또 다른 활용
건웅 문
 
Vuejs 시작하기
Vuejs 시작하기Vuejs 시작하기
Vuejs 시작하기
성일 한
 
GDG DevFest 2017 Seoul 프론트엔드 모던 프레임워크 낱낱히 파헤치기
 GDG DevFest 2017 Seoul 프론트엔드 모던 프레임워크 낱낱히 파헤치기 GDG DevFest 2017 Seoul 프론트엔드 모던 프레임워크 낱낱히 파헤치기
GDG DevFest 2017 Seoul 프론트엔드 모던 프레임워크 낱낱히 파헤치기
Kenneth Ceyer
 
Deep dive into Modern frameworks - HTML5 Forum 2018
Deep dive into Modern frameworks - HTML5 Forum 2018Deep dive into Modern frameworks - HTML5 Forum 2018
Deep dive into Modern frameworks - HTML5 Forum 2018
Kenneth Ceyer
 
2. widget
2. widget2. widget
2. widget
Jongmini
 
자바스크립트 프레임워크 살펴보기
자바스크립트 프레임워크 살펴보기자바스크립트 프레임워크 살펴보기
자바스크립트 프레임워크 살펴보기
Jeado Ko
 
Opinion 프로젝트 발표 자료
Opinion 프로젝트 발표 자료Opinion 프로젝트 발표 자료
Opinion 프로젝트 발표 자료
joonseokkim11
 
Modern web application with meteor
Modern web application with meteorModern web application with meteor
Modern web application with meteor
Jaeho Lee
 
Android UI Test (Espresso/Kakao)
Android UI Test (Espresso/Kakao)Android UI Test (Espresso/Kakao)
Android UI Test (Espresso/Kakao)
MDLicht
 

Similar to Virtual dom to render (20)

안드로이드 개발자를 위한 스위프트
안드로이드 개발자를 위한 스위프트안드로이드 개발자를 위한 스위프트
안드로이드 개발자를 위한 스위프트
 
Secrets of the JavaScript Ninja - Chapter 12. DOM modification
Secrets of the JavaScript Ninja - Chapter 12. DOM modificationSecrets of the JavaScript Ninja - Chapter 12. DOM modification
Secrets of the JavaScript Ninja - Chapter 12. DOM modification
 
FE로 취업 전에 알았으면 좋았을 것들
FE로 취업 전에 알았으면 좋았을 것들FE로 취업 전에 알았으면 좋았을 것들
FE로 취업 전에 알았으면 좋았을 것들
 
MVI on android Droid Knights 2020
MVI on android Droid Knights 2020 MVI on android Droid Knights 2020
MVI on android Droid Knights 2020
 
Meteor2015 codelab
Meteor2015 codelab Meteor2015 codelab
Meteor2015 codelab
 
Hacosa js study 4주차
Hacosa js study 4주차Hacosa js study 4주차
Hacosa js study 4주차
 
Hacosa j query 8th
Hacosa j query 8thHacosa j query 8th
Hacosa j query 8th
 
Coded ui가이드
Coded ui가이드Coded ui가이드
Coded ui가이드
 
Web Components 101 polymer & brick
Web Components 101 polymer & brickWeb Components 101 polymer & brick
Web Components 101 polymer & brick
 
[XECon+PHPFest 2014] jQuery 개발자에서 AngularJS 개발자 되기
[XECon+PHPFest 2014] jQuery 개발자에서 AngularJS 개발자 되기[XECon+PHPFest 2014] jQuery 개발자에서 AngularJS 개발자 되기
[XECon+PHPFest 2014] jQuery 개발자에서 AngularJS 개발자 되기
 
RUCK 2017 Shiny의 또 다른 활용: RStudio addin 함수 및 패키지의 제작
RUCK 2017 Shiny의 또 다른 활용: RStudio addin 함수 및 패키지의 제작RUCK 2017 Shiny의 또 다른 활용: RStudio addin 함수 및 패키지의 제작
RUCK 2017 Shiny의 또 다른 활용: RStudio addin 함수 및 패키지의 제작
 
Shiny의 또 다른 활용
Shiny의 또 다른 활용Shiny의 또 다른 활용
Shiny의 또 다른 활용
 
Vuejs 시작하기
Vuejs 시작하기Vuejs 시작하기
Vuejs 시작하기
 
GDG DevFest 2017 Seoul 프론트엔드 모던 프레임워크 낱낱히 파헤치기
 GDG DevFest 2017 Seoul 프론트엔드 모던 프레임워크 낱낱히 파헤치기 GDG DevFest 2017 Seoul 프론트엔드 모던 프레임워크 낱낱히 파헤치기
GDG DevFest 2017 Seoul 프론트엔드 모던 프레임워크 낱낱히 파헤치기
 
Deep dive into Modern frameworks - HTML5 Forum 2018
Deep dive into Modern frameworks - HTML5 Forum 2018Deep dive into Modern frameworks - HTML5 Forum 2018
Deep dive into Modern frameworks - HTML5 Forum 2018
 
2. widget
2. widget2. widget
2. widget
 
자바스크립트 프레임워크 살펴보기
자바스크립트 프레임워크 살펴보기자바스크립트 프레임워크 살펴보기
자바스크립트 프레임워크 살펴보기
 
Opinion 프로젝트 발표 자료
Opinion 프로젝트 발표 자료Opinion 프로젝트 발표 자료
Opinion 프로젝트 발표 자료
 
Modern web application with meteor
Modern web application with meteorModern web application with meteor
Modern web application with meteor
 
Android UI Test (Espresso/Kakao)
Android UI Test (Espresso/Kakao)Android UI Test (Espresso/Kakao)
Android UI Test (Espresso/Kakao)
 

Virtual dom to render

  • 2. Question export default { data () { return { isBlue : true } }, methods : { toggleColor () { this.isBlue = !this.isBlue } }, mounted () { makeItRed( document.querySelector(‘#btn) ) } } .btn-red { background: red !important} .btn-white { background: white} .btn-blue { background: blue} function makeItRed (el){ el.classList.add(‘btn-red’); } <button id = ”btn” :class = ”isBlue? ’btn-blue’ : ’btn-white’ ” @click = ”toggleColor” >click here</button> When this component mounted, the background of the button is red (makeItRed has been called and .btn-red beats .btn-blue by ‘!important’) If you click the button, what would be the background of button?
  • 4. Dom and Virtual Dom DOM virtual DOM 해결?문제? <section class=”section”> <header class=”header”> <h1></h1> </header> <article> <div class=”box”></div> <a href=”#”></a> …. </article> </section> { tag: ‘section’, data: { class: ‘section’ }, children: [ { tag: ’header’, …, data: { class: ‘header’} children: [ {tag: ’h1’...} ] }, { tag: ‘article’, … } ….. } document와 document 내부의 태그에 대한 정의와 api를 규격화 한 모델. 기존 BOM(Browser object model)의 크로스 브라우징이 어려워 w3c에서 권고됨. DOM을 본따 만든 javascript object. 메모리상에 있어 생성과 수정, 삭제가 빠름. Dom 처럼 트리구조를 가짐
  • 5. Virtual Dom is faster than Dom, so? Real Dom? Virtual Dom?
  • 6. Virtual Dom prevents bad performance bad performance? virtual dom도 결국 dom에 patch가 되어야 하니 DOM을 직접 제어하는 코드보다 빠를수 없다. DOM을 필요없이 읽거나 또는 잘못된 순서로 처리 되면 bad performance를 야기시킴 redux의 창시자 Dan Abramov
  • 7. Virtual Dom prevents bad performance chrome > 개발자 도구 >console drawer> rendering > paint flashing 체크 Green => reflow, repaint DOM의 업데이트 내용을 다시 브라우저에 표시하기 위해 다시 layout을 계산하고 그리는 작업(reflow, repaint)이 발생, 변경된 DOM뿐 아니라 근처의 DOM과 node tree의 DOM 까지 영향을 주기 때문에 필요하지 않은 과정이 반복된다면 performance에 악영향을 줌 이런 layout 재작업은 DOM의 속성을 읽을 때도 발생 나도 다시 그려줘~ 넌 관계도 없는데 왜?
  • 8. Changing one DOM leads to.. Dom is Fast! B.U.T Reflow, Repaint aren’t how many…;;;
  • 9. VDom prevents unnecessary access to DOM text C SS
  • 10. Other Benefits $('.img').mouseover(function(e){ if (err ) { $('.tranvel-msg').text(err) .show(); } }).mouseout(function(e){ $('.tranvel-msg').hide(); }) <img src="img.png" class="img" @mouseover="show = error && true" @mouseout="show = false"> <div class='travel-msg' v-show="show">{{{error}}}</div> jQuery Vue 1. DOM과 유사한 형태로 쓰기 때문에 가독성 증가 2. 쉬운 유지 보수 확장 3. DOM의 정적인 attrs 를 functional 하게 만들어줌
  • 11. Snabbdom vue 2.0에서 채택된 기본 virtual dom library
  • 12. snabbdom(https://github.com/snabbdom/snabbdom) const snabbdom = require('snabbdom/snabbdom.js'); import h from 'snabbdom/h'; //create new virtual dom const patch = snabbdom.init([ require('snabbdom/modules/class').default, require('snabbdom/modules/props').default, require('snabbdom/modules/style').default, require('snabbdom/modules/eventlisteners').default ]);
  • 13. snabbdom(https://github.com/snabbdom/snabbdom) let oldv = document.getElementById('static_dom'); let vnode = h('div#static_dom', { class: [ 'classed'], style: { color: '#f00', textDecoration: ‘underline’ }, on: { click: changeToButton } }, 'but changed by virtual dom'); setTimeout(function () { oldv = patch(oldv, vnode); }, 3000)
  • 14. snabbdom(https://github.com/snabbdom/snabbdom) let oldv = document.getElementById(‘dom’) function createVNode () { return h(this.tag, this.data, this.children) } function updateObj (oldv, data) { return patch(oldv, createVNode.call(data) } oldv = updateObj(obj) // obj 내부의 데이터에 setter로 updateObj를 호출하거나 pubsub 패턴을 더한다면 data에 따라 값이 바뀌는 원시 Vue 완성 var obj = { tag: 'button', data: { type: 'button', class: { 'btn': true, 'btn-green': true }, on: { click: function () { window.open('https://kr.vuejs.org/v2/guide/r ender-function.html','_blank');} }}, children: 'To Vue Blog' }
  • 16. Vue create VNode Fn https://vuejs.org/v2/guide/render-function.html#ad
  • 17. Vue render function render: function (h) { var vm = this // this는 현재의 component를 가리킴 var myHi = h('p', 'hi') return h( 'div' , … //tag { … //data object class, staticClass, style, }⁰, [myHi, Object.assign({}, myHi)¹]) //children } //0. https://kr.vuejs.org/v2/guide/render-function.htm 실제 data structure //1. vnode는 유일무이해야한다.
  • 21. Rendering example(https://kellywoo.github.io/vnode/ -2.render) 숫자가 렌더링 템플릿에 더해짐숫자가 렌더링 템플릿에 없음 show Numbers: trueshow Numbers : false 아무리 버튼을 클릭해도 숫자 증가 없음 각 숫자는 해당 컴포넌트가 새로운 virtual dom을 생성할때 마다(render function 호출 때 마다) 1씩 증가 버튼 클릭시 child component만 1씩 증가, 자식 컴포넌트인 grand-child 는 변경없음 click click4
  • 22. keep-alive example(https://kellywoo.github.io/vnode/ -3.vnode) seranio vnode의 keep-alive 제어 child comp의 v-if 제어 classLIst.add로 dom에 .btn-red 를 더함 .btn-red{ background:red !important} 현재는 .btn-blue {background:skyblue} A B C c를 눌러 버튼을 변경 버튼에 빨간색이 적용 B를 2번 눌러 child component를 remove => create 시킴
  • 23. keep-alive example(https://kellywoo.github.io/vnode/ -3.vnode) case: false 버튼에 빨간색이 적용이 사라짐 버튼에 빨간색이 적용이 그대로임 case: true ❋console에 vueconsole()을 입력, parent component.$children 항목을 볼 수 있습니다. -keep-alive: false child destroy hook이 발생되며 component가 제거되어 create을 누르면 다시 component가 생성, element도 재생성되며 기존에 있던 .btn-red 클래스는 사라짐. vueconsole() => (2) [a, a] -keep-alive: true child deactivate hook이 발생, 자식 컴포넌트가 그대로 남아있어,create을 눌렀을 때 별도의 data 변경이 없다면 render 함수가 실행되지 않아 이전의 $el을 그대로 보여줌 vueconsole() => (3) [a, a, a]
  • 24. Answer : white export default { data () { return { isBlue : true } }, methods : { toggleColor () { this.isBlue = !this.isBlue } }, mounted () { makeItRed( document.querySelector(‘#btn) ) } } .btn-red { background: red !important} .btn-white { background: white} .btn-blue { background: blue} function makeItRed (el){ el.classList.add(‘btn-red’); } <button id = ”btn” :class = ”isBlue? ’btn-blue’ : ’btn-white’ ” @click = ”toggleColor” >click here</button> When this component mounted, the background of the button is red (makeItRed has been called and .btn-red beats .btn-blue by ‘!important’) If you click the button, what would be the background of button?
  • 25. Again, Patch function doesn’t care the element’s state OLD VNode NEW VNode patch 함수 내부에선 old vnode와 new vnode 만 비교, class 영역의 diff 발견 => element의 class 업데이트 이때 vnode와 연결되지 않은 .btn-red 클래스는 사라집니다. Virtual Dom은 자신에게 알려지지 않은 속성들에 대해서는 책임지지 않습니다. 확인을 위해 하늘색 버튼 더블 클릭
  • 26. nonetheless, vue is Javascript. 결과를 아는 것 보다, 왜 그렇게 되는 것인지 이해하는 것이 vue를 더 잘 쓸 수 있는 방법