
<style>
.active {
color: red;
}
.title--small {
font-size: 40px;
}
.color--orange {
color: orange;
}
</style>
<div id="app">
<button @click="toggle">Toggle</button>
<h1 :class="{ active, 'title--small color--orange':small}" class="title">{{ msg }}</h1>
</div>
<script>
const App = {
data() {
return {
msg: 'Hello Vue!',
active: false,
small:true,
}
},
active:active 는 active로 생략가능
title—small은 html표기법으로, 'title—small': small 으로 해줘야함
'title--small color--orange':small'' 처럼 안에서는 띄어쓰기로 여러개의 클래스 사용가능
<h1 :class="{ active, 'title--small color--orange':small}" class="title">{{ msg }}</h1>
return {
msg: 'Hello Vue!',
active: false,
small:true,
classObject: {
active: false,
'title--small color--orange': true
}
}
},
methods: {
toggle() {
this.active = !this.active
this.small = !this.small
}
}
}
<h1 :class="classObject" class="title">{{ msg }}</h1>
return {
msg: 'Hello Vue!',
classObject: {
active: false,
'title--small color--orange': true
}
}
classObject로 묶어서 사용 가능
return {
msg: 'Hello Vue!',
active: false,
small:true,
}
},
computed: {
classObject: {
active: this.active,
'title--small color--orange': this.small
}
},
methods: {
toggle() {
this.active = !this.active
this.small = !this.small
}
}
}
반응형 데이터로 활용하려면 computed로 계산된 데이터로 만들어줘야함
<h1 :class="[active, title]">Hello Vue!</h1>
대괄호를 이용해 2가지 class 적용
<h1 *v-if*="isShow">Hello Vue!</h1>, <h2 *v-else*>Good Morning~</h2> 연결가능
<template v-else-if="[]">
<h2>Hi</h2>
</template>
template 요소는 html에서 보이지 않고 컨테이너로 묶을 수 있음
v-show 디렉티브는 display: none 속성을 다룸
v-if="false" or "true" 를 통해 화면표기를 다루면 <!—v-if—>으로 구조적으로 없앰
따라서 v-if는 초기렌더링 비용이 낮은 반면 전환비용이 높고, v-show는 그의 역을 가짐
일반적으로는 v-if를 작성하며 v-show를 사용할 땐 v-cloak디렉티브, [v-cloak] { display: none;} 을 사용하는 것을 권장
※ v-clock: 연결된 인스턴스의 컴파일이 완료되기 전까지 존재하며, 생성되면 사라짐
v-if의 실행 우선순위가 v-for의 우선순위보다 높기 때문에 v-if는 v-for 범위의 변수에 접근하지 못한다. 즉, v-if와 v-for 는 같은 동시에 사용하면 안되며, 사용하려면 template를 통해 분리하여야 한다.
<li v-for="(item, index) in items"> {{ parentMsg }} - {{ index }} - {{item.msg }} </li> item과 index는 원하는 인자이름으로 사용 가능
<li v-for="value in myObject">{{ value }}</li> myObject라는 객체의 값을 가져온다.
<li v-for="(value, name, index) in myObject">{{index}}. {{ name }} :{{ value }}</li>
<span v-for="n in 10">{{ n }} </span> : 12345678910
❗v-for의 렌더링은 데이터 순서가 바뀔 때 DOM요소를 항목의 순서대로 이동시키지 않고, 각 요소를 적절한 위치에 패치하고 해당 인덱스에서 렌더링할 내용을 반영하는지 확인한다.
따라서 v-for를 사용할 때에는 key를 통해 고유값을 추가하는 것이 권장된다.
❗ v-for 객체의 index는 객체를 반복할 때 순서는 Object.keys()의 순서대로 결정되며, 자바스크립트 엔진과 일관적이지 않기 때문에 사용시 주의를 요하며, 반복순서 정도로만 사용하는 것을 권장한다.
<div id="app">
<form @submit="addNewTodo">
<label for="new-todo">Add a todo</label>
<input v-model="newTodoText"
id="new-todo"
placeholder="E.g. Feed a cat">
<button>Add</button>
</form>
<ul>
<todo-item v-for="todo in todos"
:key="todo.id"
:todo="todo"
@remove="removeTodo" />
<!-- @romove를 통해 $emit으로 정의했던 removeTodo 함수를 받는다. -->
</ul>
</div>
<script>
function generateId() {
return `${Date.now()}${Math.random()}`
}
const TodoItem = {
template: `
<li >
{{ todo.title }}
<button @click="$emit('remove', todo.id)">Remove</button>
</li>
`,
props: ['todo'] // 컴포넌트 밖에서 todo 데이터를 받는다.
}
const App = {
components: {
TodoItem
},
data () {
return {
newTodoText: '',
todos: []
}
},
methods: {
addNewTodo(e) {
e.preventDefault()
this.todos.push({
id: generateId(),
title: this.newTodoText
})
this.newTodoText = ''
console.log(this.todos);
},
removeTodo(todoId) {
this.todos = this.todos.filter(todo => {
return todo.id !== todoId
})
}
}
}
const vm = Vue.createApp(App).mount('#app')
<button @click="$emit('remove(사용자정의함수)', todo.id)">Button</button>
@click시, $emit으로 todo.id값을 사용자정의함수에 담아 보낸다.
todo-item의 @remove="removeTodo"으로 @click 이벤트와 $emit했던 todo.id값을 받는다.
<h1 @click="say('Hello~', $event)">{{ msg }}</h1>
say(*message*, *event*) { console.log(message); console.log(event); }
$event로 event를 받을 수 있다.
<h1 @click="a(), b(), c()"> ... </h1> or <h1 @click="a(); b(); c();"> ... </h1>
event.preventDefault() 또는 event.stopPropagation() 대신 Vue의 이벤트 수식어 사용가능
<a href="https://google.com" target="_blank" @click.prevent="method">Google</a>
@click.prevnet="" 은 @click.prevent 으로 줄일 수 있음
@click.stop : event.stopPropagation() 의 역할로 이벤트 버블링 정지@submit.prevent : event.preventDefault() 의 역할.once 한번만 동작.capture 하위 이벤트 실행시, capture가 있는 최상위 개체부터 하위 이벤트까지 내려오며 각각 실행되며, capture 수식어가 있는 디렉티브에서만 실행된다..self event.currentTarget는 이벤트가 연결된 곳, evnet.target은 이벤트를 실행한 곳인데, .self는 이벤트가 연결된 곳과 실행된 곳이 같아야 실행된다..passive 화면의 렌더링과 로직의 동작처리를 분리시켜서 사용경험을 높임@keydown.meta : 윈도우키 혹은 맥의 command키, keyup에서는 실행되지 않음
<input @keyup.alt.enter="clear" /> alt+enter 같이 체이닝가능
@keydown.arrow-down.exact 다른 키를 같이 누르면 동작하지 않음
@click.middle.exact 휠클릭과 다른 키를 같이 누르면 동작하지 않음
<h1>{{ msg }}</h1>
<input type="text"
:value="msg"
@input="msg = $event.target.value" />
<input type="text" v-model="msg" />
인풋의 값으로 msg값이 변하고, 변화된 msg가 <h1>으로 업데이트된다.
:value="msg" @input="msg = $event.target.value"을 v-model="msg"으로 단축할 수 있다.
v-model은 text, 체크박스, Select태그별로 달라지는 이벤트를 통합하여 신경쓰지 않아도 된다.
주의할점은 v-model은 IME(문자조합 ex 한글자모결합) 중 v-model이 업데이트되지 않으며, input type의 속성값보다 v-model의 데이터를 우선한다.
textarea에서 v-model 사용시 style="white-space: pre-line;을 넣어줘야 줄바꿈 된다.
<textarea v-model="msg" @change="log"></textarea>
<h1 style="white-space: pre-line;">{{ msg }}</h1>
<div id="app">
<input type="checkbox" value="떡볶이" v-model="checked" />
<input type="checkbox" value="라볶이" v-model="checked" />
<input type="checkbox" value="계란튀김" v-model="checked" />
</div>
<script>
const App = {
data() {
return {
checked: []
}
},
watch: {
checked(newValue) {
console.log(newValue);
}
}
}
// <input type="radio" v-model="picked" value="연어덮밥" /> ,
// picked: '', picked(newValue) { console.log(newValue); }
v-model의 checked 값을 빈배열 []으로 넣으면 어떤 checkbox에 체크했는지 알 수 있다.
비슷한 방식으로 ratio는 단일선택이므로 picked 값을 빈값 ''으로 넣으면 어떤 ratio에 체크했는지 알 수 있으며, select 는 v-model="selected", selected: ''으로 사용할 수있다.
<input v-model.lazy="msg">일 때 input 대신 change 이후 동기화된다.