[Vue.js] 뷰 모델의 Reactivity 구현(Databinding에 관하여)

안녕하세요.

오늘은 vue.js의 특징중 Reactivity에 관해서 포스팅해보고자 합니다.

 

먼저, vue.js의 특징중에서 뷰 모델의 내용이 바뀌면 새로고침이 필요없이 즉각적으로 화면에 반영된다는 장점이 있습니다. 기존 웹개발에서의 소스를 보시죠.

 

기존 소스
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <div id="app"></div>
    <script>
        var div = document.querySelector("#app");
        var str = 'hello world'
        div.innerHTML = str

        str = 'hello world!!!'
        div.innerHTML = str
        
    </script>
</body>
</html>

우리가 일반적으로 html, css, javascript를 코딩할 때의 모습과 똑같은 모습입니다. 

여기서 주목해야할 점이 str이라는 변수를 바꿔주고 innerHTML을 이용해서 두번 바인딩해주었다는 것입니다. 즉, 기존 웹개발에서는 데이터가 변경이 될때마다 개발자가 프로그래밍을 통해서 직접 바인딩해주어야 했습니다.

 

하지만 Vue.js에서는 

 

Vue.js 소스
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Getting Started</title>
  </head>
  <body>
    <div id="app">
      {{ message }}
    </div>

    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <script>
      new Vue({
        el: '#app',
        data: {
          message: 'Hello Vuejs'
        }
      })
    </script>
  </body>
</html>

Vue 객체의 data의 message 속성이 변할 때마다 브라우저의 html 문서가 즉각적으로 변경될 것입니다.

오늘의 포스팅은 이를 직접 구현하여 이해해보고자 합니다.

 

그 전에 한가지 api를 알아두어야 하는데요.

바로 Object.defineProperty() 입니다. 

 

Object.defineProperty()
Object.defineProperty('대상 객체', '객체의 속성', {

    // 정의할 내용

}) //객체의 동작을 재정의

객체에 직접 새로운 속성을 정의하거나 이미 존재하는 속성을 수정한 후, 그 객체를 반환합니다.

 

만약 우리가 정의해야할 속성이

var viewModel = {};

다음과 같이 정의되어 있을 때,

 

Object.defineProperty(viewModel, 'str', {
//속성의 접근했을 때 동작을 정의.
	get: function(){
		console.log('접근')
	},
//속성의 값을 할당했을 때의 동작을 정의
	set : function(newValue){
		console.log('할당' , newValue)                
		div.innerHTML(newValue)
	}
})

viewModel이라는 객체에 대하여 접근(get)할때와, 할당(set)할때 특정한 액션을 취해주도록 합니다. 이는 Object.defineProperty() 메소드 레퍼런스 문서에 정의된 내용이 있으므로 필요하신 경우 참조하시길 바랍니다.

https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty

 

라이브러리화 하기

다음과 같은 로직을 해당 html 내부에서 라이브러리화하기 위해서는 즉시실행 함수를 활용해야합니다.

 

즉시실행함수에 관하여는 다음의 포스팅을 확인해주시기 바랍니다.!!

2020/03/03 - [웹 개발/Javascript] - [Javascript] 자바스크립트 즉시실행 함수(IIFE)

 

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <div id="app"></div>

    <script>
        var div = document.querySelector('#app')
        var viewModel = {};
        
        (function(){
          //라이브러리화 소스
          function init(){
            Object.defineProperty(viewModel, 'str', {
              //속성의 접근했을 때 동작을 정의.
              get: function(){
                console.log('접근')
              },
              //속성의 값을 할당했을 때의 동작을 정의
              set : function(newValue){
                console.log('할당' , newValue)                
                render(newValue)
              }
            })
          }

          function render(newValue){
            div.innerHTML = newValue
          }
          init()
        })()
    </script>
</body>
</html>

즉시실행함수 패턴을 이용하여 먼저 즉시실행 함수내 init을 정의하고 접근할때, 할당할 때 행동을 정의해줍니다. 특히 할당할 때 html의 데이터바인딩을 위해 render함수를 호출하게되고 이는 innerHTML로 새 할당값을 변경해주는 로직으로 간단히 구현하였습니다.

 

이후 즉각적으로 init()을 실행하여 viewModel에 접근할 때, 할당할 때 특정 이벤트가 발생하도록 실행합니다. 

 

이 모든 과정이 끝났을 때 실질적으로 익명함수가 즉시실행되어 html 내부에서 viewModel에 대한 새로운 속성들이 정의되어 실행됩니다.

 

Vue의 Reactivity

- 뷰의 리액티비티에 대한 핵심, 데이터 바인딩.
- 데이터의 변화를 라이브러리에서 감지해서 알아서 화면을 자동으로 그려주는 것.

 

 

댓글

Designed by JB FACTORY