티스토리 뷰

Vue.JS

[Vue.JS] 반응형 시스템

버미노트 2019. 2. 20. 00:33

Vue의 가장 두드러지는 특징 중 하나는 눈에 띄지 않는 반응형 시스템입니다. 모델은 단순한 JavaScript 객체입니다. 모델이 수정되면 화면이 갱신됩니다. 이번 포스트에서 이러한 반응형 시스템을 좀 더 자세히 알아보려고 합니다.

1. MVVM 패턴

Vue는 MVVM 패턴에 영감을 받은 프레임워크입니다.

MVVM 패턴
MVVM 패턴

위의 그림은 MVVM 패턴을 나타내는 그림입니다. 더 자세한 설명은 [디자인패턴] MVC, MVP, MVVM 비교를 참고 바랍니다.

View는 DOM, View Model은 Vue, Model은 단순한 JavaScript 객체 입니다. View Model은 View와 데이터 바인딩되어 View Model이 변경 되 었을 때 View가 업데이트 됩니다.

2. 변경 내용을 추적하는 방법

Vue 인스턴스에 data 옵션을 포함하는 JavaScript 객체를 전달하면 Vue는 모든 속성에 Object.defineProperty를 사용하여 getter/setter로 변환합니다. 이것이 Vue는 ES5를 사용할 수 없는 IE8 이하를 지원하지 않는 이유입니다.

getter/setter는 사용자에게는 보이지 않지만 속성에 접근하거나 수정할 때 Vue가 종속성 추적 및 변경 알림을 수행할 수 있습니다.

모든 컴포넌트 인스턴스에는 해당 watcher 인스턴스가 있으며, 이 인스턴스는 컴포넌트가 종속적으로 렌더링되는 동안 수정된 모든 속성을 기록합니다. 또한 종속적인 setter가 트리거 되면 watcher에 알리고 컴포넌트가 다시 랜더링됩니다.

watcher의 역할
watcher의 역할

3. 변경 감지 경고

최신 JavaScript의 한계(Object.observe의 포기)로 인해 Vue는 속성의 추가 체거를 감지 할 수 없습니다. Vue는 인스턴스 초기화 할 때 getter/setter 변환 과정을 수행하기 때문에 data 객체에 속성이 있어서 Vue가 변경사항을 감지할 수 있습니다.

var vm = new Vue({
  data: {
    a: 1
  }
})
// `vm.a` 은 이제 반응적입니다.

vm.b = 2
// `vm.b` 은 이제 반응적이지 않습니다.

이미 만들어진 인스턴스에 반응 속성을 동적으로 추가하는 것을 허용하지 않지만, Vue.set(object, key, value) 메소드를 사용하여 중첩 된 객체에 반응성 속성을 추가 할 수 있습니다.

Vue.set(vm.someObject, 'b', 2)

위의 코드와 같이 루트 수준의 중첩 된 객체에 반응성 속성을 추가할 수 있습니다.

this.$set(this.someObject, 'b', 2)

위의 코드는 Vue.set에 별칭으로 this.$set을 사용한 코드입니다.

4. 반응형 속성 선언하기

Vue는 반응성 속성을 동적으로 추가 할 수 없기 때문에 반응성 테이터 속성을 빈 값으로라도 초기에 선언하여 Vue 인스턴스를 초기화 해야 합니다.

var vm = new Vue({
  data: {
    // 빈 값으로 메시지를 선언 합니다.
    message: ''
  },
  template: '{{ message }}'
})
// 나중에 `message`를 설정합니다.
vm.message = 'Hello!'

data 옵션에 message를 선언하지 않으면 Vue의 render 함수는 존재하지 않는 속성에 접근하려고 한다는 경고를 발생시킵니다. 모든 반응 속성을 미리 선언하면 나중에 다른 개발자가 코드를 분석 할 때 코드를 더 쉽게 이해 할 수 있습니다.

5. 비동기 갱신 큐

Vue는 DOM 업데이트를 비동기로 동작합니다. 모든 데이터 변경 사항은 버퍼링됩니다. 즉 동일한 watcher가 여러번 트리거 되더라고 한번만 큐에 푸시 됩니다. 이 버퍼링은 중복된 변경 사항의 불필요한 계산을 줄이고, DOM 조작을 최소화하기 때문에 중요합니다. 그 후에는 이벤트 루프 tick에서 Vue는 큐를 비우고 실제 DOM에 작업(버퍼링으로 중복이 제거된 작업)을 수행합니다.

예를 들어, vm,someDate = 'new value'를 설정하면, 컴포넌트는 즉시 재 랜더링하지 않습니다. 다음 tick에서 업데이트 됩니다. 대부분의 경우에는 이 작업을 신경 쓸 필요는 없지만, 업데이트 된 후 DOM 상태에 의존적인 작업을 하기 위해서는 까다로울 수 있습니다. Vue는 일반적으로 개발자가 데이터 중심적으로 개발하고 DOM을 직접 수정하지 않는 것을 권장하지만 때로는 직접 DOM을 수정해야 필요도 있습니다.

Vue가 DOM을 업데이트 된 후의 DOM을 보장하기 위해서는 Vue.nextTick(callback) 을 사용하면 됩니다. 이 callback은 DOM이 업데이트 된 후에 호출 되기 때문에 DOM이 업데이트 된 이후임을 보장할 수 있습니다.

<div id="example">{{ message }}</div>
var vm = new Vue({
  el: '#example',
  data: {
    message: '123'
  }
})
vm.message = 'new message' // 데이터  변경
vm.$el.textContent === 'new message' // false
Vue.nextTick(function () {
  vm.$el.textContent === 'new message' // true
})

또한 this.$nextTick() 메소드를 제공합니다. 이 메소드는 컴포넌트 인스턴스에서 사용할 때 유용합니다.

Vue.component('example', {
  template: '{{ message }}',
  data: function () {
    return {
      message: '갱신 안됨'
    }
  },
  methods: {
    updateMessage: function () {
      this.message = '갱신됨'
      console.log(this.$el.textContent) // => '갱신 안됨'
      this.$nextTick(function () {
        console.log(this.$el.textContent) // => '갱신됨'
      })
    }
  }
})

참고

'Vue.JS' 카테고리의 다른 글

[vue-router] 동적 라우트 매칭  (0) 2019.06.09
[vue-router] 시작하기  (0) 2019.06.06
[Vue.JS] 필터  (2) 2019.02.19
[Vue.JS] 플러그인  (0) 2019.02.18
[Vue.JS] Render Functions & JSX  (0) 2019.02.14
댓글
공지사항
최근에 올라온 글