vueJS에서 제공해주는 v-cloak 디렉티브에 대해 알아보자.

 

vueJS를 사용하자마자 눈에 거슬리는게 있는데, 이게 바로 머스태쉬 태그{{}} 이다.

script 코드가 아직 실행되기 전이여서 값이 바인딩 되기 전에 깜빡이며 잠깐 보이는건데 이게 매우 거슬린다.

 

이럴때 사용하는게 v-cloak 디렉티브이다.

v-cloak 디렉티브를 사용하여 렌더링되어 바인딩 되기 전에 {{}}태그를 숨길 수 있다.

 

예제 코드를 통해 사용방법에 대해 알아보고 vueJS를 사용하면서 거슬렸던 깜빡임을 제거해보자.


▷ 예제1) v-cloak 디렉티브 기본 사용법

<div id="example">
  <p>메시지: "{{ message }}"</p>
</div>
var vm = new Vue({
  el: '#example',
  data: {
    message: '안녕하세요'
  },
})

 

이렇게 간단하게 설정된 코드가 존재한다고 하면,

당연히 화면에서는 message값이 바인딩 되어 "안녕하세요"가 나오는게 정상이다.

 

허나, 그 바인딩 되는 과정에서 화면에는 흉측한 {{ message }} 코드가 보이게 된다.

 

▷ 결과 1 ) - 바인딩 되기 전

▷ 결과 2 ) - 바인딩 된 후 화면에 출력


여기서 이제 우리는 v-cloak 디렉티브를 사용할 것이다.

추가적으로 몇가지 작업을 해주자.

 

[v-cloak] { display: none; }
<div id="example" v-cloak>
  <p>메시지: "{{ message }}"</p>
</div>

 

▷ 결과 3 ) - 바인딩 된 다음에만 화면에 출력


css 에 v-cloak에 대한 display: none; 을 설정해주고, dom 태그 속성에 v-cloak을 걸어주면된다.

 

v-cloak 디렉티브에 대해 display: none;을 해줬는데 어째서 결과가 출력되냐면,

v-cloak 디렉티브는 vueJS의 처리가 완료되기 전까지는 존재하고 완료된 후에는 스스로 제거하기 때문이다.

 

즉, 바인딩 되기 이전 {{}}태그가 존재할때는 display:none의 효과를 받으면서 바인딩이 완료되면 스스로 사라지기 때문에 css 적용없이 그대로 보여지게 되는것이다.

 

vueJS 코드가 복잡하거나 시스템이 느린경우 v-cloak 디렉티브는 꼭 필수적으로 사용해주는 것이 좋아보인다.

반응형

vueJS의 기본 디렉티브 중 하나인 v-once에 대해 알아보자. 

 

제목처럼 v-once가 정적 디렉티브라 불리는 이유는 처음 한번만 렌더링을 수행하며, 그 이후 데이터가 변경되어도 그대로 유지되기 때문이다.

즉, 처음 렌더링 된 후 캐싱되도록 지정한다고 생각하면된다.

 

이러한 특성을 사용하여 정적 콘텐츠를 지정할 수 있다.

예제를 통해 실제 어떻게 적용되는지 알아보도록 하자.


▷ 예제1) v-once 기본 사용법

<div id="example">
  <p v-once>유지 메시지: "{{ message }}"</p>
  <p>변경 메시지: "{{ message }}"</p>
  <button @click="change()">내 블로그는 mine-it-record야</button>
</div>
var vm = new Vue({
  el: '#example',
  data: {
    message: '안녕하세요'
  },
  methods : {
    change : function(){
      this.message = '내 블로그는 mine-it-record야'
    }
  }
})

 

▷ 결과 1) 초기 출력


위 결과 1) 과 같이 출력된다고 할때 버튼을 클릭하면 message가 변경되도록 구성해 놓았다.

 

html 영역을 보면 유지 메시지에 v-once를 걸어두었는데, 이 때 버튼을 클릭하면 어떻게 될까?

다음 결과를 확인해보자.

 

▷ 결과 2) 버튼 클릭 후 출력


결과 2와 같이 v-once를 선언해둔 곳은 이후 값이 변경된다 하여도 처음 렌더링할때의 값을 유지한다.

상황에 따라 사용하면 매우 좋을것 같으나, 이러한 패턴을 남용하지 않는것을 권장한다.

 

아래 안내문구를 한번 읽어보고 마치도록하자.

다시 한번 강조하지만, 이러한 패턴을 남용하지 마세요. 이는 렌더링할 정적 컨텐츠가 굉장히 많은 경우에 편리하게 사용할 수는 있지만, 느리게 렌더링 되는 것을 인지하지 못할 정도라면 필수적이지 않습니다. -- 더해서, 이런 방식은 추후에 많은 혼란을 야기할 수 있습니다. 예를 들어, v-once에 친숙하지 않은 개발자이거나 실수로 놓치는 경우에 그들은 템플릿이 정상적으로 업데이트 되지 않는 문제에 대해서 많은 시간을 소비하게 될 수 있습니다.

 

참고 : https://kr.vuejs.org/v2/guide/components-edge-cases.html#v-once%EB%A5%BC-%EC%82%AC%EC%9A%A9%ED%95%98%EB%8A%94-%EC%A0%95%EC%A0%81-%EC%BB%B4%ED%8F%AC%EB%84%8C%ED%8A%B8

 

예외적인 상황들 — Vue.js

Vue.js - 프로그레시브 자바스크립트 프레임워크

kr.vuejs.org

반응형

vueJS에서 제공하는 computed와 watch 속성에 대해 알아보자.

 

왜 이 두가지를 동시에 다루냐면 서로 비슷한 특징을 가지고 있기도 하고,

처음 접할때도 둘을 비교하는 경우가 많았기 때문에 나 역시 같이 기록해두고자 한다.

 

역시 vueJS는 공식홈페이지가 너무 잘되어있기 때문에 예제를 그대로 가져와 사용해보고자 한다.


1. computed

<div id="example">
  <p>원본 메시지: "{{ message }}"</p>
  <p>역순으로 표시한 메시지: "{{ reversedMessage }}"</p>
</div>
var vm = new Vue({
  el: '#example',
  data: {
    message: '안녕하세요'
  },
  computed: {
    reversedMessage: function () {
      return this.message.split('').reverse().join('')
    }
  }
})

 

▷ 결과

원본 메시지: "안녕하세요"
역순으로 표시한 메시지: "요세하녕안"

 

이렇게 본다면 당연히 methods와의 차이점을 느낄수가 없는데,

나 역시 도대체 computed는 methods와 기능이 동일한데 왜 존재하며 왜 사용하는걸까? 라는 의문을 가졌었다.

 

computed와 methods의 차이점을 보며 computed의 특징을 알아보도록하자.

 

위 예제를 보면 computed에 reversedMessage를 선언해 놨는데, reversedMessage는 message에 의존하는 상태이다.

이게 무슨말이냐면 message의 값이 변경될때 마다 reversedMessage가 실행된다는 얘기다.

 

이쯤되면 의아한게 methods에서 선언해도 값이 바뀌면 실행되는거 아닌가? 라고 의문을 가질 수 있는데

여기서 computed가장 큰 특징속성의 캐싱이 나온다.

 

캐싱이라는 특징을 보기 위해 다시 코드를 살펴보자.

 

1-1 computed 캐싱

<div id="example">
  <p>computed: {{ computedCount }}</p>
  <p>method: {{ methodsCount() }}</p>
  <button @click='count1++'>computedCount</button>
  <button @click='count2++'>methodsCount</button>
</div>
var vm = new Vue({
  el: '#example',
  data: {
    count1 : 0,
    count2 : 0
  },
  computed: {
    computedCount: function () {
      console.log('computed 감지');
      return this.count1
    }
  },
  methods: {
     methodsCount: function () {
      console.log('methods 감지');
      return this.count2
    }
  }
})

 

이런식으로 되어있다면 결과가 어떻게 될까?

둘다 당연히 count를 정상적으로 뿌려주긴할텐데 console.log에 찍히는게 문제가 있다.

 

버튼을 각각 두번씩 눌러본다 하면 다음과 같은 결과가 나온다.

 

▷ 결과

 

어째서 이런 결과가 나오는걸까?

위에서 설명한것 처럼 computed 속성은 종속 대상을 따라 저장(캐싱) 되는 특징을 가지고 있어서 그렇다.

그래서 종속대상의 값이 변경되지 않는다면 다시 실행되는 경우가 없으며,

methods의 경우에는 종속관계가 아니기 때문에 vue에서 데이터가 바뀔때 마다 재렌더링이 되는데 그때마다 실행되는 것이다.

 

이게 코드가 길어지고 기능이 많아지면 성능에서 아주 큰 차이가 나게 될 것이다.

 

그리고 computed의 특징 중 자잘한 몇가지는

호출할 때 괄호()를 사용할 필요가 없다는것과, 파라미터를 받을수가 없다 라는 특징을 가지고있다.

 

1-2 computed getter/setter 함수

coumputed 속성은 기본적으로 getter 함수만 가지고 있으나, 필요에 따라 setter 함수를 만들어 사용할 수 있다.

잘 사용은 하지 않지만 필요한 경우에만 사용해 주도록 하자.

 

<div id="demo">
  <p>{{ fullName }}</p>
  <button @click='fullName="John Doe"'>change</button>
</div>
var vm = new Vue({
  el: '#demo',
  data: {
    firstName: 'Foo',
    lastName: 'Bar'
  },
  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]
      }
    }
  }
})

 

이때 동작 원리는 버튼을 클릭할 경우 fullName = 'John Doe'가 실행되는데

computed에서의 fullName에서 반응하여 set 메서드를 먼저 실행해 firstName 과 lastName을 설정하고

그 뒤에 get 메서드를 실행하여 fullName을 반환한다.


2. watch

<div id="demo">
  <p>{{ fullName }}</p>
  <button @click='firstName="John"'>change-firstName</button>
  <button @click='lastName="Doe"'>change-lastName</button>
</div>
var vm = new Vue({
  el: '#demo',
  data: {
    firstName: 'Foo',
    lastName: 'Bar',
    fullName: 'Foo Bar'
  },
  watch: {
    firstName: function (val) {
      console.log('change-firstName');
      this.fullName = val + ' ' + this.lastName
    },
    lastName: function (val) {
      console.log('change-lastName');
      this.fullName = this.firstName + ' ' + val
    }
  }
})

 

watch 속성은 이름 그대로 감시자같은 역할을 한다 생각하면 되는데 데이터 변경을 감지하여 실행되는 특징을 가지고 있다.

 

예제를 통해 작동 원리를 직접 살펴보자면 버튼 두개를 순서대로 눌러보면 다음과 같은 결과가 나온다.

 

▷ 결과

 

firstName 과 lastName이 변경될 때만 실행된 것을 확인할 수 있다.

그래서 사용방법은 예제와 마찬가지로 watch 안에 데이터명을 입력하여 데이터 변경 감지를 해서 처리를 해주면된다.


대부분의 경우 computed 속성을 많이 사용하며 watch는 많이 사용하는 추세는 아니다.

computed와 methods의 경우 파라미터가 있고 return을 굳이 해줄필요 없는 경우 methods를 사용하며 그 외의 것은 computed를 사용해주면 좋다.

 

참고 : https://kr.vuejs.org/v2/guide/computed.html

 

computed와 watch — Vue.js

Vue.js - 프로그레시브 자바스크립트 프레임워크

kr.vuejs.org

 

반응형

vueJs에서 checkbox를 사용하는 방법에 대해 알아보자.

 

checkbox를 쓸때는 checkbox에 값을 넣어두고 체크여부에 따라 값을 가져오고는 하는데

vueJs에서는 신기하게도 값을 알아서 넣어준다.

 

코드를 통해 접근해보자.

 

▷ html

<div id='app'>
  <input type="checkbox" v-model="arr" value="mine">mine
  <input type="checkbox" v-model="arr" value="it">it
  <input type="checkbox" v-model="arr" value="record">record
  <button @click='checkArr()'>check</button>
</div>

 

▷ script

new Vue({
    el: '#app',
    data: {
        arr : []
    },
    methods : {
      checkArr : function() {
        console.log(this.arr);
      }
    }
});

 

이런식으로 구성되어있다면 어떤식으로 작동할까?

일단 화면구성은 아래와 같다.

 

초기화면

 

이 상태의 화면에서 아래와 같이 몇개를 체크해보고 'check' 버튼을 눌러보자.

 

 

▶ 결과


저런식으로 v-model로 연결되어있는 배열에 차곡차곡 쌓이게 된다.

물론 선택한 순서대로 삽입되며 당연하게도 체크를 해제하게 되면 알아서 배열에서 빠져나간다.

 

vueJs에서 checkbox를 사용할때 이런식으로 하나의 배열을 바라보게 하여 v-model을 사용하게 되면 쓸데없이 jquery를 사용하여 체크된것들의 값들을 뽑아서 다시 넣어주는 불필요한 행위는 할 필요가 없다.

 

하나 주의할 점은 저 상태의 checkbox를 prop같은것을 통해 강제로 체크상태를 제어하게되면 값이 배열에 들어가질 않는다.

반응형

자주 보는 에러는 아니지만 한번 겪은김에 기록해둔다.

 

The "data" option should be a function that returns a per-instance value in component definitions

에러 내용을 살펴보면 대략 살펴보면 "데이터" 옵션을 함수로 선언하고 return을 통해 각 변수들을 반환하라는 의미로 보이는데 에러 뒷부분에 명시된것처럼 이 에러는 Vue.component 에서 발생하는 에러이다.

 

Vue에서 data 옵션을 선언하는 방법과 Vue.component에서 data 옵션을 선언하는 방식에 차이가 존재하는데

즉, Vue.component에서 data 옵션을 잘못 선언했을때 발생하는 에러라는 의미이다.


▷ 에러가 발생한 코드

Vue.component('mine-it', {
	data : { 
		test : 'hi'
	},
	methods: {} 
  } 
});

 

▷ 정상 코드

Vue.component('mine-it', {
	data() { 
		return { 
			test : 'hi'
		} 
	},
	methods: {} 
  } 
});
반응형

vueJS에서 여러 component를 자식으로 두고 페이지를 구성할 때 공통으로 사용하는걸 상위 컴포넌트에 두고, 하위 컴포넌트에서 이를 사용하게 되는 방식으로 구현을 하게 되는데,

이때 상위 컴포넌트와 하위 컴포넌트 간의 메서드에 접근하는 방법에 대해 알아보자.

 

예제는 inline-template을 기반으로 하였으며 이 template 사용법은 3.x 버전부터는 사용이 중지된것으로 알고있다.


▷ 예제1) inline-tempate example

<div id='it_list'>
     <mine-it inline-template ref='mint'>
        <ul>
          <li>mine</li>
          <li>it</li>
          <li>record</li>
          <button v-on:click="goParnet()">VueJS</button>
        </ul>
    </mine-it>
</div>
Vue.component('mine-it', {
  data() { 
    return { 
      test : 'hi'
    } 
  },
  methods: { 
    goParnet : function(){ 
     this.$parent.goChild();
    },
    hiParent : function() {
       alert(this.test); 
    }
  } 
});
  
  new Vue({
      el: '#it_list',
      data: {
      },
      methods: {
        goChild : function() {
          this.$refs.mint.hiParent();
        }
      }
  });

 

코드를 보면 알겠지만

this.$parentthis.$refs 가 사용되었는데

this.$parent는 말그대로 부모 즉, 상위 컴포넌트에 접근하는 방법이며

 

this.$refs는 자식 즉, 하위 컴포넌트에 접근하는 방법인데

inline-template 옆에 ref라고 명시해둔 것이 보일것이다. 그게 자식 component 각각의 고유이름이다.

($refs를 사용하지 않고 하위 컴포넌트에 접근할때 children을 사용해서 접근하는 방법도있다.)

 

이처럼 $parent와 $refs를 사용하여 부모/자식간 메소드에 접근이 가능하다.

반응형