Mixins & Composition API

Heena·2022년 8월 13일
1

Vue3-Project

목록 보기
2/2

Mixins

Mixins은 여러 컴포넌트 간에 공통으로 사용하고 있는 로직, 기능들을 재사용하는 방법이다. Mixins컴포넌트의 옵션과 동일한 옵션들을 모두 정의할 수 있다. 컴포넌트가 Mixins를 사용하면, Mixins의 모든 옵션이 컴포넌트 자체 옵션으로 혼합된다. 중복된 옵션이 있는 경우, 적절한 방법을 사용해서 병합된다.

  • Mixins의 data로부터 얻어진 속성과
    컴포넌트의 data로부터 얻어진 속성의 이름이 충돌하는 경우,
    컴포넌트의 이름이 우선권을 가진다.
const myMixin = {
	data() {
      return {
        message: 'hello',
        foo: 'abc'
      }
    }
};

const app = Vue.createApp({
	mixins: [myMixin],
	data() {
      return {
        message: 'goodbye',
        bar: 'def'
      }
    },
  	created() {
      console.log(this.$data)      
      // => {message:"goodbye", foo: "abc", bar: "def"}
    }
});
  • 같은 이름의 훅 함수가 있을 경우, 모두 호출될 수 있도록 배열에 병합되며 Mixins 훅은 컴포넌트 자체 훅이 호출되기 전에 호출된다. (Mixins 훅 호출 => 컴포넌트 훅 호출)
const myMixin = {
  created() {
    	console.log('mixin hook called');
  }
};

const app = Vue.createApp({
  mixins: [myMixin],
  created() {
    console.log('component hook called');
  }
});

// => "mixin hook called"
// => "component hook called"
  • methods, components, directives 같은 객체에 충돌하는 키가 있을 경우, 컴포넌트의 옵션이 우선순위를 갖는다.
const myMixin = {
  methods: {
    foo() {
      	console.log('foo');
    },
    conflicting() {
      	console.log('from mixin');
    }
  }
};

const app = Vue.createApp({
  mixins: [myMixin],
  methods: {
    bar() {
      console.log('bar');
    },
    comflicting() {
      console.log('from self');
    }
  }
});

const vm = app.mount('#mixins-basic')

vm.foo() // => "foo"
vm.bar() // => "bar"
vm.conflicting() // => "from self"

Mixins 사용 예시

다이얼로그(모달 혹은 팝업 창)의 열기, 닫기 로직을 Mixins에 정의했다.

  • mixins.js
var DialogMixin = {
  data() {
    return {
      dialog: false;
    };
  },
  methods: {
    showDialog: {
      this.dialog = true;
    },
    closeDialog: {
      this.dialog = false;
    }
  }
};

컴포넌트에 DialogMixin이 주입되었기 때문에 closeDialog 메서드가 LoginForm 컴포넌트에 없더라도 주입된 closeDialog 메서드를 사용할 수 있다.

  • LoginForm.vue
import { DialogMixin } from './mixins.js';

export default {
  // ...
  mixins: [DialogMixin],
  methods: {
    submitForm() {
      axios.post('login', {
        id: this.id,
        pw: this.pw
      }).then(() => this.closeDialog())
      .catch((error) => new Error(error));
    }
  }
}

Mixins 한계

Vue 2에서는 Mixins은 컴포넌트 로직을 재사용할 수 있게 만드는 주 도구였지만, 병합으로 인한 잦은 충돌속성 파악에 여러움이 있었고, 논리 변경을 위해 매개 변수를 Mixins에 전달할 수 없었기 때문에 논리를 추상화할 때 유연성이 떨어져 재사용성이 제한되었다. 이런 문제 해결을 위해 Vue 3에서는 Composition API를 추가했다.

Composition API

Composition API는 옵션을 선언하는 것 대신 가져온 함수를 사용하여 Vue 컴포넌트를 작성할 수 있는 API이다. 기존에 사용하던 Option API를 사용해서 논리 구조를 분리하고 재사용 가능하도록 하는 것을 목적으로 만들어졌다.

Vue 2까지 사용하던 Mixins를 활용하여 코드를 재사용할 수 있었으나 병합으로 인해 발생하는 여러 가지 문제로 인해 Vue 3 추가되었다. Composition API는 Vue 3 내장 기능이지만 현재 공식적으로 유지 관리되는 @vue/composition-api 플러그인을 통해 Vue 2에서도 사용할 수 있다.

Composition API는 다음 API를 포괄하는 상위 용어이다.

  • Reactivity API
    : ref()reactive()를 사용하여 반응 상태(reactive state), 계산 상태(computed state), 감시자(watchers)를 직접 생성할 수 있다.
  • Lifecycle Hooks
    : onMounted()onUnmounted()를 사용하여 프로그래밍 방식으로 컴포넌트의 생명주기에 연결할 수 있다.
  • Dependency Injection
    : provide()inject()를 사용하여 Reactivity API를 사용하는 동안 Vue의 의존성 주입 시스템을 활용할 수 있다.

setup 컴포넌트 옵션은 Composition API의 진입점 역할을 한다. 컴포넌트가 생성되기 전에, props가 한번 resolved될 때 실행된다.

setup이 실행될 때, 컴포넌트 인스턴스가 아직 생성되지 않아 setup 옵션 내에 this가 존재하지 않는다. 즉, props를 제외하고 컴포넌트 내 다른 속성에 접근할 수 없다.

  • setup 함수 사용 예시
<script>
  import { ref, onMounted } from 'vue';
  
  export default {
  	setup() {
      const count = ref(0);

      function increment() {
        count.value ++;
      }

      onMounted(() => {
        console.log(`The initial count is ${count.value}.`);
      }
  
  	  return {
  		count,
  		increment
      }
    }
  });
</script>

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

Vue 3에서 Composition API는 주로 Single-File Components의 <script setup> 구문과 함께 사용된다.

  • script setup 사용 예시
<script setup>
  import { ref, onMounted } from 'vue';
  
  const count = ref(0);
  
  function increment() {
  	count.value ++;
  }
  
  onMounted(() => {
  	console.log(`The initial count is ${count.value}.`);
  });
</script>

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

Composition API 사용 예시

  • utils.js
import { ref } from 'vue';

export default DialogUtil = () => {
  const dialog = ref(false);
  const showDialog = () => {
    dialog.value = true;
  };
  
  const closeDialog = () => {
    dialog.value = false;
  };
  
  return { dialog, showDialog, closeDialog };
};
  • LoginForm.vue
import { DialogUtil } from './utils.js';

export default {
  setup() {
    const { closeDialog } = DialogUtil();
    const submitForm = () => {
      axios.post('login', {
        id: this.id,
        pw: this.pw
      }).then(() => closeDialog())
      .catch((error) => new Error(error));
    };
    
    return {
      submitForm
    };
  }
}
profile
Hello, I am Heena :)

0개의 댓글