양방향 바인딩

    <input type="text" v-model="name">
    <button v-on:click="resetInput">Reset Input</button>
    <p>Your Name: {{ name }}</p>

v-model

  • 양방향 바인딩 (양방향으로 통신)
    1. 입력 요소에서 나오는 이벤트, 즉 입력 이벤트 수신 = v-on:input
    2. value 속성 및 value 프로퍼티를 통해 값을 입력 요소에 다시 보낸다. = v-bind:value
  • v-bind:value, v-on:input의 축약어
  • name 프로퍼티를 Vue에서 관리
  • input 이벤트에서 업데이트 되고 , name 프로퍼티 값은 입력 요소로 다시 전송된다.
  • 사용자 입력의 수신과 업데이트를 쉽게 한다.
  • 양방향 바인딩(v-model) = 데이터 바인딩(v-bind:value) + 이벤트 바인딩(v-on:input)

데이터 바인딩에 사용되는 메서드 작동 원리

  • DOM Interaction, Templates & Data Binding
  • Event Handling
  • "Advanced" Reactivity

성을 추가하는 기능을 메서드로 구현해보자!

    <h2>Events in Action</h2>
    <button v-on:click=addCounter(5)>Add</button>
    <button v-on:click=reduceCounter(5)>Reduce</button>
    <p v-once>Starting Counter: {{ counter }}</p>
    <p>Result: {{ counter }}</p>
    
    <input type="text" v-model="name">
    <button v-on:click="resetInput">Reset Input</button>
    <p>Your Name: {{ outputFullname() }}</p>
    
  methods: {
    outputFullname() {
      console.log('Running again...')
      if (this.name === '') {
        return '';
      }
      return this.name + ' ' + 'Lee';
    },
  }

이제 정상적으로 성을 뒤에 붙여주는 기능을 구현했다.

그러나 이것은 최고의 방법이 아니다.

🧐 왜 최고의 방법이 아닐까?

위에 counter 값이 변화할때도 보이진 않으나 Vue가 내부에서 이상적이지 않은 어떤 기능을 수행한다.

counter 값이 변경되면 Vue는 기본적으로 이 페이지에서 렌더링 된 페이지를 업데이트 할 위치를 찾으려고 한다. 가령 <p>Result: {{ counter }}</p> 이 부분에서 counter를 사용하고 있으므로 이 부분을 업데이트하려고 할 것이다. (이같은 자동 업데이트 기능이란 장점이 우리가 vue를 사용하는 이유이기도 하다.)

문제는 outputFullname()과 같은 메서드를 실행하면, 페이지에 변경이 생길 때마다 메서드도 Vue에 의해 재실행된다. (만약 outputFullname() 메서드에서 counter 값이 변경이 있다면, 이 메서드가 실행되는 것이 실제로 옳은 행위일 것이다.) Vue는 메서드가 하는 일을 알 수 없기 때문에, counter 사용 여부 역시 모르고, 따라서 HTML 코드 내 모든 메서드들을 재실행한다! 😮 이는 성능 면에서 좋지 않다.

따라서, 메서드는 동적으로 계산된 값을 출력하기 위한 최선의 해결책은 아니다. 더 나은 해결책은 무엇일까?


연산(Computed) 프로퍼티

    <input type="text" v-model="name">
    <button v-on:click="resetInput">Reset Input</button>
    <p>Your Name: {{ fullName }}</p>
    
    computed: {
    fullName() {
      console.log('Running again...');
      if (this.name === '') {
        return '';
      }
      return this.name + ' ' + 'Lee';
     }
   },

computed

  • Vue에서 지원하는 주요 옵션 중 하나 (1.data, 2.method, 3.computed)
  • methods 처럼 객체를 값으로 가진다.
  • (기술적으로 메서드임에도 불구하고) 메서드가 아니라 데이터 프로퍼티처럼 사용된다.
    • 따라서, 데이터 프로퍼티처럼 작명한다.
  • 괄호 없이 입력해야 한다.
    • fullName (⭕️)
    • fullName() (❌)

methods와의 "차이점"

computed 프로퍼티에 사용된 뭔가를 변경해야만 해당 객체가 작동한다.

Vue는 computed 프로퍼티의 의존성을 인식(여기선 name에 의존하고 있다)한다. computed 프로퍼티 값을 캐시에 저장하고 의존성 중 하나, 이 경우 유일한 의존성인 name 프로퍼티가 변경된 경우에만 재계산하고 재평가한다.

성능 면에서 값을 출력하는 대부분의 경우 메서드보다 연산 프로퍼티 사용이 좋다. 페이지에서 어떤 항목이 변경되든 값을 재계산하려는 경우에만 메서드를 사용한다. 그러나 대부분의 경우에 의존성이 변경되는 경우에만 재계산하길 원할텐데, 이런 경우 computed를 사용할 수 있다.


감시자(Watcher)

    <input type="text" v-model="name">
    <button v-on:click="resetInput">Reset Input</button>
    <p>Your Name: {{ fullName }}</p>
    
    watch: {
    // name이 변경될때마다 watch가 재시행된다.
    name(value) {
      this.fullName = value + ' ' + 'Lee';
    }
  },

watch:

  • 의존성 중 하나가 변경될 때 Vue에 실행하도록 지시할 수 있는 함수.
    • computed와 유사하며 실제로 대신 사용할 수 있다.
  • 자동으로 watch 프로퍼티의 마지막 값을 파라미터로 가져온다.
    • (Vue에 의해 자동 전달)
  • 두 번째 인수는 watch 프로퍼티의 이전 값을 의미한다.
watch: {
	name(newValue, oldValue) {...}
}

computed 와의 차이점

🤔 거의 computed와 차이가 없다. 왜 두가지가 구분되어 있을까?

watcher 사용의 문제점은 두 개 이상의 요소에 의존성을 가지고 있는 경우 발생한다. 이번에는 "성"과 "이름" 모두에 반응하는 기능을 구현하려고 한다.

    <input type="text" v-model="name">
    <input type="text" v-model="lastName">
    <p>Your Name: {{ fullName }}</p>
    
    watch: {
    name(value) {
      if(value === '') {
        this.fullName = '';
      } else {
        this.fullName = value + ' ' + 'Lee';
      }
    },
    lastName(value) {
      if(value === '') {
        this.fullName = '';
      } else {
        this.fullName = this.name + ' ' + value;
      }
    }
  },

두 개 이상의 변수를 추적하면서 코드가 중복되는 모습을 보인다. 같은 기능을 computed로 구현해보면 어떻게 코드가 바뀔까?

  computed: {
    fullname() {
      if(this.name === '' || this.alstNAme === '') {
        return '';
      }
      return this.name + ' ' + this.lastName;
    }
  },

훨씬 간단해진 모습을 확인 할 수 있다.

🤔 성능이 computed가 좋다면 왜 watch가 존재하는 걸까?

이 같은 기능은 watch의 핵심 기능이 아니기 때문이다.
이번엔 counter가 50을 초과하면 재설정하는 기능을 구현해보자. 이런 종류의 작업에서 watch이 유용하다.

 watch: {
    counter(value) {
      if(value > 50) {
        this.counter = 0;
      }
    }
  },

데이터 프로퍼티를 업데이트하나 항상 업데이트해선 안되는 로직을 실행하려는 경우 computed보다 watch가 훨씬 유용할 수 있다.

또 다른 예로, "특정 데이터가 변경되면 보내는 HTTP 요청", "특정 값이 변경되면 설정하는 타이머"에도 watch가 유용할 수 있다.


메서드(methods) vs 연산(Computed) 프로퍼티 vs 감시자(Watch)

🙄 음.. methods.. computed... wat.. 너무 혼란서롭고 헷갈린다...
😀 간단하게 정리해보자!

methods

  • 템플릿에서 데이터를 바인딩할 때 혹은 이벤트 바인딩을 위해 사용
    • 템플릿에서 사용해야 하는 데이터를 가져오기 위해 사용.
    • ex. {{}} 보간법 사용등을 위함
  • 템플릿에서 Vue 인스턴스로 로직을 아웃소싱 하는 경우, 메서드는 컴포넌트의 리렌더링 주기에 맞춰 매번 실행된다.
    • 따라서, 변동사항이 생기면 템플릿을 재평가하고 해당 템플릿에 호출된 모든 메서드를 다시 호출한다.
  • 이벤트 바인딩에는 메서드를 주로 사용한다.
    • 역으로, 페이지 변동 사항 발생 시 마다 메서드가 재 실행되기를 원하는 경우, "데이터 바인딩 + 중괄호"를 사용할 수 있다!

computed

  • 데이터 바인딩에 사용 (이벤트 바인딩에는 사용하지 않는다.)
  • 다른 데이터를 기반으로 하는 데이터를 가져오기에 유용하다.
    • 의존하는 데이터가 바뀔 때에만 Vue에 의해 재평가하거나 재실행된다.
  • 따라서, 다른 데이터에 의존하는 데이터에 사용한다.

watch

  • 템플릿에 바로 사용하지 않는다.
  • computed 프로퍼티를 포함해 어느 프로퍼티든 감시 가능하다.
  • 데이터 변경에 대한 반응을 코드로 실행할 수 있다.
    • (HTTP 요청, 타이머 설정, 로컬 스토리지에 데이터 저장 작업 등등...)
  • 데이터가 아닌 업데이트에 사용해야 한다.
    • 변경되는 데이터를 토대로, 데이터가 아니라 업데이트 하는 작업이 있을 때 사용하면 좋다.

... 근데 정리를 해도 헷갈린다..ㅠㅠ


v-on, v-bind 축약어

v-on

  • v-on을 "@"로 대체할 수 있다.
    • v-on:click = @click

v-bind

  • v-bind를 ":"로 대체할 수 있다.
    • v-bind:value = :value

+) v-model은 축약어가 없다.

profile
Good Luck!

0개의 댓글

Powered by GraphCDN, the GraphQL CDN