본문 바로가기

FRONT/Vue.js

[Vue.js] Vue3 Composition API - life cycle

 

Composition API란?

Vue3가 나오고 Composition API 를 제공하고 있다.

Vue2와 유사하게 작동하지만, 해당 API를 사용할 경우 라이프 사이클 훅(Life cycle hook)에 대한 엑세스가 변경된다.

 

 

 

 

  • Vue3에서는 beforeCreate , createdsetup()이 대체하고 수행한다.
  • setup() 안에 life cycle methods에 on을 추가해 Call back hook 을 만들 수 있다.
  • beforeDestroy, destryoedbeforeUnmount, unmounted 로 변경 됐다.

Vue3 New Methods

 

● onRenderTracked

 

reactive dependency 가 렌더 함수에서 처음 접근 되었을 때 호출 된다.

추적 중인 dependency를 확인 할 때 사용한다.

 

● onRenderTriggered

 

새로운 렌더가 트리거 될 때 호출 된다.

어떤 dependency 가 컴포넌트를 재 렌더링했는지 검사 할 수 있다.(최적화)

 

Setup

hook 내부에 data 와 function 을 구성한다.

이 때 구성되는 data는 반응형이 아님.

 

<template>
  <div class="home">
    <p>{{ name }} {{ age }}</p>
    <button @click="handleClick">click</button>
  </div>
</template>
<script>
export default {
  name: "HOME",
  setup() {
    let name = "ogg";
    let age = 27;

    const handleClick = () => {
      console.log(1);
    };
    return { name, age, handleClick };
  }
};
</script>

 

 

반응형 data를 만들 때는 ref 와 reactive를 사용한다.

 

<template>
  <div class="home">
    <p>{{ person1.name }} {{ person1.value }}</p>
    <button @click="handleClick">click</button>
  </div>
</template>
<script>
import { ref, reactive } from "vue";

export default {
  name: "HOME",
  setup() {
    // ref, reactive를 사용하면 반응형으로 바꿀 수 있다.
    const person1 = ref({ name: "ogg", age: 27 });
    const person2 = reactive({ name: "qgg", age: 28 });

    const handleClick = () => {
      // ref 값을 변경할 때는 value를 통해 바꾼다.
      person1.value.age = 30;

      // reactive는 바로 변경한다.
      person2.age = 30;
    };

    // ref값은 return을 거치게되면 person1.value.age는 person1.age로 바뀝니다. (template에서는 person1.age로 사용합니다)
    return { person1, handleClick };
  }
};
</script>

 

ref , reactive 차이

 

ref는 값을 변경할 때 value를 통해 바꾸지만 reactive는 바로 변경할 수 있다.

reactive는 원시값은 반응형을 갖지 않는다.

- 객체, 배열을 사용하는 경우에만 사용할 수 있다.

ref는 원시값도 반응형 값으로 취급되어 재 렌더링 된다.

 

 

watchEffect

 

처음 컴포넌트가 렌더될 때 최초 1회 실행되며, 이후에는 watchEffect 내부에 사용 된 변수가 바뀔 때 마다 재실행된다.

watchEffect 함수를 변수로 지정하고 해당 변수를 실행하면 watch, watchEffect는 중지된다.

 

 

<template>
  <div class="home">
    <input type="text" v-model="search" />
    <p>{{ search }}</p>
    <div v-for="name in matchingNames" :key="name">
      {{ name }}
    </div>
    <button @click="handleClick">watchEffect 중지하기</button>
  </div>
</template>
<script>
import { computed, ref, watch, watchEffect } from "vue";

export default {
  name: "HOME",
  setup() {
    const search = ref("");
    const names = ref(["qq", "aa", "zz", "dd"]);

    const matchingNames = computed(() => {
      return names.valie.filter(name => name.includes(search.value));
    });

    const stopWatch = watch(search, () => {
      "search 값이 바뀔 때 마다 실행되는 함수";
    });

    const stopWatchEffect = watchEffect(() => {
      console.log(
        "search value가 정의됬기에 search가 바뀔때마다 실행된다",
        search.value
      );
    });

    const handleClick = () => {
      stopWatch();
      stopWatchEffect();
    };

    return { names, search, handleClick, matchingNames };
  }
};
</script>

 

 

utils 함수 재사용 - composable

 

Vue2 에서는 재사용을 위한 함수를 mixins에 포함시켜 사용했다.

함수가 추가 될 때 마다 데이터 추적이 어려워 확장성이 불리하였다.

Composition API를 사용함으로써 util 함수를 import, export 가능하게 되었고, 데이터 추적 및 사용이 쉽게 변경되었다.

Vue3 에서는 composable 이라고 부른다.

 

아래는 getLists라는 utils 함수를 이용해 컴포넌트에 사용하는 예시.

ref가 아닌 reactive 사용 시 return 에서 toRefs를 사용해야 반응성이 유지된다.

 

import { ref } from "vue";
const getLists = () => {
  const lists = ref([]);
  const error = ref(null);

  const load = async () => {
    try {
      // 예시 api
      let res = await fetch("http://localhost:8080/lists");
      if (!res.isSuccess) {
        throw Error("fail");
      }
      lists.value = await res.json();
    } catch (err) {
      error.value = err.message;
    }
  };

  return { lists, err, load };
};

export default getLists;

 

<template>
  <dlv class="home">
    <div v-if="error">{{ error }}</div>
    <div v-if="lists.length">
      <List :lists="lists" />
    </div>
    <div v-else>loading...</div>
  </div>
</template>
<script>
// 사용할 컴포넌트 import
import List from '../components/List.vue';
import getLists from '../composables/getLists';

export default {
  name: 'Home',
  components: { List },

  setup() {
    const { lists, error, load } = getLists();

    load();

    return { lists, error };
  };
}
</script>