
const App = {
  data() {
    return {};
  },
};
<div id="app">
  
  <input :value="title" />
  <h1>{{ title }}</h1>
  
</div>
// main.js
const App = {
 data() {
  return {
  	title: 'Hello~'
   }
 }
}
현재, HTML의 title는 v-bind로 연결 한 것이다(약어 :)
이것은 단방향 데이터로 연결한 것인데, 화면에서 수정해도 데이터가 바뀌지 않는다. methods도 등록해줘야한다.
methods: {
  changeInput(event) {
    this.title = event.target.value;
  }
}
HTML 수정
<!-- 뷰 문법 내부에서 제공'하는 이벤트 객체 $event
이벤트를 쉽게 참조하는 방법인 $ -->
<input :value="title" @input="changeInput" />
하지만 반응형 데이터란? 데이터가 바뀌면 화면도 같이 바꿔줘야 한다.
자동으로 양방향으로 바꿔주는 디렉티브가 존재한다.
그것은  v-model 이다.
<input v-model="title"/>
위 코드 처럼 작성만 하면 메소드도 필요 없어지고 간편해진다. 꼭 수동으로 해야하는 경우 아니면 자동으로 양방향으로 되는 걸 사용해야된다.
사용자에게 데이터를 입력 받는 요소인 input
그런 input은 여러 타입이 존재한다. 파일, 라디오, 체크박스 등등..
<input type="checkbox" v-model="checked">
<input type="radio" name="yejin" value="H1" v-model="radio" />
<input type="radio" name="yejin" value="H2" v-model="radio" />
<h2>{{ radio }}</h2>
여기서 name속성은 지워줘도 된다 왜냐하면 같은 모델로 연결되고 있기 때문이다.
const App = {
  data() {
    return {
      title: 'Hello~',
      checked: true,
      radio: '',
    };
  },
};
Vue.createApp(App).mount('#app');
그런데 한국어, 중국어, 일본어를 입력 받을 때 v-model은 이슈가 있다.
IME (중국어, 일본어, 한국어 등)가 필요한 언어의 경우 IME 중
v-model이 업데이트 되지 않습니다. 이러한 업데이트를 처리하려면input이벤트를 대신 사용하십시오.
<input :value="title" @input="title = $event.target.value" />
<input v-model="title" />
두 줄의 코드 중 v-bind방식을 이용하면 된다.
.lazy
<!-- 수동 -->
<input :value="title" @change="title = $event.target.value" />
<!-- 자동 -->
<input v-model.lazy="title" />
      <h1>{{ title }}</h1>
.lazy 수식어를 사용한다면 실시간으로 바뀌지 않고 엔터를쳤거나, 값이 바뀌거나, input창에 블러(포커스 해제)되었거나 할 때 값이 바뀐다.
수동으로 만들면 @change이벤트랑 같다.(v-on)
.number
<input v-model.number="title" />
      <h1>{{ title }}</h1>
Number() 나 parseInt 같은 것이다.
템플릿상에서 형 변환 해주는거라서 편리하다.
.trim
양끝 공백 제거
전역 컴포넌트를 만드는 경우가 더 적다.
<input v-model="title" @keydown.enter="addTodo" />
-> 키보드의 enter키를 입력하면 addTodo 메소드가 실행된다고 먼저 html에 정의
const App = {
  data() {
    return {
      title: '',
      todos: [],
    };
  },
  methods: {
    addTodo() {
      // 타이틀이라는 데이터를 투두라는 빈배열에 밀어넣기 (데이터상)
      this.todos.push(this.title);
      // 타이틀 초기화
      this.title = '';
    },
  },
};
-> 배열 데이터를 화면에 출력할때 v-for를 쓸 수 있다.
<ul>
   <li v-for="todo in todos">
    {{ todo }}
   </li>
</ul>

그런데, v-for와 key는 세트이다. 현재 키 값은 지정해주지 않는데 키는 고유값이여한다. 마치 주민등록번호 처럼,
키 값에 index를 넣는건 최후의 방법이다. 기본적으로 사용하지 마라!. 정말 도저히 키 값을 채울 만한 마땅한 것이 없을 때, 순서를 바꿀 일 없을때는 사용한다.
여기서는 key에 고유한 id를 주기로 한다.
<ul>
  <li v-for="todo in todos" :key="todo.id">{{ todo.title }}
  </li>
</ul>
import { nanoid } from 'https://cdn.jsdelivr.net/npm/nanoid/nanoid.js'
const App = {
 data() {
    return {
      title: '',
      todos: [
        { id: nanoid(), title: 'ABC' },
        { id: nanoid(), title: 'XYZ' },
      ],
      editMode: false,
    };
  },
id: nanoid() methods: {
    addTodo() {
      if (!this.title.trim) {
        // 타이틀이 없으면 멈춰라
        return;
      }
      this.todos.push(this.title);
      this.title = '';
    },
  },
};
if(this.title.trim === '') 이렇게 사용할 수도 있겠지만, 간단히 if (!this.title.trim) 이렇게 사용할 수 있다.
공백은 falsy 인데, 부정연산자 !를 사용해서
빈문자(falsy)가 부정되어 true로 된다.
.trim 메소드를 사용해서 공백 입력을 막아준다.
<!-- deleteTodo를 호출할건데 삭제 버튼 눌렀을때 누른 todo가 객체로 들어온다. -->
<button @click="deleteTodo">삭제!</button>
삭제 버튼을 만들고, 사용자가 많은 항목 중 어떤 것을 지웠는지 알아내야한다.
참고로 데이터를 바꾸면 뷰가 알아서 지워주는 것을 화면까지 제어하지말자. 나는 데이터만 제어해주면 된다. 데이터에 맞게 화면이 출력되면 된다.(중요)
메소드 등록
// return 키워드 사용 
deleteTodo(todoToDelete) {
   this.todos.findIndex(todo => {
     return todo.id === todoToDelete.id
    })
   this.todos.splice(index, 1)
    }
// 간편화 + index 변수에 담아서 사용
deleteTodo(todoToDelete) {
     const index = this.todos.findIndex(todo => todo.id === todoToDelete.id)
     this.todos.splice(index, 1)
    }
this.todos.splice(index, 1)
배열에서 몇번째(인덱스 번호)인지 알아내서 하나 지우겠다.
this.todos.findIndex
몇 번째 인지 알아내는 방법  .findIndex
투두 데이터만 받아서는 텍스트를 바꿀수가 없다. 그 텍스트가 input요소로 바껴야하는 작업까지 필요함
<button @click="oneditMode">수정!</button>
수정! 버튼을 클릭하면 oneditMode를 실행하라
메소드 만들기
    onEditMode() {
      this.editMode = true;
    },
editMode모드가 true일때 실행.
컴포넌트 만들기?
현재 수정, 삭제 버튼은 li 태그 부분, 즉 투두가 만들어지는 개별적인 항목이다. 이부분을
캡슐화하는 것이 중요하다. 수정 할려면 전체 화면을 제어할 필요 없이 해당 하는 항목 부분만 제어하면 되는 것. 이럴때 컴포넌트가 필요하다.
컴포넌트 생성을 위해 맨 밑에 있는 코드에
app.component('todo-item', TodoItem);
추가
두번째 인수로 들어가는 자리에 변수 명을 입력하고, 따로 쓰면 훨씬 갈끔해짐. 컴포넌트 변수명은 대문자로 시작한다
// 대문자 시작 컴포넌트
const TodoItem = {
  template: /* HTML */ `
  <li>
  {{ todo.title }}
  <button @click="onEditMode">수정!</button>
  <button @click="deleteTodo">삭제!</button>
  </li>
  `,
  data() {
    return {
      // 유효범위는 이 컴포넌트 안임
      // App에 있는 타이틀은 그 컴포넌트에서만 사용하는것임
      // 이름 중복 상관 없음
      title: '컴포넌트'
    };
  },
  methods: {
    onEditMode() {
    },
    deleteTodo() {
    }
  }
};
const app = Vue.createApp(App);
// 컴포넌트는'todo-item' 이 이름으로 사용하면된다. 이름으로 html에 태그로 만든다.
app.component('todo-item', TodoItem);
app.mount('#app');
template 태그에 백틱기호를 사용해서 li부분을 안에 넣어준다.
<ul>
  <todo-item v-for="todo in todos" :key="todo.id" :yejin="todo"> </todo-item> </ul>
 태그로 원래 li태그가 있던 부분에 바꿔준다.
:yejin="todo"라고 적은 부분은 반복되는 todo라는 데이터를 통로로 밀어 넣을 수 있는데 통로 이름이 yejin인 것 이다.
todo는 객체데이터다. yejin은 반응형데이터라서 todo를 받아오고 곧 yejin=todo인 셈이다.
<ul>
  <todo-item v-for="todo in todos" :key="todo.id" :todo="todo"> </todo-item> 
</ul>
:to : 속성"todo" : 데이터 const TodoItem = {
  template: /* HTML */ `
    <li>
      <span v-if="!editMode">{{ todo.title }}</span>
      <input v-else v-model="todo.title" />
      <button @click="onEditMode">수정!</button>
      <button @click="deleteTodo">삭제!</button>
    </li>
  `,
  props: {
    todo: Object,
  },
 컴포넌트에 props를 추가해주는데 객체 데이터라 Object로 객체데이터라는 타입을 명시해준다.
 template도 위와 같이 수정해준다.
{{ todo.title }})한다.그런데, 중간에 아래 코드 처럼 쓰면 에러가 난다.
현재는 CDN으로 가져온 경우라 에러가 안나는 것 뿐.
<input v-else v-model="todo.title" />
v-model은 양방향 데이터다. 컴포넌트 사이에서 연결하는것은 양방향 데이터가 안된다.
todo-item 컴포넌트는 App의 자식 컴포넌트이다.
const App = {
 data() {
   return {
     title: '',
     todos: [
       { id: nanoid(), title: 'apc' },
       { id: nanoid(), title: 'xyz' },
     ],
     editMode: false,
   };
 },
todos 배열은 현재 부모 컴포넌트에 있다. 자식은 수정 권한이 없다. todo라는 데이터의 주인은 부모 컴포넌트이다. 즉 타이틀을 수정할려면 자식이 부모에게 요청을 해서 부모가 바꿔줘야 한다.
  자식 -> 부모: emits(하위 컴포넌트 이벤트 수신)
부모 -> 자식 : Props
일단 해당 부분은 아래코드로 변경한다.
// TodoItem 백틱 안 내용임
 <input v-else :value="todo.title" @input="inputTitle" />  inputTitle(event){
      // update-title 하면 타이틀 수정해달라고 요청 할 수 있음
      this.$emit('update-title', event.target.value)
    },
 $emit 사용해서 자식이 update-title라고 부모에게 요청 -> 커스텀 이벤트
근데 어떤 걸 수정해줄지 정해줘야함 event.target.value이걸로 수정할 값을 준다.
 <ul>
    <todo-item v-for="todo in todos" :key="todo.id" :todo="todo"
       @hello="todo.title = $event">
     </todo-item>
 </ul>
@hello="todo.title = $event"
이벤트 발생은 v-on (약어: @)
$event객체에 event.target.value 값이 들어온다. 자식 컴포넌트가 넣어준 값이며 부모는 이 값으로 타이틀을 갱신한다.
  
<button v-else @click="offEditMode">확인</button>
  
  // 부모 컴포넌트
  const App = {
  data() {
    return {
      title: '',
      todos: [
        { id: nanoid(), title: 'ABC' },
        { id: nanoid(), title: 'XYZ' },
      ],
  
  // 수정 권한은 부모에게 있다.(기본 값 false로 지정)
      editMode: false,
    };
  },
// -- 중략 --
  
 // 자식 컴포넌트 
const TodoItem = {
  template: /* HTML */ `
    <li>
 <!-- true가 되어 수정 input창에 내가 적었던 투두 타이틀들이 보인다. -->     
      <span v-if="!editMode"> {{ todo.title }} </span>
     
      <input v-else :value="todo.title" @input="inputTitle" />
     
 <!-- 수정 버튼을 클릭하면 기본값인 editMode가 부정되어 true가 된다.(수정 가능) -->
      <button v-if="!editMode" @click="onEditMode">수정!</button>
      
 <!-- 확인 버튼을 다시 true에서 기본값인 false로 된다.(수정 닫힘) -->
      <button v-else @click="offEditMode">확인!</button>
      <button @click="deleteTodo">삭제!</button>
    </li>
  `,
  props: {
    todo: Object,
  },
  data() {
    return {
      title: '컴포넌트',
      editMode: false,
    };
  },
  methods: {
    onEditMode() {
      this.editMode = true;
    },
    offEditMode() {
      this.editMode = false;
    },
    inputTitle(event) {
      this.$emit('update-title', event.target.value);
    },
    deleteTodo() {},
  },
};
  회고
간단한 투두 만들기 실습으로 컴포넌트가 필요한 이유와 컴포넌트 구조에 대해서 배울 수 있었다. 실시간으로 강의들으면서 나만 볼 수 있도록 필기해둔거라 군데 군데 부족한 부분이 많다.(아주 만약 읽으시는 분이 있다면 참고 부탁드립니다..😅) 컴포넌트의 필요성 1. 캡슐화 2. 재사용 잊지 말자!!!! 그리고 나는 데이터만 제어한다. 화면 출력은 뷰가 알아서하게끔 한다...중요중요