Vue Template Syntax - 보간법, 디렉티브

  1. Vue는 렌더링된 DOM과 바인딩할 수 있는 HTML 친화적인 템플릿 구문을 사용
  2. HTML 처럼 보이지만 내부적으로는 Javascript 파싱되어 순수 js 객체로 관리 된다.
  3. 작성된 템플릿 구문은 Vue app을 통해 이벤트 및 반응성 처리를 지원
  4. 또한 DOM의 변경을 최소한으로 수행하기 위해 Virtual DOM으로 구성됨

참고 : https://ko.vuejs.org/guide/essentials/template-syntax

보간법 (Text Interpolation)

  1. Text Interpolation(보간법)
  • 콧수엽(Mustache)문법을 통해 반응형으로 vue에 선언된 data를 출력한다.
  • 출력된 값은 escape 처리 되어 XSS에 안전하게 어플리케이션을 보호한다.
  1. JavaScript Expressions
  • JS 문법을 표현식으로 처리할수 있다.
  • document.write(‘this!’) this에 들어갈수 있는 문법만 적용 가능
  • 순수 문자열, 삼항연산자, 초기화 구문, 함수 등이 사용 될 수 있다.
<script setup>
import { ref } from 'vue';

const number = ref(5);
const message = ref('Hello vue world!');
const id = ref('test');
const myFunc = ref(() => 'myFunc Test!');
</script>

<template>
  <div>
    {{ number + 5 }} <br />
    {{ null ? 'null 입니다' : 'null이 아닙니다' }} <br />
    {{ null || '초기화 문장입니다' }} <br />
    {{ message.split('').reverse().join('') }}<br />
    <div :id="`list-${id}`"></div>
    {{ myFunc() }}
  </div>
</template>

디렉티브(Directives)

  1. HTML 요소에 특수한 동작을 추가하는 템플릿 전용 속성(Attribute)이다.
  2. v- 접두사를 사용하며, Vue의 반응형 시스템과 결합하여 동적인 동작을 수행할 수 있다.
  3. 주로 속성 바인딩, 양방향 바인딩 또는 분기문, 반복문 등을 표현할 때 활용 된다.

v-bind (Attribute Bindings)

  1. vue에서 속성 값을 바인딩 하기 위해 활용되는 문법
  2. 모든 속성값(id, class, type, value …)이 바인딩 될수 있음
  3. v-bind:value=”~~~“와 같이 속성값 앞에 문법을 활용
  4. Shorthand 문법지원
  • bind 생략 후 ’:‘만 사용
  • 속성값과 같은 이름 생략하여 ‘:width’만 사용
<script setup>
import { ref } from 'vue';
const message = ref('v-bind 디렉티브');
const imagePath = ref(
  'https://www.google.com/images/branding/googlelogo/1x/googlelogo_color_272x92dp.png',
);
const url = ref('https://www.google.com/images/branding/googlelogo/1x/');
const filename = ref('googlelogo_color_272x92dp.png');
const width = ref('200px');
const isButtonDisabled = ref(true);
const objectOfAttrs = ref({
  id: 'container',
  class: 'wrapper',
  style: 'background-color:green',
});
</script>

<template>
  <input type="text" v-bind:value="message" />

  <!-- Shorthand 문법, ':'만 활용, :width, 속성이름과 같은면 대체 -->
  <input type="text" :value="message" />
  <img :src="imagePath" />
  <img :src="imagePath" :width="width" />

  <!-- width는 이름이 같아서 생략 가능-->
  <img :src="imagePath" :width />

  <!-- v-bind 내에서 문자열을 조합하는 방법 -->
  <img :src="url + filename" :width />
  <img :src="`${url}${filename}`" :width />

  <!-- boolean 적용 방법 -->
  <button :disabled="isButtonDisabled">Button</button>

  <!--objectOfAttrs에 다수의 속성값을 한번에 적용하는 문법-->
  <div v-bind="objectOfAttrs">복합속성 적용</div>
</template>

v-model (component two-way binding)

  1. 사용자 입력을 받는 폼(form) 엘리먼트 또는 컴포넌트에 양방향 바인딩을 만드는 디렉티브
  2. 이벤트를 통해 변경된 값을 감지하여 vue(VDOM) 내부 변수와 양방향 바인딩
  3. input, select, textarea 그리고 사용자 컴포넌트에서만 활용 가능하다.

참고 : https://ko.vuejs.org/guide/essentials/forms.html

checkBox

<script setup>
import { ref } from 'vue';

const hobby = ref(['A', 'B']);
</script>

<template>
  <input type="checkbox" id="hobbyA" value="A" v-model="hobby" />
  <label for="hobbyA">운동</label>

  <input type="checkbox" id="hobbyB" value="B" v-model="hobby" />
  <label for="hobbyB">독서</label>

  <input type="checkbox" id="hobbyC" value="C" v-model="hobby" />
  <label for="hobbyC">영화보기</label>

  선택된 취미 : {{ hobby.sort() }}
</template>

select

<script setup>
import { ref } from 'vue';

const category = ref('');
</script>

<template>
  <select v-model="category">
    <option value="">-- 상품 분류 선택 --</option>
    <option value="C01">레저</option>
    <option value="C02">가전</option>
    <option value="C03">음식</option>
    <option value="C04">도서</option>
  </select>
  선택된 상품 분류 : {{ category }} <br />
</template>

true-value, false-value 속성

<script setup>
import { ref } from 'vue';

const agree = ref('no');
</script>

<template>
  위의 내용에 동의하십니까?
  <input type="checkbox" v-model="agree" true-value="yes" false-value="no" />
</template>
  • 체크박스를 클릭하면 agree의 값이 바뀜

Modifiers

  1. event가 감지된 이후 적용할 값에 대한 후처리 기능도 지원
  2. number: 입력시 number타입으로 자동형변환
  3. trim: 문자열의 앞뒤 문자열 제거
  4. lazy: 포커스가 이동하는 이벤트 발생시 데이터 동기화
<script setup>
import { ref } from 'vue';

const agree = ref('no');
</script>

<template>
  //숫자 변환
  <input type="text" v-model.number="num" />
  number : {{ num * 10 }}

  // 자동 trim 변환
  <input type="text" v-model.trim="trimStr" />
  trimStr : {{ trimStr }}

  // lazy 연동(포커스 벗어나면 업데이트)
  <input type="text" v-model.lazy="msg" />
  msg : {{ msg }}
</template>

Conditional Rendering

  1. 제어문의 조건문으로 조건이 일치할 경우 동작
  2. v-if는 값이 없을때 보이지 않도록 하는 필터링 문으로도 많이 활용

참고 : https://ko.vuejs.org/guide/essentials/conditional.html

조건문 - if, else-if, else

<script setup>
import { ref } from 'vue';

const text = ref('Hello vue world!');
const nullValue = ref(null);
const balance = ref(0);
</script>

<template>
  <!-- 텍스트가 있으면 출력하거나 없으면 출력하지 않는 문장 -->
  text : <span v-if="text">{{ text }}</span>

  nullValue: <span v-if="nullValue">{{ nullValue }}</span>

  잔고: <input type="text" v-model="balance" />

  회원님의 등급 :
  <span v-if="balance >= 1000000">Gold</span>
  <span v-else-if="balance >= 500000">Silver</span>
  <span v-else-if="balance >= 200000">Bronze</span>
  <span v-else>Iron</span>
</template>

v-for (list Rendering)

  1. 엘리먼트 또는 템플릿 블록을 반복하여 렌더링 할 때 list로 표현하는 디렉티브
  2. 또한 반드시 key를 적용 해야 하며, 이는 렌더링 시 최적화를 위해 활용된다.
<script setup>
import { ref } from 'vue';

const names = ref(['홍길동', '김길동', '박길동']);

const regions = ref({
  A: 'Asia',
  B: 'America',
  C: 'Europe',
  D: 'Africa',
  E: 'Oceania',
});
</script>

<template>
  <span v-for="(item, index) in names" :key="index">{{ `${index} ${item}` }}, </span>

  <!-- 객체 반복하는 방법 -->
  <ul>
    <li v-for="(item, key, index) in regions" :key="index">{{ `${key}: ${item}` }}</li>
  </ul>
</template>

v-on (이벤트 연결)

  1. 이벤트 리스너를 특정 메소드로 바인딩하거나 익명함수를 통해 즉시 구현 가능 디렉티브
  2. @ 단축 문법 사용 가능하여 @을 통해 축약하는 것이 일반적

참고 : https://ko.vuejs.org/api/built-in-directives#v-on

Vue 이벤트 핸들링

<script setup>
import { ref } from 'vue';
// 이벤트 핸들러 함수
const doThis = () => {
  alert('doThis 실행! ');
};
const doThat = (message, event) => {
  alert(`doThat 실행! 메시지: ${message}, 이벤트 타입: ${event.type}`);
};
const onEnter = () => {
  alert('Enter 키가 눌렸습니다!');
};
const count = ref(0);

const increment = () => {
  count.value++;
};
// 동적 이벤트 이름
const event = ref('click');
</script>

<template>
  <!-- @으로 사용하는 것이 정석 -->
  <button @click="doThis">매서드 핸들러 실행</button>

  <!-- 동적 이벤트 -->
  <button v-on:[event]="doThis">동적 이벤트</button>

  <!-- 인라인 표현식 -->
  <button @click="doThat(`hello`, $event)">인라인 표현식</button>

  <!-- 단축 문법 -->
  <button @click="doThis">단축 문법</button>

  <!-- 단축 문법 동적 이벤트 -->
  <button @[event]="doThis">단축 문법 동적 이벤트</button>

  <!-- 전파 중지 -->
  <button @click.stop="doThis">전파 중지</button>

  <!-- 키 별칭을 수식어로 사용 -->
  <input type="text" @keyup.enter="onEnter" placeholder="Enter를 눌러보세요!" name="" id="" />

  <!-- 클릭 이벤트 단 한 번만 트리거 -->
  <button @click.once="doThis">클릭 이벤트 한번만 실행</button>
</template>

이벤트 처리 방식

  1. 인라인 처리, 함수 분리, 인라인 함수 처리로 처리 가능
<script setup>
import { ref } from 'vue';

const count = ref(0);

const increment = () => {
  count.value++;
};
</script>

<template>
  <!-- 인라인 처리 -->
  <button @click="count++">count: {{ count }}</button>

  <!-- 함수 분리 -->
  <button @click="increment">count : {{ count }}</button>

  <!-- 인라인 함수 처리 -->
  <button @click="(e) => count++">count: {{ count }}</button>
</template>