일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
- 카카오
- C++
- 프로그래머스
- 배열
- Level3
- 리트코드
- 자바스크립트
- 웹프로그래밍
- sql
- Doitvue.js입문
- OS
- typescript
- dp
- VUE
- javascript
- Medium
- python
- react
- 백준
- Level1
- LeetCode
- 프로그래밍
- 파이썬
- 코테연습
- 동적계획법
- Level2
- CS
- web
- 고득점Kit
- 리액트
- Today
- Total
[vue] Vue.js tutorial 본문
https://vuejs.org/tutorial/#step-1 읽고 정리한 내용
Vue.js tutorial
Getting Started
SFC(Vue Single File Component)는 HTML, CSS, JS가 함께 캡슐화된 재사용 가능한 코드블럭으로서 .vue 안에 쓰인다.
Vue의 가장큰 특징은 declarative rendering으로 template 태그를 이용해 HTML를 확장하여 js state에 따라 HTML이 자동으로 업데이트 되도록 할 수 있다는 점이다.
<script>
export default {
data() {
return {
msg: 'Hello Word!'
}
}
}
</script>
<template>
<h1>{{msg}}</h1>
</template>
{{}} 를 이용해 dynamic text를 렌더링할 수 있고 state명이 아니라 자바스크립트 표현식을 써도 된다.
Attribute Bindings
{{}}는 단순히 텍스트를 삽입하기 위함이고 dynamic value를 바인딩하려면 v-bind를 사용해야한다.
<div v-bind:id="dynamicId"></div>
아래와 같이 생략할 수 있다.
<div :id="dynamicId"></div>
Event Listeners
DOM event를 바인딩할 때에는 v-on을 사용한다.
<button v-on:click="increment">{{ count }}</button>
아래와 같이 생략할 수 있다.
<button @click="increment">{{ count }}</button>
methods 옵션에 이벤트 함수를 선언하면 된다.
<script>
export default {
data() {
return {
count: 0
}
},
methods: {
increment() {
this.count++
}
}
}
</script>
<template>
<!-- make this button work -->
<button @click="increment">count is: {{ count }}</button>
</template>
Form Bindings
v-bind, v-on을 한 번에 바인딩하기 위해서는 v-model를 사용한다. v-model에 바인딩된 state는 e.target.value에 따라 자동으로 업데이트 된다. text input 외에 checkbox나 radio button도 가능하다
<input v-model="text">
Conditional Rendering
조건부 렌더링은 v-if를 이용한다. 이외에 v-else, v-else-if가 있다.
<h1 v-if="awesome">Vue is awesome!</h1>
<h1 v-else>Oh no 😢</h1>
List Rendering
v-for를 이용해서 리스트를 렌더링할 수 있다. 각각의 요소들에는 key attribute를 바인딩하여 unique id를 부여한다.
list를 업데이트하는 것으로 삽입, 삭제를 구현할 수 있다.
<script>
// give each todo a unique id
let id = 0
export default {
data() {
return {
newTodo: '',
todos: [
{ id: id++, text: 'Learn HTML' },
{ id: id++, text: 'Learn JavaScript' },
{ id: id++, text: 'Learn Vue' }
]
}
},
methods: {
addTodo() {
this.todos.push({ id: id++, text: this.newTodo })
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 todos" :key="todo.id">
{{ todo.text }}
<button @click="removeTodo(todo)">X</button>
</li>
</ul>
</template>
computed Property
state에 따라 다른 리스트 아이템을 렌더링하고 싶을 때 computed property를 사용한다. compute 옵션을 사용해서 작성할 수 있다.
dependecy가 변경될 때마다 새로 리턴한다.
export default {
// ...
computed: {
filteredTodos() {
return this.hideCompleted
? this.todos.filter((t) => !t.done)
: this.todos
}
}
}
to-do list 업그레이드
<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.filter((t) => !t.done)
: this.todos
}
},
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>
Lifecycle and Template Refs
reactivity, declarative 렌더링을 통해서 Vue가 자동으로 DOM을 업데이트해주지만 불가피하게 직접 DOM에 접근해야할 때가 있다. 이때 ref attribute를 사용한다.
<p ref="p">hello</p>
this.$refs.p로 접근이 가능해졌다. 하지만 해당 컴포넌트가 마운트된 이후에만 접근이 가능하다.
마운트 이후에 코드를 실행하기 위해서 mount 옵션을 사용하며 이를 lifecycle hook이라고 한다. Vue는 아래와 같은 life cycle을 가진다.
<script>
export default {
mounted() {
this.$refs.p.textContent = 'mounted!'
}
}
</script>
<template>
<p ref="p">hello</p>
</template>
Watchers
side effects를 reactive하게 해야할 때가 있다. 예를 들면 콘솔에 번호가 바뀔 때마다 로깅한다던지.. 이때 watcher를 사용할 수 있다.
side effects란 의도하지 않은 결과를 의미한다.
즉, 어떤 state의 값의 변화에 따른 callback을 작성할 수 있다.
<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()
}
},
mounted() {
this.fetchData()
},
watch: {
todoId() {
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>
위 코드를 보면Fetch next todo 버튼에서 click 이벤트가 발생할 때마다 todoId가 증가하고 todoId가 증가할 때마다 watch에서 fetchData를 실행한다.
Components
실제 뷰 어플리케이션은 중첩된 컴포넌트로 구성된다.
부모 컴포넌트에서는 다른 컴포넌트를 자신의 template 안에서 자식 컴포넌트로 사용할 수 있다.
- 사용할 자식 컴포넌트를 import 한다.
- components` 옵션에 자식 컴포넌트를 등록한다.
import ChildComp from './ChildComp.vue'
export default {
components: {
ChildComp
}
}
이후에 temple 안에서 사용할 수 있다.
<ChildComp />
Props
자식 컴포넌트들은 부모로부터 props를 받을 수 있다.
자식 컴포넌트에서는 받을 props 옵션을 통해 받을 props를 선언한다.
// in child component
export default {
props: {
msg: String
}
}
부모 컴포넌트는 attribute처럼 prop를 전달할 수 있다. dynamic value를 전달하기 위해서는 v-bind를 사용한다.
<ChildComp :msg="greeting" />
Emits
자식 컴포넌트는 부모에게 이벤트를 emit할 수 있다.
export default {
// declare emitted events
emits: ['response'],
created() {
// emit with argument
this.$emit('response', 'hello from child')
}
}
this.$emit의 첫 번째 인자는 이벤트 이름이며 나머지 argument들은 이벤트 리스너로 전달된다.
부모 컴포넌트에서는 자식의 emitted event를 v-on을 이용해 받고 가공할 수 있다.
<ChildComp @response="(msg) => childMsg = msg" />
Slots
부모 컴포넌트는 자식 컴포넌트로 template fragment를 내려보내기 위해서 slot을 사용할 수 있다.
자식 컴포넌트에서는 <slot>으로 slot content를 render할 수 있다. <slot> 의 안은 fallback으로 동작한다. 즉 부모로부터 아무런 slot도 오지 않았을 때에만 보인다.
//App.vue
<script>
import ChildComp from './ChildComp.vue'
export default {
components: {
ChildComp
},
data() {
return {
msg: 'from parent'
}
}
}
</script>
<template>
<ChildComp>
This is some slot content!
</ChildComp>
</template>
// ChildComp.vue
<template>
<slot>Fallback content</slot>
</template>
'Web > Vue' 카테고리의 다른 글
[Vue] 뷰 라우터 (Router, Nested Router, Named View) (0) | 2022.07.12 |
---|---|
[Vue] 뷰 컴포넌트 (props, emit, eventBus) (0) | 2022.07.07 |
[Vue] Vue 인스턴스, 라이프 사이클 (0) | 2022.07.07 |
[Vue] Vue.js란 (0) | 2022.07.07 |
[vue] 뷰.js에서 타입스크립트 사용하기 (0) | 2022.06.28 |