vue3

developer.do·2023년 4월 29일
0

1. 뷰에서 변수를 사용하는법

Template 부분에서는 {{변수}]를 적으면 선언&할당 했던 변수를 불러올수있음

<script setup>
const name = 'frank'
</script>

<template>
  <div>{{ name }}</div>
</template>

<style lang="scss" scoped>

</style>
// frank

2. 함수 또한 template로 표현이 가능하다.

<script setup>
const name = 'frank'
const greeting = () => {
  return 'hello'
}
</script>

<template>
  <div>{{ greeting() }}</div>
</template>

<style lang="scss" scoped>

</style>
// hello 출력

3. 함수의 인자로도 넘겨줄 수 있다.

<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 출력

4. 다시 변수로 할당을 해서 사용 할 수 있다.

<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가 출력됨

5. Event를 활용해보자

@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>

6. 지역변수

<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>

7. Click Event를 이용하여 변수의 값(value)을 변경 할 수 있다.

<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로 변경이됨

8. v-bind를 이용해서 input의 value값을 설정 할 수 있다.

<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>

9. Click 이벤트를 통해서 버튼을 누르면 색상을 변경 할 수 있다.


<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>


10. v-model로 양방향 바인딩을 할 수 있다.

<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로 변경이 된다.

11. TODOLIST를 만들어보자(1)

<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>

12. TODOLIST를 만들어보자(2)

<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>

13. TODOLIST를 만들어보자(3)



<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>

14. TODOLIST를 만들어보자(4)

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>

15. TODOLIST를 만들어보자(5)

  • todolist의 completed 연결하기

<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>

16. 스타일바인딩 CSS 효과 주기

<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>

17. TODOLIST를 만들어보자(6)

  • 배열에서 항목 삭제하기
<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>
      

18. TODOLIST를 만들어보자(7)

  • emit 상태관리 배우기
  • 자식컴포넌트에서 부모컴포넌트로 객체를 옮기기

자식컴포넌트

<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>

19. TODOLIST를 만들어보자(8)

  • props 상태관리 배우기
  • 부모컴포넌트에서 자식컴포넌트로 객체를 옮기기

부모컴포넌트

<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>

20. TODOLIST를 만들어보자(9)

  • props 사용 시 v-model 보다는 :value 값을 바꿔보자
자식컴포넌트

<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>

21. TODOLIST를 만들어보자

  • emit
<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>

0개의 댓글