TodoList.vue

이동언·2024년 8월 20일

new world

목록 보기
29/62
post-thumbnail

8.20(화)

1. v-bind

👉 하나의 컴포넌트에 속성을 주는것
👉 messeage라는 변수를 만들어서 컴포넌트에 달아놓으면 elemnets 에서 확인시에 변수에 대한 속성값이 주어진다.
👉 v-bind라고 사용하지않고 주로 :src="message"로 사용한다.

<template>
<MyNav></MyNav>
<div class="container">

<MyTitle></MyTitle>

<Counter2></Counter2>

<MyContent v-bind:src="message"></MyContent> <!--<div class="row g-3" src="[object Object]"-->

<MyFooter></MyFooter>

</div>
</template>

<script setup>
import MyNav from '../components/MyNav.vue';
import MyFooter from '../components/MyFooter.vue';
import MyTitle from '../components/MyTitle.vue';
import Counter2 from '../components/ex1/Counter2.vue';
import MyContent from '../components/MyContent.vue';

const message = {sender:'aaa'}

</script>

<style lang="scss" scoped>

</style>




2. props / emits

props

👉 상위 컴포넌트에서 하위 컴포넌트에게 속성값을 주어줬을때 props라는 변수에 할당

emits

👉 하위 컴포넌트에서 발생되는 이벤트에 대해 상위 컴포넌트에게 전달




3. UUID

👉 중복이 되지 않는 고유 식별자. TNO같은 느낌

📌 npm install uuid이 필요하다.

console.log(uuid4()); 출력하게 되면 해당 값이 출력이된다.

5d92a9e4-35dc-48bd-a011-89a7a28deb13




4. COUNTER 만들기

4-1. CounterButton1.vue

<template>
    <div>
        <button @click="changeCountPlus">+</button> <!--버튼을 클릭하면 plus이벤트 실행-->
        <button @click="changeCountMinus">-</button> <!--버튼을 클릭하면 minus이벤트 실행-->
    </div>
</template>

<script setup>

const emits = defineEmits(['changeCountB']) // changeCountB이벤트를 하위컴포넌트에서 상위컴포넌트로 전달

const changeCountPlus = () => {

    emits('changeCountB',1) // changeCountB이벤트의 인자로 1 을 반환한다
}

const changeCountMinus = () => {

    emits('changeCountB',-1) // changeCountB이벤트의 인자로 -1 을 반환한다
}


</script>

<style lang="scss" scoped>

</style>




4-2. CounterContainer1.vue

<template>
    <div>
        <CounterDisplay1 :countobj="countobj"></CounterDisplay1> <!--display에는 countobj를 출력 해야하니 display에서는 props로 받음-->
        <CounterButtons1 @changeCountB="changeCountC"></CounterButtons1> 
        <!--Button에서는 changeCountB이벤트가 발생하면 Container에서 ChangeCountC메소드 실행-->
    </div>
</template>

<script setup>
import { ref } from 'vue';
import CounterButtons1 from './CounterButtons1.vue';
import CounterDisplay1 from './CounterDisplay1.vue';

const countobj = ref({num:10})
// display에 표출될 숫자 default 값 10

const changeCountC = (amount) => {
    countobj.value.num = countobj.value.num + amount
    // Button의 이벤트가 발생하면 해당 인자를 amount에 할당하고 countobj의 값을 변경
}



</script>



<style lang="scss" scoped>

</style>




4-3. CounterDisplay1

<template>
    <div>
        <h1>{{ props.countobj.num }}</h1> 
        <!--아래 const props = defineProps(['countobj']) 를 하게되면 호출할때 props를 붙혀야하고-->
        <!--const {countobj} 로 직접 가져오게 되면 countobj.num을 해도 상관없다.-->
    </div>
</template>

<script setup>
const props = defineProps(['countobj']) //countobj라는 속성값을 props에 할당
</script>

<style lang="scss" scoped>

</style>




5. TODO LIST 프로젝트

5-1. TodoBox.vue

<template>
    <div>
        <h1>{{ props.title }}</h1> <!-- 저장된 pops의 title속성값을 출력-->
        <slot></slot>
    </div>
</template>

<script setup>
const props = defineProps(['title']) // 부모컴포넌트에서 받은 title속성값을 props에 저장

</script>

<style scoped>
div{
    border: 1px solid black;
    width: 50vw;
    min-width: 10vh;
    margin: 0.2em;
    padding: 0.3em;
}

</style>




5-2. TodoContainer.vue

<template>
    <div>
        <TodoInput @addTodoI="addTodoC"></TodoInput> 
        <!--TodoInput에서 @addTodoI라는 사용자 정의 이벤트가 발생될시 Container에 있는 addTodoC메서드가 호출된다.-->
        <TodoList :todoList="todoList" @removeTodosL="removeTodosC"></TodoList>
        <!--Container에 있는 todoList데이터를 TodoList.vue에다가 prop으로 전달한다. -->
        <!--TodoList에 있는 removeTodosL라는 사용자 이벤트가 발생될시 Container에 있는 removeTodosC메서드가 호출된다.-->
    </div>
</template>

<script setup>
import TodoInput from './TodoInput.vue';
import TodoList from './TodoList.vue';
import { ref } from 'vue';
import {v4 as uuid4} from 'uuid';

const todoList = ref([]) // TodoList에 저장될 값들을 빈 배열로 만들기

const addTodoC = (todo) => { // todoInput 에서 받은 인자값을 todo에 매개변수로 할당
    todo.tno = uuid4() // tno의 값은 uuid4를 통해서 독립적인 값을 생성하기
    todoList.value = [...todoList.value, todo] // 궁극적인 todoList의 값은 기존에 있던 todoList의 값에다가 매개변수로 받은 todo를 포함
}

const removeTodosC = (tnos) => { //todoList에서 받은 인자값을 tnos 매개변수로 할당

   todoList.value = todoList.value.filter(todo => !tnos.includes(todo.tno))
   // todoList의 궁극적인 값은 기존의 todoList값이 있을때, 매개변수로 받은(삭제될값들) tno값을 포함된 value들을 제외한 나머지의 todoList.value들이다.

}




</script>

<style lang="scss" scoped>

</style>




5-3. TodoInput.vue

<template>
    <TodoBox :title="'Input New Todo'">  <!--todoBox의 title속성에 Input New Todo의 값이 할당됨 / input이 부모 컴포넌트-->
        <input type="text" v-model="todoRef.title"> <!--title에 입력된 값이 todoRef에 자동으로 적용이 되는것.-->
        <input type="text" v-model="todoRef.content">
        <button @click="handleClick">ADD</button>
    </TodoBox>

</template>

<script setup>
import TodoBox from './TodoBox.vue';
import { ref } from 'vue';

const initState = {title:'', content:''}; // 초기화모델 만들어놓기

const emits = defineEmits(['addTodoI']) // 자식컴포넌트에서 부모컴포넌트로 이벤트를 전달

const todoRef = ref({...initState})  // todoRef라는 친구는 ref함수를 통해서 반응형 모델로 되는데, default값은 initState로 설정.

const handleClick = () => {
    console.log(todoRef.value)

    const todoParam = { // 부모에게 전달하기 좋게 1개의 파라미터인 todoParam객체를 생성해서 title, content를 넣는다.
        title: todoRef.value.title,
        content: todoRef.value.content
    }
    emits('addTodoI',todoParam) // addTodoI 이벤트가 발생되면서 인자값으로 todoParam이라는 객체를 전달

    todoRef.value = {...initState}

}

</script>

<style lang="scss" scoped>

</style>




5-4. TodoList.vue

<template>
    <TodoBox :title="'TodoList'">  <!--todoBox의 title속성에 TodoList의 값이 할당됨 / TodoList가 부모 컴포넌트-->
        <button @click="handleClickRemove">REMOVE</button>
        <ul>
            <li v-for="todo in props.todoList" :key="todo.tno"> <!--props의 todoList속성을 for문을 통해서 하나씩 추출-->
                    <input type="checkbox" :value="todo.tno" v-model="selectList"> {{ todo.title }} -- {{ todo.content }}
                    <!--각각의 list들을 todo로 할당해서 check버튼을 눌렀을때 tno값이 나오게되고, v-model을 통해 selectList와 같이 동기화-->
            </li>
        </ul>

    </TodoBox>
</template>

<script setup>
import { ref } from 'vue';
import TodoBox from './TodoBox.vue';

const selectList = ref([]) // 삭제하고싶은 데이터를 선택했을때 들어갈 배열을 만들어놓기

const props = defineProps(['todoList']) // Container에서 받은 todoList속성값을 props에 넣기
const emits = defineEmits(['removeTodosL']) // 자식컴포넌트에서 발생된 이벤트를 부모컴포넌트로 전달

const handleClickRemove = () => {
    if(selectList.value.length == 0){ // 선택된 값이 없으면 함수종료
        return
    }
    emits('removeTodosL',selectList.value) // removeTodosL이벤트를 발생시키면서 selectList.value 인자들을 Container의 removeTodosC 메소드의 매개변수로 전달
}

</script>

<style lang="scss" scoped>

</style>

0개의 댓글