bgyoons / Study-with-me

0 stars 0 forks source link

Vue Compositions #41

Closed bgyoons closed 11 months ago

bgyoons commented 11 months ago

해당 학습 부분 목차

11주차 · 파트 04 [DAY 53] Vue (9)

학습 내용

// App.vue

<script setup lang="ts">
import { ref, onMounted, computed, watch, reactive } from 'vue';
import Component from './components/Component.vue';

// 원시형/참조형 데이터 타입
const count = ref(0);
const userRef = ref({
  name: 'yoon',
  age: 27,
});

// 참조형 데이터 타입
const user = reactive({
  // ref()를 사용하지 않아도 반응성을 가짐
  // .value를 사용하지 않아도 됨
  name: 'yoon',
  age: 27,
});

console.log('created app', document.querySelector('h1'));

const inputEl = ref<HTMLInputElement | null>(null);

onMounted(() => {
  console.log('mounted app', document.querySelector('h1'));
  if (inputEl.value) inputEl.value.focus();
});

// const double = computed(() => count.value * 2);
const double = computed({
  get() {
    return count.value * 2;
  },
  set(val: number) {
    count.value = val / 2;
  },
});

watch(count, (newValue, oldValue) => {
  console.log('watch count', newValue, oldValue);
});

// ref
watch(
  () => userRef.value.name, // 참조 객체의 특정한 속성만 감시할 때는 함수를 사용하여 반환해야 함
  (newValue, oldValue) => {
    console.log('watch userRef', newValue, oldValue);
  },
  { deep: true }, // 데이터 타입이 참조형이면 deep 옵션을 true로 설정해야 함
);

// reactive
watch(
  // () => user.name,
  () => user,
  (newValue, oldValue) => {
    console.log('watch user', newValue, oldValue);
  },
  // reactive는 deep 옵션을 사용하지 않아도 됨
);

const increase = () => {
  count.value += 1;
};

const assign = () => {
  double.value = 10;
};
</script>

<template>
  <button @click="increase">increase</button>
  <button @click="assign">assign</button>
  <h1>{{ count }}</h1>
  <h1>{{ double }}</h1>
  <Component
    modelValue="hello"
    name="yoon"
    active
  />
  <div>
    <input ref="inputEl" />
  </div>
</template>
// Component.vue

<script setup lang="ts">
import { useAttrs } from 'vue';

const attrs = useAttrs();

// 속성들이 최상위 요소에 바인딩되지 않도록 함
defineOptions({
  inheritAttrs: false,
});

// 기본값을 설정할 수 있음
const props = withDefaults(
  defineProps<{
    modelValue: string;
    name?: string;
    active?: boolean;
  }>(),
  {
    name: '',
    active: false,
  },
);
// const props = defineProps<{
//   modelValue: string;
//   name?: string;
//   active?: boolean;
// }>();

const emit = defineEmits(['update:modelValue']);

console.log('created', attrs, props);

const inputHandler = (e: Event) => {
  const target = e.target as HTMLInputElement;
  emit('update:modelValue', target.value);
};
</script>

<template>
  <label :class="{ active }">
    {{ name }}
    <input
      v-bind="$attrs"
      :value="modelValue"
      @input="inputHandler"
    />
  </label>
</template>

<style scoped>
.active {
  color: red;
}
</style>