or
or
By clicking below, you agree to our terms of service.
New to HackMD? Sign up
Syntax | Example | Reference | |
---|---|---|---|
# Header | Header | 基本排版 | |
- Unordered List |
|
||
1. Ordered List |
|
||
- [ ] Todo List |
|
||
> Blockquote | Blockquote |
||
**Bold font** | Bold font | ||
*Italics font* | Italics font | ||
~~Strikethrough~~ | |||
19^th^ | 19th | ||
H~2~O | H2O | ||
++Inserted text++ | Inserted text | ||
==Marked text== | Marked text | ||
[link text](https:// "title") | Link | ||
 | Image | ||
`Code` | Code |
在筆記中貼入程式碼 | |
```javascript var i = 0; ``` |
|
||
:smile: | ![]() |
Emoji list | |
{%youtube youtube_id %} | Externals | ||
$L^aT_eX$ | LaTeX | ||
:::info This is a alert area. ::: |
This is a alert area. |
On a scale of 0-10, how likely is it that you would recommend HackMD to your friends, family or business associates?
Please give us some advice and help us improve HackMD.
Syncing
xxxxxxxxxx
Vue2 Reactivity : Vue2의 반응형 동작 원리 살펴보기
vue.js 2의 반응형
모델은 그저 plain js object이다. 모델에 변경이 생기면, 뷰가 업데이트된다.
이 과정이 단순하고, 직관적이지만, 이것이 어떻게 동작하는지를 알아야 한다.
어떻게 변경을 추적하는가
- The image file may be corrupted
- The server hosting the image is unavailable
- The image path is incorrect
- The image format is not supported
Learn More →- The image file may be corrupted
- The server hosting the image is unavailable
- The image path is incorrect
- The image format is not supported
Learn More →순수 자바스크립트 객체가 vue instance의
data
option으로 넘겨질 때,뷰는 그 객체의 모든 프로퍼티를
Object.defineProperty
를 사용하여getter/setter
로 바꾼다. 이는 ES5에만 적용되는 기능이고, 이것이 뷰가 IE8이하는 지원되지 않는 이유가 된다.getter와 setter는 유저에게는 보이지 않지만, 내부적으로 getter와 setter는 뷰가 의존관계를 추적하여 프로퍼티에 접근하거나 수정될 때, 변화를 알린다.
브라우저 콘솔은 이 getter와 setter를 다른 포맷으로 보여주므로 vue-devtools를 설치하여 관찰하기에 더 좋은 인터페이스로 보는 것이 좋다.
모든 컴포넌트 인스턴스는 그에 대응하는
watcher
인스턴스가 있다. 이 인스턴스는 컴포넌트가 종속적으로 렌더링되는동안 touch되는 모든 프로퍼티를 기록한다. 나중에 이 의존적인 것의 setter가 호출될 경우, 그것을 watcher가 알게 되며, 결과적으로 컴포넌트가 리렌더링이 된다.💡정리
변화 감지하기
객체
뷰는 프로퍼티가 추가되거나 삭제되는 것을 감지할 수 없다. 인스턴스가 초기화되는 동안에 프로퍼티를 getter/setter로 바꾸는 작업을 하기 때문에, 프로퍼티는 반드시
data
객체에 존재해야 한다. 그래야 뷰가 data 객체를 변경시키고, reactive하게 만들 수 있다.예를 들어, 아래의 a 프로퍼티는 인스턴스가 초기화되는 동안에 getter/setter로 변경되었으므로, reactive하다. 그러나, 초기화가 끝난 후 추가된 b는 reactive하지 않다.
즉, 뷰는 이미 생성된 인스턴스에 새로운 root-level 프로퍼티를 동적으로 추가하는 것을 허용하지 않는다. 그러나, 중첩된 객체에
Vue.set(object, propertyName, value
메소드를 사용하여 반응적인 프로퍼티를 추가할 수 있다.vm.$set
인스턴스 메서드를 사용할 수도 있다. 이는 전역Vue.set
의 alias이다.만약, 여러개의 프로퍼티를 이미 존재하는 객체에 추가하고 싶다면, 새로운 객체를 만들어서, 원래의 객체와 새로운 객체를 합쳐야 반응적이게 된다.
배열
뷰는 배열에 다음과 같은 일을 하면 변화를 감지할 수 없다.
배열의 요소를 변경시키고 싶다면, Vue.set이나 Array.prototype.splice로 변경시켜야 한다.
또 다른 방법으로는 vm.$set 인스턴스 메소드를 사용하는 것이다.
배열의 길이를 변경시키려면, splice를 사용해야 한다.
반응적인 프로퍼티 선언하기
뷰는 Root-level 반응적인 프로퍼티를 동적으로 추가할 수 없으므로, 뷰 인스턴스가 초기화되는 시점에 모든 데이타 프로퍼티를 선언해야 한다.
이러한 제약사항이 있는 이유에는 기술적인 이유가 있다.
이러한 제약이
코드의 유지보수면에서도 data객체에 모든 상태를 적는 것이 좋다. 해당 컴포넌트에서 사용하는 모든 상태를 데이타 객체에 넣으면, 나중에 다시 그 코드를 봤을 때도 더 쉽게 이해할 수 잇다.
Async Update Queue
뷰는 DOM 업데이트를 비동기적으로 한다. 데이터의 변화가 감지되면, queue를 열어서, 같은 이벤트 루프에서 일어난 데이터 변화들을 큐에 추가한다. 같은 watcher가 여러번 호출되면, 큐에는 한 번만 푸쉬된다. 오직 하나의 변화만 넣음으로써 불필요한 계산과 DOM 조작을 피할 수 있다.
그 다음 이벤트 루프가 tick되면, 뷰는 queue를 싹 비우고, 실제 작업을 수행한다. 내부적으로 뷰는 비동기 큐를 위해
Promise.then
,MutationObserver
,setImmediate
를 수행하고,setTimeout(fn, 0)
으로 돌아간다.예를 들어,
vm.someData = 'newVal'
처럼 상태가 변경되면, 컴포넌트는 즉시 리렌더링하지 않는다. 뷰는 다음 tick에 큐를 비우고, 업데이트한다.이러한 뷰의 동작 방식은 DOM 상태가 업데이트된 후에 의존적인 일을 하고자 하면, 까다로워진다. 뷰는 data-driven 방식을 지향하고, DOM에 직접 접근하는 것을 지양하지만, 직접 접근하는 것이 필요해질 것이다.
data가 변경된 후 뷰가 DOM에 업데이트한 것을 끝낸 것을 보장하기 위해서는, data가 변경된 직후에 바로
Vue.nextTick(callback)
을 사용해야 한다. 콜백은 DOM이 업데이트된 이후에 호출된다.vm.$nextTick()
인스턴스 메서드를 사용할 수 있다. 이 인스턴스 메서드의 콜백의 this는 자동으로 현재 뷰 인스턴스에 바인드되어있다.Vue.nextTick(callback)
vm.$el.textContent는 앞에 공백이 있기 때문에 trim을 해줘야 'new message'와 일치하는지를 제대로 비교할 수 있다.
this.$nextTick
async/await
nextTick은 프라미스를 반환하므로, async/await으로 DOM 업데이트가 끝나기를 기다릴 수 있다.
참고