vue3 composition api mixin

vue3 composition api로 mixin 대체하기

  • 고민 상황
    여러 페이지에서 사용할 보험종류, 보험회사, 취급자 셀렉트 박스의 옵션명을 하나의 파일에서 관리하고 싶었음. 이는 이전에도 mixins를 통해 해결했으므로 그 방법으로 해결 시도. 그런데 composition api에서는 어떻게 쓰는걸까..?

vue2 option api mixins 용례

// MyMixin.js
export default {
  data: () => ({
    mySharedDataProperty: null
  }),
  methods: {
    mySharedMethod () { ... }
  }
}
// ConsumingComponent.js
import MyMixin from "./MyMixin.js";

export default {
  mixins: [MyMixin],
  data: () => ({
    myLocalDataProperty: null
  }),
  methods: {
    myLocalMethod () { ... }
  }
}

1. name 중복 이슈!

const mixin = {
  data: () => ({
    myProp: null
  })
}

export default {
  mixins: [mixin],
  data: () => ({
    // same name!
    myProp: null
  })
}

2. implicit dependency 이슈!

const countDownMixin = {
  data() {
    return {
      countDown: 10,
      interval: null,
    };
  },
  computed: {
    isDone: function () {
      return this.countDown <= 0;
    },
  },
  methods: {
    decrement() {
      if (this.countDown > 0) this.countDown -= 1;
    },
  },
  mounted: function () {
    this.interval = setInterval(this.decrement, 1000);
  },
  unmounted: function () {
    clearInterval(this.interval);
  },
};

export default countDownMixin;
- countDown을 20초로 바꾸고 싶다면...
<template>
  <div>
  <h1 v-if="!isDone">Countdown: {{ countDown }} seconds</h1>
  <h1 v-else>Hello World</h1>
  </div>
</template>

<script>
import countDownMixin from "./countDownMixin";
export default {
  name: "HelloWorld",
  mixins: [countDownMixin],
  data(){
  return {countDown:20}
  }
};
</script>
- composition api 방식
import { ref, computed, onMounted, onUnmounted, readonly } from "vue";

export default function useCountDown(countDownDuration = 10) {
  const countDown = ref(countDownDuration);
  const interval = ref(null);
  const decrement = () => {
    if (countDown.value > 0) countDown.value -= 1;
  };
  const isDone = computed(() => {
    return countDown.value <= 0;
  });
  onMounted(() => {
    interval.value = setInterval(decrement, 1000);
  });
  onUnmounted(() => {
    clearInterval(interval.value);
  });

  return { countDown:readonly(countDown), isDone };
}
- composition api 방식
<template>
  <div>
  <h1 v-if="!isDone">Countdown: {{ countDown }} seconds</h1>
  <h1 v-else>Hello World</h1>
  </div>
</template>

<script>
import useCountDown from "./useCountDown";
export default {
  name: "HelloWorld",
  setup(){
  const {countDown, isDone} = useCountDown(20);
  return {countDown, isDone};
  }
};
</script>

암시적 의존성도 결국 name 중복에서부터 나오는거구나...

참조 링크

좋은 웹페이지 즐겨찾기