vue 3.0 reference 공부

2022. 03. 03.

tutorial

목표 : 이해가 아닌 읽을 줄 아는 것.
전제조건 : 기본 HTML, CSS, JavaScript는 알 것.

1) 선언형 랜더링(Declarative Rendering)

  • data()를 통해 전달된다.
  • 해당 reactive state를 받은 HTML에서는 JavaScript 표현식을 사용할 수 있다.

** {{}}를 mustaches -> 콧수염이라고 부름.

2) 속성 묶기(Attribute Bindings)

  • 속성에서는 mustaches를 사용하지 않는다. 해당 값은 텍스트 보간에서 사용한다.
  • 특별한 속성 선언은 v-로 시작한다. mustaches와 비슷하게 JavaScript 표현식을 사용할 수 있다.
  • : 이후에 붙는 값들은 argument를 의미한다.
<script>
export default {
  data() {
    return {
      titleClass: 'title'
    }
  }
}
</script>

<template>
  <h1 :class="titleClass">Make me red</h1>
</template>

<style>
.title {
  color: red;
}
</style>

3) Event Listeners

  • v-on을 통해서 DOM에 접근할 수 있다. v-on은 @로도 처리된다.
  • method에서는 this를 이용해서 컴포넌트 인스턴스에 접근할 수 있다.
<script>
export default {
  data() {
    return {
      count: 0
    }
  }, 
  methods: {
		increment() {
      this.count++; 
		}
  }
}
</script>

<template>
  <button @click="increment">count is: {{ count }}</button>
</template>

4) 형식 묶기(Form Bindings)

  • v-bind와 v-on을 함께 사용해 만드는 것을 v-model로 축약사용할 수 있다. 즉, 한번에 state랑 value를 엮어낼 수 있다.
  • input이외에도 checkbox, radio button, select dropdown 등...
<script>
export default {
  data() {
    return {
      text: ''
    }
  },
  methods: {
    onInput(e) {
      this.text = e.target.value
    }
  }
}
</script>

<template>
  <input v-model="text" placeholder="Type here">
  <p>{{ text }}</p>
</template>

5) 조건부 랜더링(Conditional Rendering)

  • v-if로 조건부 랜더링을 선언할 수 있다. v-else, v-else-if로 이어진다.
<script>
export default {
  data() {
    return {
      awesome: true
    }
  },
  methods: {
    toggle() {
      this.awesome = !this.awesome; 
    }
  }
}
</script>

<template>
  <button @click="toggle">toggle</button>
  <h1 v-if="awesome">Vue is awesome!</h1>
  <h1 v-else>Oh no 😢</h1>
</template>

6) List Rendering(리스트 랜더링)

  • 배열에 기초한 리스트 랜더링은 v-for을 사용한다.
<script>
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(ele=> ele !== todo); 
    }
  }
}
</script>

<template>
  <input v-model="newTodo" @keyup.enter="addTodo">
  <button @click="addTodo">Add Todo</button>
  <ul>
    <li v-for="todo in todos" :key="todo.id">
      {{ todo.text }}
      <button @click="removeTodo(todo)">X</button>
    </li>
  </ul>
</template>

** 실수한 부분 todos.filter(ele => ele !== todo) 해당함수는 새로운 배열을 반환하는 함수이므로 state에 바로 반영하고 싶으면 this.todos = this.todos.filter(ele => ele !== todo)로 해야한다.

7) 자동처리되는 속성(Computed Property)

  • computed :를 통해 처리
  • DB에서 trigger로 이해됨.(정확히 이해하지는 못했음.)
  • 필요에 따라 state에 붙이는 디자인으로 이해.
<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(ele=> !ele.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>
  <input v-model="newTodo" @keyup.enter="addTodo" />
  <button @click="addTodo">Add Todo</button>
  <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>

8) 주기와 탬플릿 참조(LifeCycle and Template Refs)

  • HTML에 있는 element를 참조할 수 있다. 다만 mounted한 이후 접근 가능하다.
  • 참조를 옳바로 사용하기 위해서는 LifeCylcle에 대한 이해를 요한다.
  • mounted() {} 이외에도 created, updated 등 lifecycle hook이 존재한다.
  • 참조는 해당 element에 ref를 선언한다. 그 이후 this.$ref.p로 사용한다.
<script>
export default {
  mounted() {
    this.$refs.p.textContent = "hello world!";
  }
}
</script>

<template>
  <p ref="p">hello</p>
</template>

9) 감시자(Watchers)

  • 때때로 side effect가 필요하다. 예를 들면 값이 변화할 때마다 콘솔에 출력하는 식으로
  • 특정 state에 대해서 업데이트될 때 특정 함수를 작동시키는 것.
  • 아래 예시는 todoId가 업데이트될 때마다 새로운 json을 출력받는다.
<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>

10) 컴포넌트(Components)

  • 지금까지 다루어 온 것들은 단일파일컴포넌트이다. 이번에는 nested Component를 다룬다.
  • script 필드에서 child component를 호출한다. import 작명 from '위치'. 그 이후 components라는 option을 추가한 이후 template 필드에 적용한다.
<script>
import ChildComp from './ChildComp.vue'
  
export default {
  components: {
    ChildComp
  }
}
</script>

<template>
  <ChildComp />
</template>

11) Props

  • 이전에 배운 child Component에 몇몇 선언을 한다. props option에 직접 선언한다. 그 이후 HTML에 :prop=""하여 적용한다.
<script>
import ChildComp from './ChildComp.vue'

export default {
  components: {
    ChildComp
  },
  props: {
    msg: String
  },
  data() {
    return {
      greeting: 'Hello from parent'
    }
  }
}
</script>

<template>
  <ChildComp :msg="greeting" />
</template>

12) 방출(Emits)

  • child component가 받은 것이 props라면 child component가 parent comopnent로 보내는 것이 emits이다.
  • 기본 array 형태를 띄며, 기본 이벤트이름이 this.$emit()이다. 어떤 Event Listener도 통과된다.
  • 기존 Event Listener처럼 v-on을 사용하고 @와 변경할 수 있다.
  • ref와 비슷한 특징이 눈에 띈다. 생성이후에 사용할 수 있고, $를 사용한다는 점 등등...
<script>
import ChildComp from './ChildComp.vue'

export default {
  components: {
    ChildComp
  },
  emits: ['response'],
  data() {
    return {
      childMsg: 'No child msg yet'
    }
  },
  created() {
    this.$emit('response', 'hello from child')
  }
}
</script>

<template>
  <ChildComp @response="(msg) => childMsg=msg"/>
  <p>{{ childMsg }}</p>
</template>

13) 슬롯(Slots)

  • parent component는 props이외에도 slot을 통해 값을 내려보낼 수 있다.
    조사
  • 컴포넌트 자체의 재사용성을 높인다.
<script>
import ChildComp from './ChildComp.vue'

export default {
  components: {
    ChildComp
  },
  data() {
    return {
      msg: 'from parent'
    }
  }
}
</script>

<template>
  <ChildComp>Message {{msg}}</ChildComp>
</template>
  • 이 챕터의 목표는 적응에 가까우니 자세하고 적용할만한 내용은 Main Guide에서 배운다.
profile
프론트엔드 개발자

0개의 댓글

Powered by GraphCDN, the GraphQL CDN