html 제외하고 모두 import해서 사용 가능
script
export default{
data(){
return {
//여기에서 선언한 값들은 모두 그냥 변수가 아니라 reactive state
//reactive : state that can trigger updates when changed
//data component 안에서 사용된다
}
}
}
template
<h1>{{ message }}</h1>
<h1>{{ message.split('').reverse().join('') }}</h1>
{{}} 안에 사용할 수 있는 것들
cf. directive
v-접두사를 가진 특별한 속성
Vue의 template 문법
text interpolation({{}})와 마찬가지로 컴포넌트의 상태에 접근할 수 있는 자바스크립트 문법들
ex. v-bind, v-for 등
<script>
export default {
data() {
return {
titleClass: 'title'
}
}
}
</script>
<template>
<h1 :class="title">Make me red</h1>
<!-- add dynamic class binding here -->
<h1 class='name'>
name
</h1>
</template>
<style>
.title {
color: red;
}
.name{
color: blue;
}
</style>
v-on:event ="method이름"
@event="method이름"
click의 경우 아래 둘 다 가능
<button v-on:click="increment">{{ count }}</button>
<button @click="increment">{{ count }}</button
이렇게 method함수들은 script 태그 안의 export default{}안의 methods:{}를 사용한다
methods안에 정의한 함수들은 this를 이용해 data 안에 정의한 값들에 접근한다
export default {
data() {
return {
count: 0
}
},
methods: {
increment() {
// update component state
this.count++
}
}
}
<h1 v-if="awesome">Vue is awesome!</h1>
will be rendered only if the value of awesome is truthy.
If awesome changes to a falsy value, it will be removed from the DOM.
We can also use v-else and v-else-if to denote other branches of the condition:
<script>
export default {
data() {
return {
awesome: true
}
},
methods: {
toggle() {
this.awesome = !this.awesome
}
}
}
</script>
<template>
<button @click="toggle">toggle</button>
<h1 v-if="awesome">Vue is awesome!</h1>
<h1 v-else>Oh no 😢</h1>
</template>
<ul>
<li v-for="todo in todos" :key="todo.id"> //unique id, binded with key attribute(v-bind:key)
{{ todo.text }}
</li>
</ul>
how to update the list
this.todos.push(newTodo)
this.todos = this.todos.filter(~)
<script>
let id = 0
export default {
data() {
return {
newTodo: '',
hideCompleted: false,
todos: [
{ id: id++, text: 'Learn HTML', done: true },
{ id: id++, text: 'Learn JavaScript', done: true },
{ id: id++, text: 'Learn Vue', done: false }
]
}
},
computed: {
filteredTodos(){
return this.hideCompleted?
this.todos :
this.todos.filter(el => el.done === false)
}
},
methods: {
addTodo() {
this.todos.push({ id: id++, text: this.newTodo, done: false })
this.newTodo = ''
},
removeTodo(todo) {
this.todos = this.todos.filter((t) => t !== todo)
}
}
}
</script>
<template>
<form @submit.prevent="addTodo">
<input v-model="newTodo" />
<button>Add Todo</button>
</form>
<ul>
<li v-for="todo in filteredTodos" :key="todo.id">
<input type="checkbox" v-model="todo.done">
<span :class="{ done: todo.done }">{{ todo.text }}</span>
<button @click="removeTodo(todo)">X</button>
</li>
</ul>
<button @click="hideCompleted = !hideCompleted">
{{ hideCompleted ? 'Show all' : 'Hide completed' }}
</button>
</template>
<style>
.done {
text-decoration: line-through;
}
</style>
두 코드 모두 구조가 비슷하지만
Vue는 DOM의 업데이트를 다 알아서 해준다.
하지만 직접 조작해야 하는 경우도 있다
이때는 template에서 ref를 써주면 된다
이는 html 코드에 대해 참조한다
script에서는 this.$refs.태그이름 으로 접근할 수 있다
하지만 앱이 mount가 된 다음에 접근할 수 있다
그리고 위처럼 접근하기 위해서는 script내에서 mounted(){}를 통해 접근해야 한다
이를 lifecycle hook라고 한다. 이는 컴포넌트의 특정한 라이프사이클에서 콜백 함수를 등록할 수 있게 한다. created, updated 같은 다른 hook들도 있다
<script>
export default {
mounted(){
this.$refs.p.textContent = 'this'
}
}
</script>
<template>
<p ref="p">hello</p>
</template>
side effect(순수 함수 외의 동작들)에 반응해야 할 때 사용한다
trigger a function whenever a reactive property changes
export default {
data() {
return {
count: 0
}
},
watch: {
count(newCount) {
// yes, console.log() is a side effect
// count라는 reactive property에 대한 함수
console.log(`new count is: ${newCount}`)
}
}
}
<script>
export default {
data() {
return {
todoId: 1,
todoData: null
}
},
methods: {
async fetchData() {
this.todoData = null
const res = await fetch(
`https://jsonplaceholder.typicode.com/todos/${this.todoId}`
)
this.todoData = await res.json()
}
},
watch: {
todoId(newId){
//todoId를 가지고 이에 맞는 todo를 가져온다
//newId에 바뀐 todoId가 들어간다
//또 mount할 때만 fetchData해오니까 여기서도
~~ this.todoId = newId ~~
//이건 필요 없음. 아래 클릭할 때마다 ++을 직접해주고 있기 때문에
this.fetchData()
}
},
mounted() {
this.fetchData()
}
}
</script>
<template>
<p>Todo id: {{ todoId }}</p>
<button @click="todoId++">Fetch next todo</button>
<p v-if="!todoData">Loading...</p>
<pre v-else>{{ todoData }}</pre>
</template>
script
import ChildComp from './ChildComp.vue'
export default {
components: {
ChildComp
}
}
이제 template에서 사용할 수 있다
<ChildComp />
// in child component
export default {
props: {
msg: String
}
}
2.이후 child component에서 받을 때 사용할 수 있다
동적인 속성을 사용할 때는 부모 컴포넌트에서 v-bind로, 정적인 속성은 그냥 그대로
<ChildComp :msg="greeting" />
부모 컴포넌트
<script>
import ChildComp from './ChildComp.vue'
export default {
components: {
ChildComp
},
data() {
return {
childMsg: 'No child msg yet'
}
}
}
</script>
<template>
<ChildComp @response='(emit)=>childMsg =emit' />
//response가 이벤트 이름
//childMsg라는 부모가 설정해둔 변수로 이름이 들어간다
<p>{{ childMsg }}</p>
</template>
ChildComp
export default {
// declare emitted events
emits: ['response']
created() {
// emit with argument
this.$emit('response', 'hello from child')
//이벤트 이름, 나머지는 부모 컴포넌트의 이벤트 리스너로 넘어간다 (즉 아래 msg)
}
}
자식 컴포넌트의 children 값으로 넣은 텍스트가 ChildComp에서 보여진다
부모 컴포넌트
<template>
<ChildComp>slot content</ChildComp>
</template>
자식 컴포넌트
<template>
<slot></slot>
</template>
화면에 slot content라고 나온다