계산된 속성과 감시자

계산된 속성(Computed Properties)



템플릿 내의 표현식은 단순한 연산에만 사용해야함
복잡해지면 유지보수가 어려워짐

예제

//HTML
<div id="example">
  <p>원본 메시지: "{{ message }}"</p>
  <p>뒤집히도록 계산된 메시지: "{{ reversedMessage }}"</p>
</div>
//JavaScript
var vm = new Vue({
  el: '#example',
  data: {
    message: '안녕하세요'
  },
  computed: {
    // 계산된 getter
    reversedMessage: function () {
      // `this` 는 vm 인스턴스를 가리킵니다.
      return this.message.split('').reverse().join('')
    }
  }
})

결과
원본 메시지: “안녕하세요” => “요세하녕안”
이때 계산된 속성  reversedMessage 를 선언
return 뒤의 제공되는 함수는  vm.reversedMessage 속성에 대한 getter 함수로 사용

이 때 getter 함수란 값을 반환하기 위해 사용되는 함수
setter 함수란 값을 입력하기 위해 사용되는 함수이다.

계산된 캐싱(Computed Caching) vs 메소드(Methods)

계산된 속성 대신 methods로 정의 가능, 두가지의 접근 방식은 서로 동일함
이때 차이점은 계산된 속성은 종속성에 따라 캐시된다
무슨말인지 알아보면
계산된 속성(computed)은 종속성 중 일부가 변경된 경우에만 다시 계산
위의 예에서  message 가 변경되지 않는 한,  reversedMessage 에 대한 다중 접근은 함수를 다시 수행할 필요 없이 이전에 계산된 결과를 즉시 반환함
만약 computed 안에 실시간으로 날짜를 나타내는 함수  Date.now() 를 넣는다면 업데이트 되지 않음!
하지만 methods 호출은 렌더링 할 때마다 항상 호출

-캐싱이 필요한 이유는?
캐싱하지 않으면 시간이 많이 소요되는 A 속성이 getter를 필요한 것보다 더 > 많이 실행하게 되어 불필요한 작업을 실행함.
따라서 캐싱이 필요하지 않을때는 methods를 사용

계산된 속성(Computed) vs 감시된 속성(Watched)

<div id="demo"> {{ fullName }} </div>
var vm = new Vue({
  el: '#demo',
  data: {
    firstName: 'Foo',
    lastName: 'Bar',
    fullName: 'Foo Bar'
  },
  watch: {
    firstName: function (val) {
      this.fullName = val + ' ' + this.lastName
    },
    lastName: function (val) {
      this.fullName = this.firstName + ' ' + val
    }
  }
})

위의 코드를 보면  firstName 과  lastName 의 코드가 중복되므로 효율적이지 못함
이때는 computed를 이용한다면 아래와 같이 한줄로 작성 가능해짐

var vm = new Vue({
  el: '#demo',
  data: {
    firstName: 'Foo',
    lastName: 'Bar'
  },
  computed: {
    fullName: function () {
      return this.firstName + ' ' + this.lastName
    }
  }
})

계산된 Setter

computed는 기본적으로 getter만 가지고 있지만 필요한 경우 setter를 제공함

// ...
computed: {
  fullName: {
    // getter
    get: function () {
      return this.firstName + ' ' + this.lastName
    },
    // setter
    set: function (newValue) {
      var names = newValue.split(' ')
      this.firstName = names[0]
      this.lastName = names[names.length - 1]
    }
  }
}
// ...

 vm.fullName = ‘take u’ 를 실행하면 set 의  firstName 과  lastName 이 재설정되며 get에의해 새로 출력됨

감시자(Watchers)



대부분은 computed가 더 적합하지만 일부는  watch 가 필요한 경우가 있음
데이터 변경에 대한 응답으로 비동기식 또는 시간이 많이 소요되는 조작을 수행할 때 사용

<div id="watch-example">
  <p>
    yes/no 질문을 물어보세요:
    <input v-model="question">
  </p>
  <p>{{ answer }}</p>
</div>
<!-- 이미 Ajax 라이브러리의 풍부한 생태계와 범용 유틸리티 메소드 컬렉션이 있기 떄문에, -->
<!-- Vue 코어는 다시 만들지 않아 작게 유지됩니다. -->
<!-- 이것은 또한 당신이 사용하기 친숙할 것을 선택할 수 있는 자유를 줍니다. -->
<script src="https://unpkg.com/axios@0.12.0/dist/axios.min.js"></script>
<script src="https://unpkg.com/lodash@4.13.1/lodash.min.js"></script>
<script>
var watchExampleVM = new Vue({
  el: '#watch-example',
  data: {
    question: '',
    answer: '질문을 하기 전까지는 대답할 수 없습니다.'
  },
  watch: {
    // 질문이 변경될 때 마다 이 기능이 실행됩니다.
    question: function (newQuestion) {
      this.answer = '입력을 기다리는 중...'
      this.getAnswer()
    }
  },
  methods: {
    // _.debounce는 lodash가 제공하는 기능으로
    // 특히 시간이 많이 소요되는 작업을 실행할 수 있는 빈도를 제한합니다.
    // 이 경우, 우리는 yesno.wtf/api 에 액세스 하는 빈도를 제한하고,
    // 사용자가 ajax요청을 하기 전에 타이핑을 완전히 마칠 때까지 기다리길 바랍니다.
    // _.debounce 함수(또는 이와 유사한 _.throttle)에 대한
    // 자세한 내용을 보려면 https://lodash.com/docs#debounce 를 방문하세요.
    getAnswer: _.debounce(
      function () {
        if (this.question.indexOf('?') === -1) {
          this.answer = '질문에는 일반적으로 물음표가 포함 됩니다. ;-)'
          return
        }
        this.answer = '생각중...'
        var vm = this
        axios.get('https://yesno.wtf/api')
          .then(function (response) {
            vm.answer = _.capitalize(response.data.answer)
          })
          .catch(function (error) {
            vm.answer = '에러! API 요청에 오류가 있습니다. ' + error
          })
      },
      // 사용자가 입력을 기다리는 시간(밀리세컨드) 입니다.
      500
    )
  }
})
</script>

예제 코드인데 결과를 어케띄우는지 모르겠당..
궁금하다면 https://kr.vuejs.org/v2/guide/computed.html#

아무튼 위의 코드에서  watch 의 사용으로
비동기 연산(API)을 수행하고,
우리가 그 연산을 얼마나 자주 수행하는지 제한하고,
최종 응답을 얻을 때까지 중간 상태를 설정

'개발 > Vue.js' 카테고리의 다른 글

6. 조건부 렌더링(v-if, v-else-if, v-else, v-show)  (0) 2017.03.30
5. 클래스와 스타일 바인딩(Class and Style Bindings)  (0) 2017.03.29
4. 계산된 속성과 감시자  (0) 2017.03.28
3. Vue 템플릿 문법  (0) 2017.03.27
2. Vue 인스턴스  (0) 2017.03.23
1. Vue.js 시작하기  (0) 2017.03.23

템플릿 문법

Vue.js는 렌더링 된 DOM을 기본 Vue 인스턴스의 데이터에 선언적으로 바인딩 할 수 있는 HTML 기반 템플릿 구문을 사용

내부적으로 Vue는 템플릿을 가상 DOM 렌더링 함수로 컴파일함
반응형 시스템과 결합된 Vue는 앱 상태가 변경 될 때 최소한으로 DOM을 조작하고
다시 적용할 수 있는 최소한의 컴포넌트를 지능적으로 파악할 수 있음

#보간법


문자열

바인딩의 가장 기본 형태는 Mustache({{ }})를 사용한 텍스트 보간

<span>메시지: {{ msg }}</span>

원시 HTML

<div v-html="msg"></div>

컨텐츠는 일반 HTML 형식으로 삽입

속성

HTML 내부의 값을 데이터로 하고싶은데
Mustaches는 HTML 속성으로 사용 불가 => v-bind 사용해야함

<img v-bind:src="image.jpg" />
<img :src="image.jpg" /> 
//v-bind생략가능

JavaScript 표현식

Vue.js는 모든 데이터 바인딩 내에서 JavaScript 표현식의 모든 기능을 지원함

{{ number + 2 }}
{{ ok ? 'YES' : 'NO }}
<div v-bind:id="'list-+' + id></div>

이때 변수선언이나 조건문을 넣으면 작동하지 않으니 유의할 것

#디렉티브


디렉티브란?

v- 접두사가 있는 특수 속성
디렉티브 속성 즉 v-뒤에 오는 값은 단일 JavaScript 표현식이 됨(v-for예외)

전달인자

일부 디렉티브는 콜론으로 표시되는 “전달인자”를 사용
<a v-bind:href="url"></a>
이때 href는 전달인자로 href속성을 url의 값에 바인드하는 v-bind에게 알려줌

수식어

점으로 표시되는 특수 접미사로 디렉티브를 특별한 방법으로 바인딩할때 사용
나중에 v-on, v-model을 볼때 다시 나오니 그 때 정리할 예정

#필터


일반 텍스트 서식을 적용할 때 사용 가능한 필터를 정의할 수 있음
Mustachesv-bind 두곳에서 사용 가능
파이프( | ) 기호로 표시

{{ message | capitalize }} // message의 내용을 capitalize 하겠다

필터를 통해 데이터 변환을 할 때는 계산된 속성을 사용해야함

여러 필터를 동시에 적용 가능함(체이닝)

{{ message | filterA | filterB }}

필터는 JS함수이므로 전달인자 사용 가능

#약어


v- 접두사는 Vue 특정 속성을 식별하기 위해 사용
가장 많이 쓰이는 v-bindv-on에 대해 특별한 약어 제공

v-bind약어

<a v-bind:href="url"></a>
<a :href="url"></a> // v-bind 생략가능

v-on약어

<a v-on:click="do"></a>
<a @click="do"></a> // v-on: 대신 @사용 가능


'개발 > Vue.js' 카테고리의 다른 글

5. 클래스와 스타일 바인딩(Class and Style Bindings)  (0) 2017.03.29
4. 계산된 속성과 감시자  (0) 2017.03.28
3. Vue 템플릿 문법  (0) 2017.03.27
2. Vue 인스턴스  (0) 2017.03.23
1. Vue.js 시작하기  (0) 2017.03.23
0. Vue.js 포스팅  (0) 2017.03.23

Vue 인스턴스


모든 Vue vm(ViewModel)은 Vue라는 생성자 함수로 만들게 된다.

var vm = new Vue({
    // 옵션
})

Vue 생성자는 미리 정의 된 옵션으로 재사용 가능한 컴포넌트 생성자를 생성하도록 확장 가능

컴포넌트란?

  • Vue의 가장 강력한 기능중 하나
  • 기본 HTML엘리먼트를 확장해 재사용이 가능한 코드를 캡슐화하는데 사용

나중에 컴포넌트에 대한 부분은 다시 나오니 그 때 자세히 알아보자

그러면 위에서 나온 인스턴스의 정의가 뭔가하고 찾아봤는데
자바(한번도 안해봄)에서 객체, 인스턴스 개념이 있다고 해서 읽어보니
Vue에서 사용되는 용어와 비슷하다 생각이 되어 적어봄

인스턴스(instance)란?
- 먼저 인스턴스를 설명하기 위해서는 객체가 무엇인지 먼저 알아야만 가능하다.
- 인스턴스는 객체를 생성하기 위해 만들어진 또 다른 객체를 바로 인스턴스(instance)라고 부른다
-인스턴스를 만들기 위해서는 객체지향에서 말하는 클래스(Class)가 필요하다.

  • 클래스는 객체지향언어에서 가장 중요한 부분 중 하나라 다른 객체를 만드는 틀이라고 생각하면된다.
  • 자바스크립트는 객체지향언어이지만 클래스가 아닌 프로토타입 방식의 객체지향언어이다.
  • 인스턴스를 만드는 방법은 다르지만 인스턴스를 만든다는 것은 동일하다.

    이렇게 만들어진 인스턴스는 어떤 특징을 가지고 있을까?

  • 가장 기본적으로 원래의 객체가 가지고 있는 프로퍼티(property)와 메소드(method)를 상속받는다.

상속(inheritence)
- 객체지향에서 가장 중요한 부분이 상속이다. 상속을 통해 객체가 가지고 있는 프로퍼티와 메소드를 인스턴스에서도 동일하게 사용이 가능
- 인스턴스는 기존 객체에서 확장돼 다른 개별 속성들을 가질 수도 있을 것이다.

// 객체를 만들기 위한 생성자함수(Class)를 생성함
Shirt = function(color) {
   this.color = color;
}


var Shirt1 = new Shirt('Yellow');
// 위 과정을 통해 Shirt1이란 인스턴스가 생성됨

var Shirt2 = new Shirt('white');
var Shirt3 = new Shirt('blue');
...
// 수 많은 인스턴스를 생성할 수 있음

위의 예제로 개념을 이해하는데 큰 도움이 된 것 같다!

그럼 Vue에서 위의 개념을 적용시켜 컴포넌트 생성자와 인스턴스를 설명한 코드를 보면 다음과 같다.

var MyComponent = Vue.extend({
  // 옵션 확장
})

// `MyComponent`의 모든 인스턴스는
// 미리 정의된 확장 옵션과 함께 생성됩니다.
var myComponentInstance = new MyComponent()

속성과 메소드

각 Vue 인스턴스는 data 객체에 있는 모든 속성을 프록시 처리한다.

여기서 프록시란?
내가 이해한 바로는 속성을 받아와서 그대로 쓸수있게 해준다는 의미같다.

아래 코드로 이해해보자

var data = { a: 1 }
var vm = new Vue({
  data: data
})
vm.a === data.a // -> true
// 속성 설정은 원본 데이터에도 영향을 미칩니다.
vm.a = 2
data.a // -> 2

// ... 당연하게도
data.a = 3
vm.a // -> 3

이러한 프록시 속성은 반응형인데 나중에 다시 나온다고한다.

이때 인스턴스는 데이터 속성 이외에도 유용한 인스턴스 속성, 메소드 를 제공하는데 이는 접두사 $ 를 붙여 사용한다고 한다

아래 코드로 이해해보자

var data = { a: 1 }
var vm = new Vue({
  el: '#example',
  data: data
})

vm.$data === data // -> true
vm.$el === document.getElementById('example') // -> true

// $watch 는 인스턴스 메소드로 data에 따로 정의되지 않은 메소드
vm.$watch('a', function (newVal, oldVal) {
  // `vm.a`가 변경되면 호출
})

인스턴스 속성이나 콜백에서 화살표 함수(Arrow function) 사용하면 안됨
잘못된 예 - vm.$watch(‘a’, newVal => this.myMethod())
화살표 함수는 부모 컨텍스트에 바인딩 되어 있으므로 this는 Vue 인스턴스가 아니며
this. myMethod 는 정의되지 않는다.

인스턴스 라이프사이클 훅

  • Vue 인스턴스가 하는일
    1. 데이터 관찰 설정
    2. 템플릿 컴파일
    3. 인스턴스를 DOM에 마운트
    4. 데이터가 변경될 때, DOM을 업데이트해야 할 때 초기화 단계를 거침

이때 라이프사이클 훅이 호출!

 var vm = new Vue({
  data: {
    a: 1
  },
  created: function () {
    // `this` 는 vm 인스턴스를 가리킵니다.
    console.log('a is: ' + this.a)
  }
})
// -> "a is: 1"

위의 코드로 이해해 보자
위에서 created 훅은 인스턴스 생성 후 호출

아래는 Vue.js의 라이프사이클이다

인스턴스에 대한 정의 끝!

사실 막 와닿진 않지만 뒤로 넘어가면서 쭉 보면 알듯 싶음

'개발 > Vue.js' 카테고리의 다른 글

5. 클래스와 스타일 바인딩(Class and Style Bindings)  (0) 2017.03.29
4. 계산된 속성과 감시자  (0) 2017.03.28
3. Vue 템플릿 문법  (0) 2017.03.27
2. Vue 인스턴스  (0) 2017.03.23
1. Vue.js 시작하기  (0) 2017.03.23
0. Vue.js 포스팅  (0) 2017.03.23

+ Recent posts