👨🏻💻
Day 53 Vue Template Syntax - 보간법, 디렉티브
February 12, 2025
Vue Template Syntax - 보간법, 디렉티브
- Vue는 렌더링된 DOM과 바인딩할 수 있는 HTML 친화적인 템플릿 구문을 사용
- HTML 처럼 보이지만 내부적으로는 Javascript 파싱되어 순수 js 객체로 관리 된다.
- 작성된 템플릿 구문은 Vue app을 통해 이벤트 및 반응성 처리를 지원
- 또한 DOM의 변경을 최소한으로 수행하기 위해 Virtual DOM으로 구성됨
참고 : https://ko.vuejs.org/guide/essentials/template-syntax
보간법 (Text Interpolation)
- Text Interpolation(보간법)
- 콧수엽(Mustache)문법을 통해 반응형으로 vue에 선언된 data를 출력한다.
- 출력된 값은 escape 처리 되어 XSS에 안전하게 어플리케이션을 보호한다.
- 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)
- HTML 요소에 특수한 동작을 추가하는 템플릿 전용 속성(Attribute)이다.
- v- 접두사를 사용하며, Vue의 반응형 시스템과 결합하여 동적인 동작을 수행할 수 있다.
- 주로 속성 바인딩, 양방향 바인딩 또는 분기문, 반복문 등을 표현할 때 활용 된다.
v-bind (Attribute Bindings)
- vue에서 속성 값을 바인딩 하기 위해 활용되는 문법
- 모든 속성값(id, class, type, value …)이 바인딩 될수 있음
- v-bind:value=”~~~“와 같이 속성값 앞에 문법을 활용
- 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)
- 사용자 입력을 받는 폼(form) 엘리먼트 또는 컴포넌트에 양방향 바인딩을 만드는 디렉티브
- 이벤트를 통해 변경된 값을 감지하여 vue(VDOM) 내부 변수와 양방향 바인딩
- 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
- event가 감지된 이후 적용할 값에 대한 후처리 기능도 지원
- number: 입력시 number타입으로 자동형변환
- trim: 문자열의 앞뒤 문자열 제거
- 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
- 제어문의 조건문으로 조건이 일치할 경우 동작
- 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)
- 엘리먼트 또는 템플릿 블록을 반복하여 렌더링 할 때 list로 표현하는 디렉티브
- 또한 반드시 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 (이벤트 연결)
- 이벤트 리스너를 특정 메소드로 바인딩하거나 익명함수를 통해 즉시 구현 가능 디렉티브
- @ 단축 문법 사용 가능하여 @을 통해 축약하는 것이 일반적
참고 : 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>이벤트 처리 방식
- 인라인 처리, 함수 분리, 인라인 함수 처리로 처리 가능
<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>