Template 부분에서는 {{변수}]를 적으면 선언&할당 했던 변수를 불러올수있음
<script setup>
const name = 'frank'
</script>
<template>
<div>{{ name }}</div>
</template>
<style lang="scss" scoped>
</style>
// frank
<script setup>
const name = 'frank'
const greeting = () => {
return 'hello'
}
</script>
<template>
<div>{{ greeting() }}</div>
</template>
<style lang="scss" scoped>
</style>
// hello 출력
<script setup>
const name = 'frank'
const greeting = (name) => {
return `hello ${name}`
}
</script>
<template>
<div>{{ greeting('frank') }}</div>
</template>
<style lang="scss" scoped>
</style>
// hello frank 출력
<script setup>
const name = 'frank'
const greeting = (name) => {
return `hello ${name}`
}
const greet = greeting(name)
</script>
<template>
<div>{{ greet }}</div>
</template>
<style lang="scss" scoped>
</style>
// hello frank가 출력됨
@Click ="함수명"
v-on을 이용해서 버튼 이벤트와 함수를 연결 할 수 있다.
<script setup>
const name = 'frank'
const consoleLog = () => {
console.log('hello world')
}
</script>
<template>
<div>{{ name }}</div>
<button class="bg-red text-white p-3 rounded" @click="consoleLog">
Click
</button>
</template>
<style lang="scss" scoped>
// click 버튼을 누르면 hello world가 출력이 된다.
</style>
<script setup>
let name = 'frank'
const updateName = () => {
name = 'jenith'
console.log('지역변수', name) // frank가 아니라 jenith가 나옴
}
</script>
<template>
<div>{{ name }}</div>
<button class="bg-red text-white p-3 rounded" @click="updateName">
Click
</button>
</template>
<style lang="scss" scoped>
</style>
<script setup>
const name = ref('frank')
const updateName = () => {
name.value = 'jenith'
}
</script>
<template>
<div>{{ name }}</div>
<button class="bg-red text-white p-3 rounded" @click="updateName">
Click
</button>
</template>
<style lang="scss" scoped>
</style>
// frank에서 jenith로 변경이됨
<script setup>
const name = ref('jenith') // name의 기본 value를 jenith로 설정함
const updateName = () => {
name.value = 'frank'
}
</script>
<template>
{{ name }} // jenith -> frank (버튼을 누르면 바뀜)
<input :value="name" type="text"> // value에 변수값을 넣는다. jenith에서 클릭을 누르면 frank로 변경이 된다.
<button class="bg-red text-white p-3 rounded" @click="updateName">
Click
</button>
</template>
<style lang="scss" scoped>
</style>
<script setup>
const name = ref('jenith')
const nameClass = ref('name') // 가장먼저 nameClass 변수에 ref('name') 연결해준다.
// 여기서 name은 밑에 .name{color:red} 이다.
const updateName = () => { // updateName 함수를 실행하면, nameClass의 value가 name -> changeColor로 변경이 된다.
name.value = 'frank'
nameClass.value = 'changeColor'
}
</script>
<template>
<div :class="nameClass"> // 일단 v-bind:class="nameClass" 로 연결을 해준다.
{{ name }}
</div>
<input type="text" class="p-3">
<button class="bg-red text-white p-3 rounded" @click="updateName">
Click
</button>
</template>
<style lang="scss" scoped>
.name{
color:red
}
.changeColor{
color:yellow
}
</style>
<script setup>
const name = ref('jenith')
const nameClass = ref('')
const onSubmit = () => {
name.value = 'frank'
}
</script>
<template>
<input v-model="name" type="text" class="p-10 mb-300 mt-50">
<button class="bg-red text-white p-10 rounded" @click="onSubmit">
Click
</button>
</template>
<style lang="scss" scoped>
</style>
input value 값의 기존이 jenith에서 버튼을 클릭하면 frank로 변경이 된다.
<script setup>
const todo = ref('')
const todos = ref([])
const nameClass = ref('nameColor')
const onSubmit = () => {
todo.value = 'frank'
nameClass.value = 'nameColor2'
todos.value.push({
id: Date.now(),
subject: todo.value,
})
}
</script>
<template>
<h1 class=" mt-50 text-30px" :class="nameClass">
To-Do List
</h1>
<form class="flex justify-center " @submit.prevent>
<div>
<input v-model="todo" w-100 type="text" class="p-5" placeholder="Type new To-do">
</div>
<div>
<button class="bg-red text-white p-5 rounded" @click="onSubmit">
Add
</button>
</div>
</form>
{{ todos }}
</template>
<style lang="scss" scoped>
.nameColor{
color:red
}
.nameColor2{
color:blue
}
</style>
<script setup>
const todo = ref('') // 여기서 todo는 input과 연결한 변수로, input에 쓰는 값이 나온다.
const todos = ref([ // todos는 각각의 객체를 가진 배열이다.
{
id: 1,
subject: '공부하기',
},
{
id: 2,
subject: '놀기',
},
])
const onSubmit = () => { // 해당함수를 실행하면, todos 배열에 id와 subject가 각각 추가된다.
todos.value.push({
id: Date.now(),
subject: todo.value,
})
todo.value = ''
}
</script>
<template>
<h1 class=" mt-50 text-30px">
To-Do List
</h1>
<form class="flex justify-center " @submit.prevent>
<div>
<input v-model="todo" w-100 type="text" class="p-5" placeholder="Type new To-do">
</div>
<div>
<button class="bg-red text-white p-5 rounded" @click="onSubmit">
Add
</button>
</div>
</form>
{{ todos[0].subject }}
</template>
<style lang="scss" scoped>
</style>
<script setup>
const todo = ref('')
const todos = ref([
])
const onSubmit = () => {
todos.value.push({
id: Date.now(),
subject: todo.value,
})
todo.value = ''
}
</script>
<template>
<h1 class=" mt-50 text-30px mb-10">
To-Do List
</h1>
<form class="flex justify-center " @submit.prevent>
<div>
<input v-model="todo" w-100 type="text" class="p-5" placeholder="Type new To-do">
</div>
<div>
<button class="bg-red text-white p-5 rounded" @click="onSubmit">
Add
</button>
</div>
</form>
<div v-for="todo in todos" :key="todo.id"> // v-for 반복문을 돌려보자
<div class="bg-white text-black p-3 rounded text-20px w-128 mx-auto mt-10">
{{ todo.subject }} // todo의 subject만 쳐도 바로바로 새로운 todo가 나옴
</div>
</div>
</template>
<style lang="scss" scoped>
</style>
v-show는 display:none이 생긴다.
v-if 는 아예 사라진다.
그럼 어떨 때 각각 사용할까?
-> 랜더링의 차이가 있다고 보면 됨
<script setup>
const todo = ref('')
const todos = ref([])
const hasError = ref(false) // validation
const onSubmit = () => {
if (todo.value === '') { hasError.value = true } // todo의 input 입력값이 빈칸이라면 hasError의 값을 false -> true로 변경해라
else {
todos.value.push({
id: Date.now(),
subject: todo.value,
})
hasError.value = false
todo.value = ''
}
}
</script>
<template>
<h1 class=" mt-50 text-30px mb-10">
To-Do List
</h1>
<form class="flex justify-center" @submit.prevent>
<div>
<input v-model="todo" w-100 type="text" class="p-5" placeholder="Type new To-do">
</div>
<div>
<button class="bg-red text-white p-5 rounded" @click="onSubmit">
Add
</button>
</div>
</form>
<div v-if="hasError" class="text-red mt-5">
투두를 입력해주세요.
</div>
<div v-for="todo in todos" :key="todo.id">
<div class="bg-white text-black p-3 rounded text-20px w-128 mx-auto mt-5">
{{ todo.subject }}
</div>
</div>
</template>
<style lang="scss" scoped>
</style>
<script setup>
const todo = ref('')
const todos = ref([])
const hasError = ref(false)
const onSubmit = () => {
if (todo.value === '') { hasError.value = true }
else {
todos.value.push({
id: Date.now(),
subject: todo.value,
completed: false,
})
hasError.value = false
todo.value = ''
}
}
</script>
<template>
<h1 class=" mt-50 text-30px mb-10">
To-Do List
</h1>
<form class="flex justify-center" @submit.prevent>
<div>
<input v-model="todo" w-100 type="text" class="p-5" placeholder="Type new To-do">
</div>
<div>
<button class="bg-red text-white p-5 rounded" @click="onSubmit">
Add
</button>
</div>
</form>
<div v-if="hasError" class="text-red mt-5">
투두를 입력해주세요.
</div>
<div v-for="todo in todos" :key="todo.id">
<div class="bg-white text-black p-3 rounded text-20px w-128 mx-auto mt-5">
<input v-model="todo.completed" type="checkbox"> // todo.completed를 v-model을 통해 연결을 했다.
<label />
{{ todo.subject }}
</div>
</div>
</template>
<style lang="scss" scoped>
</style>
<script setup>
const todoStyle = {
textDecoration: 'line-through',
color: 'gray',
}
</script>
<template>
<div v-for="todo in todos" :key="todo.id">
<div class="bg-white text-black p-3 rounded text-20px w-128 mx-auto mt-5">
<input v-model="todo.completed" type="checkbox">
<label :style="todo.completed ? todoStyle : {}"> // 여기서 todo.completed의
// 값이 true면 todoStyle 효과를 주고, false 이면 {} 그대로 나오게해라 뜻임
{{ todo.subject }}
</label>
</div>
</div>
</template>
<style lang="scss" scoped>
</style>
<div v-for="todo in todos" :key="todo.id">
<div class="bg-white text-black p-3 rounded text-20px w-128 mx-auto mt-5">
<input v-model="todo.completed" type="checkbox">
<label :class="{ todo: todo.completed }"> // 여기서 todo.completed의 값이
// true일 떄 todo의 효과를 준다는 뜻임
{{ todo.subject }}
</label>
</div>
</div>
</template>
<style lang="scss" scoped>
.todo{ // 먼저 효과를 적어주고
color:gray;
text-decoration: line-through;
}
</style>
<script setup>
const deleteTodo = (index) => { // 2. deleteTodo 파라미ㅓㅌ에 index를 넣어주고
todos.value.splice(index, 1) // 3. 여기서 index를 연결시켜준다. 그리고 todos(배열에서) splice 를 통해 삭제를 해준다.
}
<div v-for="(todo, index) in todos" :key="todo.id">
<div>
<button @click="deleteTodo(index)"> // 1. 먼저 삭제 버튼에 deleteTodo(index) 함수를 연결해주고. index를 인자로 넣어주자.
DELETE
</button>
자식컴포넌트
<script>
export default {
setup(props, context) { // 1. 자식 -> 부모로 보낼 때 context가 필요함
const addTodo = () => {
if (todo.value === '') { hasError.value = true }
else {
context.emit('add-Todo', { // 2. event 이름을 적어주고(add-Todo),
id: Date.now(), // 올려주고 싶은 데이터를 넣어주면됨
subject: todo.value,
completed: false,
})
hasError.value = false
todo.value = ''
}
}
return {
todo, hasError, addTodo,
}
},
}
</script>
<div>
<button class="bg-red text-white p-5 rounded" @click="addTodo">
Add
</button>
</style>
부모컴포넌트
<script setup>
const addTodo = (todo) => { // 여기 인자 todo에 자식컴포넌트에서 받아온 data가 들어감
console.log(todo)
todos.value.push(todo)
}
</script>
<template>
<TodoSimpleForm @add-Todo="addTodo" />
<!-- 3. props랑 비슷함 add-Todo(이름)="onSubmit 으로 가져옴") -->
</template>
부모컴포넌트
<script setup>
import TodoSimpleForm from './TodoSimpleForm.vue'
import TodoList from './TodoList.vue'
const todos = ref([]) // 요놈을 자식컴포넌트로 보낼꺼임
const addTodo = (todo) => {
console.log(todo)
todos.value.push(todo)
}
</script>
<template>
<TodoList :todos="todos" /> <!--todos를 자식컴포넌트로 보내보자, :내가지은 이름 ="원하는데이터" -->
</template>
자식컴포넌트
<script>
export default {
props: ['todos'], // 이렇게 'todos'(내가 지은이름) 을 받아오면 바로 todos 사용이 가능함
}
</script>
<template>
<div v-for="(todo, index) in todos" :key="todo.id">
<!-- 여기서 todos는 부모컴포넌트에 있기 때문에 props로받아야함 -->
<div class="bg-white text-black p-3 rounded text-20px w-128 mx-auto mt-5 flex justify-between">
<input v-model="todo.completed" type="checkbox">
<label :class="{ todo: todo.completed }">
{{ todo.subject }}
</label>
<div>
<button @click="deleteTodo(index)">
DELETE
</button>
</div>
</div>
</div>
</template>
<style>
</style>
자식컴포넌트
<div v-for="(todo, index) in todos" :key="todo.id">
1 --- <input v-model: todo.completed> // 양방향 바인딩이기 때문에 v-model이 아니라 v-bind를 사용해야 한다.
2 --- <input :value="todo.completed" type="checkbox" @change="toggleTodo(index)"> // v-bind 사용 및 toggle 함수를 사용한다.
자식컴포넌트
<script>
export default {
props: {
todos: {
type: Array,
required: true,
},
},
setup(props, context) { // 일단 여기서 context를 불러오고
const toggleTodo = (index) => { // toggleTodo를 생성한다. 변수는 index를 가져온다.
context.emit('toggle-todo', index) // context.emit을 통해서 이제 부모에게 보낼 준비를 하자. toggle-todo라는 이름으로 index를 부모에게 보내자
}
return {
toggleTodo,
}
},
}
</script>
<template>
<div>
<div v-for="(todo, index) in todos" :key="todo.id" class="mt-2">
<div class="bg-black p-2 w-148 mx-auto b-white b-1.5 flex justify-between items-center">
<input :value="todo.completed" type="checkbox" @change="toggleTodo(index)">
<label :class="{ todo: todo.completed }">{{ todo.subject }}</label>
<button class="text-black bg-white p-2 rounded" @click="deleteTodo(index)">
Delete
</button>
</div>
</div>
</div>
</template>
<style>
.todo{
color:gray;
text-decoration: line-through;
}
</style>
부모컴포넌트
<script>
import TodoList from './TodoList.vue'
import TodoSimpleForm from './TodoSimpleForm.vue'
export default {
components: { TodoSimpleForm, TodoList },
setup() {
const todos = ref([])
const todoStyle = {
textDecoration: 'line-through',
color: 'gray',
}
const deleteTodo = (index) => {
todos.value.splice(index, 1)
}
const addTodo = (todo) => {
console.log(todo)
todos.value.push(todo)
}
const toggleTodo = (index) => {
todos.value[index].completed = !todos.value[index].completed
}
return {
todos,
todoStyle,
deleteTodo,
addTodo,
toggleTodo,
}
},
}
</script>
<script>
const toggleTodo = (index) => { // 자식 컴포넌트의 toggleTodo를 가져왔다. 여기서 인자에는 index를 담아보자
todos.value[index].completed = !todos.value[index].completed // 해당 상태값이 false라면 true로 바꿔라 대신 index는 내가 누른 걸 자식컴포넌트에서 여기로 가져옴
}
</script>
<template>
<div>
<h1>TodoList</h1>
<TodoSimpleForm @add-Todo="addTodo" />
<div v-if="todos.length === 0">
추가된 Todo가 없습니다.
</div>
<TodoList :todos="todos" @toggle-todo="toggleTodo" /> // 자식컴포넌트에서 가져온 toggle-todo를 부모컴포넌트에서는 toggleTodo라고 써보자
</div>
</template>
<style lang="scss" scoped>
</style>
<script>
export default {
props: {
todos: {
type: Array,
required: true,
},
},
setup(props, { emit }) { -> context 대신 emit을 넣고 구조분해를 한다.
const toggleTodo = (index) => {
emit('toggle-todo', index) -> context.emit에서 emit만 작성해도 된다.
}
const deleteTodo = (index) => {
emit('delete-todo', index)
}
return {
toggleTodo,
deleteTodo,
}
},
}
</script>
<template>
<div>
<div v-for="(todo, index) in todos" :key="todo.id" class="mt-2">
<div class="bg-black p-2 w-148 mx-auto b-white b-1.5 flex justify-between items-center">
<input :value="todo.completed" type="checkbox" @change="toggleTodo(index)">
<label :class="{ todo: todo.completed }">{{ todo.subject }}</label>
<button class="text-black bg-white p-2 rounded" @click="deleteTodo(index)">
Delete
</button>
</div>
</div>
</div>
</template>
<style>
.todo{
color:gray;
text-decoration: line-through;
}
</style>